From 799da2100e7a45ba36d6b24278a54119855bd1de Mon Sep 17 00:00:00 2001 From: arcum42 Date: Fri, 19 Mar 2010 00:31:15 +0000 Subject: [PATCH] zzogl-pg: Create a local fork of ZZOgl to play with. Currently just ZZOgl 211 with name and version changes. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2739 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/build.sh | 1 + plugins/zzogl-pg/build.sh | 32 + plugins/zzogl-pg/opengl/GS.h | 1228 ++ plugins/zzogl-pg/opengl/GSmain.cpp | 1603 ++ plugins/zzogl-pg/opengl/Linux/CMakeLists.txt | 8 + plugins/zzogl-pg/opengl/Linux/Conf.cpp | 110 + plugins/zzogl-pg/opengl/Linux/Linux.cpp | 441 + plugins/zzogl-pg/opengl/Linux/Linux.h | 26 + plugins/zzogl-pg/opengl/Linux/Makefile | 531 + plugins/zzogl-pg/opengl/Linux/Makefile.am | 10 + plugins/zzogl-pg/opengl/Linux/Makefile.in | 531 + plugins/zzogl-pg/opengl/Linux/buildgui.sh | 9 + plugins/zzogl-pg/opengl/Linux/callbacks.c | 34 + plugins/zzogl-pg/opengl/Linux/callbacks.h | 14 + .../zzogl-pg/opengl/Linux/cmake_install.cmake | 34 + plugins/zzogl-pg/opengl/Linux/interface.c | 392 + plugins/zzogl-pg/opengl/Linux/interface.h | 6 + plugins/zzogl-pg/opengl/Linux/support.c | 144 + plugins/zzogl-pg/opengl/Linux/support.h | 69 + plugins/zzogl-pg/opengl/Linux/zerogs.glade | 812 + plugins/zzogl-pg/opengl/Makefile.am | 50 + plugins/zzogl-pg/opengl/Mem.cpp | 902 + plugins/zzogl-pg/opengl/Mem.h | 487 + plugins/zzogl-pg/opengl/README.txt | 13 + plugins/zzogl-pg/opengl/Regs.cpp | 1061 + plugins/zzogl-pg/opengl/Regs.h | 101 + plugins/zzogl-pg/opengl/Win32/Conf.cpp | 89 + plugins/zzogl-pg/opengl/Win32/Win32.cpp | 251 + plugins/zzogl-pg/opengl/Win32/Win32.h | 9 + plugins/zzogl-pg/opengl/Win32/aviUtil.h | 488 + plugins/zzogl-pg/opengl/Win32/jconfig.h | 52 + plugins/zzogl-pg/opengl/Win32/jmorecfg.h | 363 + plugins/zzogl-pg/opengl/Win32/jpeglib.h | 1099 + plugins/zzogl-pg/opengl/Win32/libjpeg.lib | Bin 0 -> 470518 bytes plugins/zzogl-pg/opengl/Win32/libjpeg64.lib | Bin 0 -> 1010392 bytes plugins/zzogl-pg/opengl/Win32/ps2hw.dat | Bin 0 -> 108445 bytes plugins/zzogl-pg/opengl/Win32/resource.h | 45 + plugins/zzogl-pg/opengl/Win32/resrc1.h | 83 + .../opengl/Win32/tsvnrev/svnrev_template.h | 18 + .../opengl/Win32/tsvnrev/svnrev_unknown.h | 23 + .../opengl/Win32/tsvnrev/updateRevision.cmd | 8 + .../Win32/vsprops/pcsx2_plugin_common.vsprops | 34 + .../opengl/Win32/vsprops/postBuild.tmpl | 24 + .../opengl/Win32/vsprops/postBuild.unknown | 21 + .../opengl/Win32/vsprops/preBuild.cmd | 20 + .../opengl/Win32/vsprops/svnrev_template.h | 18 + .../opengl/Win32/vsprops/svnrev_unknown.h | 23 + plugins/zzogl-pg/opengl/Win32/wglext.h | 813 + plugins/zzogl-pg/opengl/Win32/zerogs.bmp | Bin 0 -> 921654 bytes plugins/zzogl-pg/opengl/Win32/zerogs.def | 37 + plugins/zzogl-pg/opengl/Win32/zerogs.rc | 227 + .../opengl/Win32/zerogsogl_2008.vcproj | 578 + plugins/zzogl-pg/opengl/Win32/zlib/adler32.c | 74 + plugins/zzogl-pg/opengl/Win32/zlib/compress.c | 79 + plugins/zzogl-pg/opengl/Win32/zlib/crc32.c | 311 + plugins/zzogl-pg/opengl/Win32/zlib/crc32.h | 441 + plugins/zzogl-pg/opengl/Win32/zlib/deflate.c | 1502 ++ plugins/zzogl-pg/opengl/Win32/zlib/deflate.h | 326 + plugins/zzogl-pg/opengl/Win32/zlib/gzio.c | 1005 + plugins/zzogl-pg/opengl/Win32/zlib/infback.c | 619 + plugins/zzogl-pg/opengl/Win32/zlib/inffast.c | 305 + plugins/zzogl-pg/opengl/Win32/zlib/inffast.h | 11 + plugins/zzogl-pg/opengl/Win32/zlib/inffixed.h | 94 + plugins/zzogl-pg/opengl/Win32/zlib/inflate.c | 1270 ++ plugins/zzogl-pg/opengl/Win32/zlib/inflate.h | 117 + plugins/zzogl-pg/opengl/Win32/zlib/inftrees.c | 321 + plugins/zzogl-pg/opengl/Win32/zlib/inftrees.h | 55 + plugins/zzogl-pg/opengl/Win32/zlib/trees.c | 1215 ++ plugins/zzogl-pg/opengl/Win32/zlib/trees.h | 128 + plugins/zzogl-pg/opengl/Win32/zlib/uncompr.c | 61 + plugins/zzogl-pg/opengl/Win32/zlib/zconf.h | 323 + plugins/zzogl-pg/opengl/Win32/zlib/zlib.h | 1200 ++ plugins/zzogl-pg/opengl/Win32/zlib/zutil.c | 319 + plugins/zzogl-pg/opengl/Win32/zlib/zutil.h | 258 + plugins/zzogl-pg/opengl/ZZoglCRTC.cpp | 821 + plugins/zzogl-pg/opengl/ZZoglCreate.cpp | 1098 + plugins/zzogl-pg/opengl/ZZoglFlush.cpp | 2627 +++ plugins/zzogl-pg/opengl/ZZoglSave.cpp | 152 + plugins/zzogl-pg/opengl/ZZoglShaders.cpp | 627 + plugins/zzogl-pg/opengl/ZZoglShoots.cpp | 552 + plugins/zzogl-pg/opengl/ZZoglVB.cpp | 450 + .../zzogl-pg/opengl/ZeroGSShaders/Makefile | 428 + .../zzogl-pg/opengl/ZeroGSShaders/Makefile.am | 2 + .../zzogl-pg/opengl/ZeroGSShaders/Makefile.in | 428 + .../zzogl-pg/opengl/ZeroGSShaders/ZLib.lib | Bin 0 -> 101154 bytes .../opengl/ZeroGSShaders/ZeroGSShaders.vcproj | 191 + .../ZeroGSShaders/ZeroGSShaders_2005.sln | 23 + .../ZeroGSShaders/ZeroGSShaders_2005.vcproj | 335 + .../opengl/ZeroGSShaders/copytozerogs.bat | 1 + .../opengl/ZeroGSShaders/zerogsshaders.cpp | 344 + .../opengl/ZeroGSShaders/zerogsshaders.h | 94 + .../opengl/ZeroGSShaders/zlib/crc32.h | 441 + .../opengl/ZeroGSShaders/zlib/deflate.h | 331 + .../opengl/ZeroGSShaders/zlib/inffast.h | 11 + .../opengl/ZeroGSShaders/zlib/inffixed.h | 94 + .../opengl/ZeroGSShaders/zlib/inflate.h | 115 + .../opengl/ZeroGSShaders/zlib/inftrees.h | 55 + .../opengl/ZeroGSShaders/zlib/trees.h | 128 + .../opengl/ZeroGSShaders/zlib/zconf.h | 332 + .../opengl/ZeroGSShaders/zlib/zconf.in.h | 332 + .../zzogl-pg/opengl/ZeroGSShaders/zlib/zlib.h | 1357 ++ .../opengl/ZeroGSShaders/zlib/zutil.h | 269 + .../zzogl-pg/opengl/ZeroGSShaders/zpipe.cpp | 115 + plugins/zzogl-pg/opengl/ZeroGSShaders/zpipe.h | 7 + plugins/zzogl-pg/opengl/buildshaders.bat | 3 + plugins/zzogl-pg/opengl/common.h | 1142 + plugins/zzogl-pg/opengl/common/PS2Edefs.h | 876 + plugins/zzogl-pg/opengl/common/PS2Etypes.h | 234 + plugins/zzogl-pg/opengl/compile | 1 + plugins/zzogl-pg/opengl/configure.ac | 151 + plugins/zzogl-pg/opengl/ctx0/ps2hw_ctx.fx | 24 + plugins/zzogl-pg/opengl/ctx1/ps2hw_ctx.fx | 23 + plugins/zzogl-pg/opengl/depcomp | 1 + plugins/zzogl-pg/opengl/glprocs.c | 17864 ++++++++++++++++ plugins/zzogl-pg/opengl/glprocs.h | 2213 ++ plugins/zzogl-pg/opengl/install-sh | 323 + plugins/zzogl-pg/opengl/memcpy_amd.cpp | 478 + plugins/zzogl-pg/opengl/missing | 1 + plugins/zzogl-pg/opengl/ps2hw.dat | Bin 0 -> 108445 bytes plugins/zzogl-pg/opengl/ps2hw.fx | 850 + plugins/zzogl-pg/opengl/rasterfont.cpp | 147 + plugins/zzogl-pg/opengl/rasterfont.h | 22 + plugins/zzogl-pg/opengl/shaders.sh | 3 + plugins/zzogl-pg/opengl/targets.cpp | 3415 +++ plugins/zzogl-pg/opengl/targets.h | 263 + plugins/zzogl-pg/opengl/x86-32.S | 1002 + plugins/zzogl-pg/opengl/x86-32.asm | 652 + plugins/zzogl-pg/opengl/x86-64.S | 906 + plugins/zzogl-pg/opengl/x86-64.asm | 1091 + plugins/zzogl-pg/opengl/x86.cpp | 719 + plugins/zzogl-pg/opengl/x86.h | 190 + plugins/zzogl-pg/opengl/zerogs.cpp | 1178 + plugins/zzogl-pg/opengl/zerogs.h | 846 + plugins/zzogl-pg/opengl/zerogsmath.h | 903 + plugins/zzogl-pg/opengl/zpipe.cpp | 115 + plugins/zzogl-pg/opengl/zpipe.h | 7 + 136 files changed, 70409 insertions(+) create mode 100644 plugins/zzogl-pg/build.sh create mode 100644 plugins/zzogl-pg/opengl/GS.h create mode 100644 plugins/zzogl-pg/opengl/GSmain.cpp create mode 100644 plugins/zzogl-pg/opengl/Linux/CMakeLists.txt create mode 100644 plugins/zzogl-pg/opengl/Linux/Conf.cpp create mode 100644 plugins/zzogl-pg/opengl/Linux/Linux.cpp create mode 100644 plugins/zzogl-pg/opengl/Linux/Linux.h create mode 100644 plugins/zzogl-pg/opengl/Linux/Makefile create mode 100644 plugins/zzogl-pg/opengl/Linux/Makefile.am create mode 100644 plugins/zzogl-pg/opengl/Linux/Makefile.in create mode 100644 plugins/zzogl-pg/opengl/Linux/buildgui.sh create mode 100644 plugins/zzogl-pg/opengl/Linux/callbacks.c create mode 100644 plugins/zzogl-pg/opengl/Linux/callbacks.h create mode 100644 plugins/zzogl-pg/opengl/Linux/cmake_install.cmake create mode 100644 plugins/zzogl-pg/opengl/Linux/interface.c create mode 100644 plugins/zzogl-pg/opengl/Linux/interface.h create mode 100644 plugins/zzogl-pg/opengl/Linux/support.c create mode 100644 plugins/zzogl-pg/opengl/Linux/support.h create mode 100644 plugins/zzogl-pg/opengl/Linux/zerogs.glade create mode 100644 plugins/zzogl-pg/opengl/Makefile.am create mode 100644 plugins/zzogl-pg/opengl/Mem.cpp create mode 100644 plugins/zzogl-pg/opengl/Mem.h create mode 100644 plugins/zzogl-pg/opengl/README.txt create mode 100644 plugins/zzogl-pg/opengl/Regs.cpp create mode 100644 plugins/zzogl-pg/opengl/Regs.h create mode 100644 plugins/zzogl-pg/opengl/Win32/Conf.cpp create mode 100644 plugins/zzogl-pg/opengl/Win32/Win32.cpp create mode 100644 plugins/zzogl-pg/opengl/Win32/Win32.h create mode 100644 plugins/zzogl-pg/opengl/Win32/aviUtil.h create mode 100644 plugins/zzogl-pg/opengl/Win32/jconfig.h create mode 100644 plugins/zzogl-pg/opengl/Win32/jmorecfg.h create mode 100644 plugins/zzogl-pg/opengl/Win32/jpeglib.h create mode 100644 plugins/zzogl-pg/opengl/Win32/libjpeg.lib create mode 100644 plugins/zzogl-pg/opengl/Win32/libjpeg64.lib create mode 100644 plugins/zzogl-pg/opengl/Win32/ps2hw.dat create mode 100644 plugins/zzogl-pg/opengl/Win32/resource.h create mode 100644 plugins/zzogl-pg/opengl/Win32/resrc1.h create mode 100644 plugins/zzogl-pg/opengl/Win32/tsvnrev/svnrev_template.h create mode 100644 plugins/zzogl-pg/opengl/Win32/tsvnrev/svnrev_unknown.h create mode 100644 plugins/zzogl-pg/opengl/Win32/tsvnrev/updateRevision.cmd create mode 100644 plugins/zzogl-pg/opengl/Win32/vsprops/pcsx2_plugin_common.vsprops create mode 100644 plugins/zzogl-pg/opengl/Win32/vsprops/postBuild.tmpl create mode 100644 plugins/zzogl-pg/opengl/Win32/vsprops/postBuild.unknown create mode 100644 plugins/zzogl-pg/opengl/Win32/vsprops/preBuild.cmd create mode 100644 plugins/zzogl-pg/opengl/Win32/vsprops/svnrev_template.h create mode 100644 plugins/zzogl-pg/opengl/Win32/vsprops/svnrev_unknown.h create mode 100644 plugins/zzogl-pg/opengl/Win32/wglext.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zerogs.bmp create mode 100644 plugins/zzogl-pg/opengl/Win32/zerogs.def create mode 100644 plugins/zzogl-pg/opengl/Win32/zerogs.rc create mode 100644 plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/adler32.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/compress.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/crc32.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/crc32.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/deflate.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/deflate.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/gzio.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/infback.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/inffast.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/inffast.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/inffixed.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/inflate.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/inflate.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/inftrees.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/inftrees.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/trees.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/trees.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/uncompr.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/zconf.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/zlib.h create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/zutil.c create mode 100644 plugins/zzogl-pg/opengl/Win32/zlib/zutil.h create mode 100644 plugins/zzogl-pg/opengl/ZZoglCRTC.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZoglCreate.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZoglFlush.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZoglSave.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZoglShaders.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZoglShoots.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZoglVB.cpp create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.am create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.in create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/ZLib.lib create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/ZeroGSShaders.vcproj create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/copytozerogs.bat create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.cpp create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/crc32.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/deflate.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inffast.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inffixed.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inflate.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inftrees.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/trees.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zconf.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zconf.in.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zlib.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zutil.h create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zpipe.cpp create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/zpipe.h create mode 100644 plugins/zzogl-pg/opengl/buildshaders.bat create mode 100644 plugins/zzogl-pg/opengl/common.h create mode 100644 plugins/zzogl-pg/opengl/common/PS2Edefs.h create mode 100644 plugins/zzogl-pg/opengl/common/PS2Etypes.h create mode 120000 plugins/zzogl-pg/opengl/compile create mode 100644 plugins/zzogl-pg/opengl/configure.ac create mode 100644 plugins/zzogl-pg/opengl/ctx0/ps2hw_ctx.fx create mode 100644 plugins/zzogl-pg/opengl/ctx1/ps2hw_ctx.fx create mode 120000 plugins/zzogl-pg/opengl/depcomp create mode 100644 plugins/zzogl-pg/opengl/glprocs.c create mode 100644 plugins/zzogl-pg/opengl/glprocs.h create mode 100644 plugins/zzogl-pg/opengl/install-sh create mode 100644 plugins/zzogl-pg/opengl/memcpy_amd.cpp create mode 120000 plugins/zzogl-pg/opengl/missing create mode 100644 plugins/zzogl-pg/opengl/ps2hw.dat create mode 100644 plugins/zzogl-pg/opengl/ps2hw.fx create mode 100644 plugins/zzogl-pg/opengl/rasterfont.cpp create mode 100644 plugins/zzogl-pg/opengl/rasterfont.h create mode 100755 plugins/zzogl-pg/opengl/shaders.sh create mode 100644 plugins/zzogl-pg/opengl/targets.cpp create mode 100644 plugins/zzogl-pg/opengl/targets.h create mode 100644 plugins/zzogl-pg/opengl/x86-32.S create mode 100644 plugins/zzogl-pg/opengl/x86-32.asm create mode 100644 plugins/zzogl-pg/opengl/x86-64.S create mode 100644 plugins/zzogl-pg/opengl/x86-64.asm create mode 100644 plugins/zzogl-pg/opengl/x86.cpp create mode 100644 plugins/zzogl-pg/opengl/x86.h create mode 100644 plugins/zzogl-pg/opengl/zerogs.cpp create mode 100644 plugins/zzogl-pg/opengl/zerogs.h create mode 100644 plugins/zzogl-pg/opengl/zerogsmath.h create mode 100644 plugins/zzogl-pg/opengl/zpipe.cpp create mode 100644 plugins/zzogl-pg/opengl/zpipe.h diff --git a/plugins/build.sh b/plugins/build.sh index d8b432137e..e9b4ca54d8 100644 --- a/plugins/build.sh +++ b/plugins/build.sh @@ -23,6 +23,7 @@ buildplugin SPU2null $@ buildplugin zerogs $@ buildplugin zzogl $@ +buildplugin zzogl-pg $@ buildplugin zeropad $@ buildplugin zerospu2 $@ diff --git a/plugins/zzogl-pg/build.sh b/plugins/zzogl-pg/build.sh new file mode 100644 index 0000000000..4271e3b1c0 --- /dev/null +++ b/plugins/zzogl-pg/build.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +curdir=`pwd` + +echo ---------------------- +echo Building ZZOpenGL +echo ---------------------- + +cd ${curdir}/opengl + +if [ $# -gt 0 ] && [ $1 = "all" ] +then + +aclocal +automake +autoconf +chmod +x configure +./configure --enable-sse2 --prefix=${PCSX2PLUGINS} +make clean +make install + +else +make $@ +fi + +if [ $? -ne 0 ] +then +exit 1 +fi + +#cp libZeroGSogl*.so* ${PCSX2PLUGINS}/ +cp Win32/ps2hw.dat ${PCSX2PLUGINS}/ diff --git a/plugins/zzogl-pg/opengl/GS.h b/plugins/zzogl-pg/opengl/GS.h new file mode 100644 index 0000000000..5fb30dae06 --- /dev/null +++ b/plugins/zzogl-pg/opengl/GS.h @@ -0,0 +1,1228 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GS_H__ +#define __GS_H__ + +#ifdef _WIN32 + +#include +#include + +extern HWND GShwnd; + +#else // linux basic definitions + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +#endif + +#include +#include +#include + +extern float fFPS; + +// need C definitions +extern "C" { +#define GSdefs +#include "PS2Edefs.h" + +extern "C" u32 CALLBACK PS2EgetLibType(void); +extern "C" u32 CALLBACK PS2EgetLibVersion2(u32 type); +extern "C" char* CALLBACK PS2EgetLibName(void); +} + +#include "zerogsmath.h" + +#include + +#include +#include +using namespace std; + +extern u32 THR_KeyEvent; // value for passing out key events beetwen threads +extern bool THR_bShift; +extern std::string s_strIniPath; // Air's new (r2361) new constant for ini file path + +#ifndef _WIN32 +#if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC) + +// declare linux equivalents +static __forceinline void* pcsx2_aligned_malloc(size_t size, size_t align) +{ + assert( align < 0x10000 ); + char* p = (char*)malloc(size+align); + int off = 2+align - ((int)(uptr)(p+2) % align); + + p += off; + *(u16*)(p-2) = off; + + return p; +} + +static __forceinline void pcsx2_aligned_free(void* pmem) +{ + if( pmem != NULL ) { + char* p = (char*)pmem; + free(p - (int)*(u16*)(p-2)); + } +} + +#define _aligned_malloc pcsx2_aligned_malloc +#define _aligned_free pcsx2_aligned_free + +#endif + +#include // ftime(), struct timeb + +inline unsigned long timeGetTime() +{ +#ifdef _WIN32 + _timeb t; + _ftime(&t); +#else + timeb t; + ftime(&t); +#endif + + return (unsigned long)(t.time*1000+t.millitm); +} + +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +struct RECT +{ + int left, top; + int right, bottom; +}; + +typedef struct { + Display *dpy; + int screen; + Window win; + GLXContext ctx; + XSetWindowAttributes attr; + Bool fs; + Bool doubleBuffered; + XF86VidModeModeInfo deskMode; + int x, y; + unsigned int width, height; + unsigned int depth; +} GLWindow; + +extern GLWindow GLWin; + +#endif // linux basic definitions + +struct Vector_16F +{ + u16 x, y, z, w; +}; + +///////////////////// +// define when releasing +// The only code that uses it is commented out! +//#define ZEROGS_CACHEDCLEAR // much better performance +//#define RELEASE_TO_PUBLIC +// fixme - We should use ZEROGS_DEVBUILD to determine devel/debug builds from "public release" builds. +// Means a lot of search-and-replace though. (air) + +#ifdef ZEROGS_DEVBUILD +#define GS_LOG __Log +#else +#define GS_LOG 0&& +#endif + +#define ERROR_LOG __LogToConsole +//Logging for oftenly calling error should have time counter. +static unsigned long int lasttime = 0; +static unsigned long int BigTime = 5000; +static bool SPAM_PASS; +#define ERROR_LOG_SPAM(text) { \ + if( timeGetTime() - lasttime > BigTime ) { \ + ERROR_LOG(text); \ + lasttime = timeGetTime(); \ + } \ +} +// The same macro with one-argument substitution. +#define ERROR_LOG_SPAMA(fmt, value) { \ + if( timeGetTime() - lasttime > BigTime ) { \ + ERROR_LOG(fmt, value); \ + lasttime = timeGetTime(); \ + } \ +} + +#define ERROR_LOG_SPAM_TEST(text) {\ + if( timeGetTime() - lasttime > BigTime ) { \ + ERROR_LOG(text); \ + lasttime = timeGetTime(); \ + SPAM_PASS = true; \ + } \ + else \ + SPAM_PASS = false; \ +} + +#if DEBUG_PROF +#define FILE_IS_IN_CHECK ((strcmp(__FILE__, "targets.cpp") == 0) || (strcmp(__FILE__, "ZZoglFlush.cpp") == 0)) + +#define FUNCLOG {\ + static bool Was_Here = false; \ + static unsigned long int waslasttime = 0; \ + if (!Was_Here && FILE_IS_IN_CHECK) { \ + Was_Here = true;\ + ERROR_LOG("%s:%d %s\n", __FILE__, __LINE__, __func__); \ + waslasttime = timeGetTime(); \ + } \ + if (FILE_IS_IN_CHECK && (timeGetTime() - waslasttime > BigTime )) { \ + Was_Here = false; \ + } \ +} +#else +#define FUNCLOG +#endif + +#define DEBUG_LOG printf + +#ifdef RELEASE_TO_PUBLIC +#define WARN_LOG 0&& +#define PRIM_LOG 0&& +#else +#define WARN_LOG printf +#define PRIM_LOG if (conf.log & 0x00000010) GS_LOG +#endif + +#ifndef GREG_LOG +#define GREG_LOG 0&& +#endif +#ifndef PRIM_LOG +#define PRIM_LOG 0&& +#endif +#ifndef WARN_LOG +#define WARN_LOG 0&& +#endif + +#define REG64(name) \ +union name \ +{ \ + u64 i64; \ + u32 ai32[2]; \ + struct { \ + +#define REG128(name)\ +union name \ +{ \ + u64 ai64[2]; \ + u32 ai32[4]; \ + struct { \ + +#define REG64_(prefix, name) REG64(prefix##name) +#define REG128_(prefix, name) REG128(prefix##name) + +#define REG_END }; }; +#define REG_END2 }; + +#define REG64_SET(name) \ +union name \ +{ \ + u64 i64; \ + u32 ai32[2]; \ + +#define REG128_SET(name)\ +union name \ +{ \ + u64 ai64[2]; \ + u32 ai32[4]; \ + +#define REG_SET_END }; + +REG64_(GSReg, BGCOLOR) + u32 R:8; + u32 G:8; + u32 B:8; + u32 _PAD1:8; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, BUSDIR) + u32 DIR:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, CSR) + u32 SIGNAL:1; + u32 FINISH:1; + u32 HSINT:1; + u32 VSINT:1; + u32 EDWINT:1; + u32 ZERO1:1; + u32 ZERO2:1; + u32 _PAD1:1; + u32 FLUSH:1; + u32 RESET:1; + u32 _PAD2:2; + u32 NFIELD:1; + u32 FIELD:1; + u32 FIFO:2; + u32 REV:8; + u32 ID:8; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, DISPFB) // (-1/2) + u32 FBP:9; + u32 FBW:6; + u32 PSM:5; + u32 _PAD:12; + u32 DBX:11; + u32 DBY:11; + u32 _PAD2:10; +REG_END + +REG64_(GSReg, DISPLAY) // (-1/2) + u32 DX:12; + u32 DY:11; + u32 MAGH:4; + u32 MAGV:2; + u32 _PAD:3; + u32 DW:12; + u32 DH:11; + u32 _PAD2:9; +REG_END + +REG64_(GSReg, EXTBUF) + u32 EXBP:14; + u32 EXBW:6; + u32 FBIN:2; + u32 WFFMD:1; + u32 EMODA:2; + u32 EMODC:2; + u32 _PAD1:5; + u32 WDX:11; + u32 WDY:11; + u32 _PAD2:10; +REG_END + +REG64_(GSReg, EXTDATA) + u32 SX:12; + u32 SY:11; + u32 SMPH:4; + u32 SMPV:2; + u32 _PAD1:3; + u32 WW:12; + u32 WH:11; + u32 _PAD2:9; +REG_END + +REG64_(GSReg, EXTWRITE) + u32 WRITE; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, IMR) + u32 _PAD1:8; + u32 SIGMSK:1; + u32 FINISHMSK:1; + u32 HSMSK:1; + u32 VSMSK:1; + u32 EDWMSK:1; + u32 _PAD2:19; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, PMODE) + u32 EN1:1; + u32 EN2:1; + u32 CRTMD:3; + u32 MMOD:1; + u32 AMOD:1; + u32 SLBG:1; + u32 ALP:8; + u32 _PAD:16; + u32 _PAD1:32; +REG_END + +REG64_(GSReg, SIGLBLID) + u32 SIGID:32; + u32 LBLID:32; +REG_END + +REG64_(GSReg, SMODE1) + u32 RC:3; + u32 LC:7; + u32 T1248:2; + u32 SLCK:1; + u32 CMOD:2; + u32 EX:1; + u32 PRST:1; + u32 SINT:1; + u32 XPCK:1; + u32 PCK2:2; + u32 SPML:4; + u32 GCONT:1; + u32 PHS:1; + u32 PVS:1; + u32 PEHS:1; + u32 PEVS:1; + u32 CLKSEL:2; + u32 NVCK:1; + u32 SLCK2:1; + u32 VCKSEL:2; + u32 VHP:1; + u32 _PAD1:27; +REG_END + +REG64_(GSReg, SMODE2) + u32 INT:1; + u32 FFMD:1; + u32 DPMS:2; + u32 _PAD2:28; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, SIGBLID) + u32 SIGID; + u32 LBLID; +REG_END + +extern int g_LastCRC; +extern u8* g_pBasePS2Mem; + +#define PMODE ((GSRegPMODE*)(g_pBasePS2Mem+0x0000)) +#define SMODE1 ((GSRegSMODE1*)(g_pBasePS2Mem+0x0010)) +#define SMODE2 ((GSRegSMODE2*)(g_pBasePS2Mem+0x0020)) +// SRFSH +#define SYNCH1 ((GSRegSYNCH1*)(g_pBasePS2Mem+0x0040)) +#define SYNCH2 ((GSRegSYNCH2*)(g_pBasePS2Mem+0x0050)) +#define SYNCV ((GSRegSYNCV*)(g_pBasePS2Mem+0x0060)) +#define DISPFB1 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0070)) +#define DISPLAY1 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x0080)) +#define DISPFB2 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0090)) +#define DISPLAY2 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x00a0)) +#define EXTBUF ((GSRegEXTBUF*)(g_pBasePS2Mem+0x00b0)) +#define EXTDATA ((GSRegEXTDATA*)(g_pBasePS2Mem+0x00c0)) +#define EXTWRITE ((GSRegEXTWRITE*)(g_pBasePS2Mem+0x00d0)) +#define BGCOLOR ((GSRegBGCOLOR*)(g_pBasePS2Mem+0x00e0)) +#define CSR ((GSRegCSR*)(g_pBasePS2Mem+0x1000)) +#define IMR ((GSRegIMR*)(g_pBasePS2Mem+0x1010)) +#define BUSDIR ((GSRegBUSDIR*)(g_pBasePS2Mem+0x1040)) +#define SIGLBLID ((GSRegSIGBLID*)(g_pBasePS2Mem+0x1080)) + +#define GET_GSFPS (((SMODE1->CMOD&1) ? 50 : 60) / (SMODE2->INT ? 1 : 2)) + +// +// sps2tags.h +// +#ifdef _M_AMD64 +#define GET_GIF_REG(tag, reg) \ + (((tag).ai64[1] >> ((reg) << 2)) & 0xf) +#else +#define GET_GIF_REG(tag, reg) \ + (((tag).ai32[2 + ((reg) >> 3)] >> (((reg) & 7) << 2)) & 0xf) +#endif + +// +// GIFTag +REG128(GIFTag) + u32 NLOOP:15; + u32 EOP:1; + u32 _PAD1:16; + u32 _PAD2:14; + u32 PRE:1; + u32 PRIM:11; + u32 FLG:2; // enum GIF_FLG + u32 NREG:4; + u64 REGS:64; +REG_END + +typedef struct { + int x, y, w, h; +} Rect; + +typedef struct { + int x, y; +} Point; + +typedef struct { + int x0, y0; + int x1, y1; +} Rect2; + +typedef struct { + int x, y, c; +} PointC; + +#define GSOPTION_FULLSCREEN 0x2 +#define GSOPTION_TGASNAP 0x4 +#define GSOPTION_CAPTUREAVI 0x8 + +#define GSOPTION_WINDIMS 0x30 +#define GSOPTION_WIN640 0x00 +#define GSOPTION_WIN800 0x10 +#define GSOPTION_WIN1024 0x20 +#define GSOPTION_WIN1280 0x30 +#define GSOPTION_WIDESCREEN 0x40 + +#define GSOPTION_WIREFRAME 0x100 +#define GSOPTION_LOADED 0x8000 + +//Configuration values. +typedef struct { + // write color in render target + u8 mrtdepth; + // intelacing mode 0, 1, 3-off + u8 interlace; + // antialiasing 0 - off, 1 - 2x, 2 - 4x, 3 - 8x, 4 - 16x + u8 aa; + // negative aliasing + u8 negaa; + // set to enable bilinear support. 0 - off, 1 -- on, 2 -- force (use it to textures, + // that usually does neet billinear + u8 bilinear; + // game options -- diffetent hacks. + u32 options; + // default game settings + u32 gamesettings; + // View target size, have no impact to speed + int width, height; + // Widescreen support + bool isWideScreen; +#ifdef GS_LOG + u32 log; +#endif +} GSconf; + +// PS2 vertex +struct VertexGPU +{ + // gained from XYZ2, XYZ3, XYZF2, XYZF3, + // X -- bits 0-15, Y-16-31. Z - 32-63 if no F used, 32-55 otherwise, F (fog) - 56-63 + // X, Y stored in 12d3 format, + s16 x, y, f, resv0; // note: xy is 12d3 + // Vertex color settings. RGB -- luminance of red/green/blue, A -- alpha. 1.0 == 0x80. + // Goes grom RGBAQ register, bits 0-7, 8-15, 16-23 and 24-31 accordingly + u32 rgba; + u32 z; + // Texture coordinates. S & T going from ST register (bits 0-31, and 32-63). + // Q goes from RGBAQ register, bits 32-63 + float s, t, q; +}; + +// Almost same with previous, controlled by prim.fst flagf +struct Vertex +{ + u16 x, y, f, resv0; // note: xy is 12d3 + u32 rgba; + u32 z; + float s, t, q; + // Texel coordinate of vertex. Used if prim.fst == 1 + // Bits 0-14 and 16-30 of UV + u16 u, v; +}; + +extern int g_GameSettings; +extern GSconf conf; +extern int ppf; + +// PSM values +// PSM types == Texture Storage Format +enum PSM_value{ + PSMCT32 = 0, // 000000 + PSMCT24 = 1, // 000001 + PSMCT16 = 2, // 000010 + PSMCT16S = 10, // 001010 + PSMT8 = 19, // 010011 + PSMT4 = 20, // 010100 + PSMT8H = 27, // 011011 + PSMT4HL = 36, // 100100 + PSMT4HH = 44, // 101100 + PSMT32Z = 48, // 110000 + PSMT24Z = 49, // 110001 + PSMT16Z = 50, // 110010 + PSMT16SZ = 58, // 111010 +}; + +// CLUT = Color look up table. Set proper color to table according CLUT table. +// Used for PSMT8, PSMT8H, PSMT4, PSMT4HH, PSMT4HL textures +inline bool PSMT_ISCLUT(int psm) { return ((psm & 0x7) > 2);} + +// PSMCT16, PSMCT16S, PSMT16Z, PSMT16SZ is 16-bit targets and usually there is +// two of them in each 32-bit word. +inline bool PSMT_IS16BIT(int psm) { return ((psm & 0x7) == 2);} + +// PSMT32Z, PSMT24Z, PSMT16Z, PSMT16SZ is Z-buffer textures +inline bool PSMT_ISZTEX(int psm) {return ((psm & 0x30) == 0x30);} + +// PSMCT16, PSMCT16S, PSMT8, PSMT8H, PSMT16Z and PSMT16SZ use only half 16 bit per pixel. +inline bool PSMT_ISHALF(int psm) {return (psm & 2);} + +// PSMT8 and PSMT8H use IDTEX8 CLUT, PSMT4H, PSMT4HL, PSMT4HH -- IDTEX4. +// Don't use it on non clut entries, please! +inline bool PSMT_IS8CLUT(int psm) {return ((psm & 3) == 3);} + +// PSM16Z and PSMT16SZ use -1 offset to z-buff. Need to check this thesis. +inline bool PSMT_IS16Z(int psm) {return ((psm & 0x32) == 0x32);} + +// Check target bit mode. PSMCT32 and 32Z return 0, 24 and 24Z - 1 +// 16, 16S, 16Z, 16SZ -- 2, PSMT8 and 8H - 3, PSMT4, 4HL, 4HH -- 4. +inline int PSMT_BITMODE(int psm) {return (psm & 0x7);} + +//----------------------- Data from registers ----------------------- +// EE part. Data transfer packet description +typedef struct { + int nloop; + int eop; + int nreg; +} tagInfo; + +typedef struct { + int mode; + int regn; + u64 regs; + tagInfo tag; +} pathInfo; + +typedef union { + s64 SD; + u64 UD; + s32 SL[2]; + u32 UL[2]; + s16 SS[4]; + u16 US[4]; + s8 SC[8]; + u8 UC[8]; +} reg64; + +/* general purpose regs structs */ +typedef struct { + int fbp; + int fbw; + int fbh; + int psm; + u32 fbm; +} frameInfo; + +// Create frame structure from known data +inline frameInfo CreateFrame(int fbp, int fbw, int fbh, int psm, u32 fbm){ + frameInfo frame; + frame.fbp = fbp; + frame.fbw = fbw; + frame.fbh = fbh; + frame.psm = psm; + frame.fbm = fbm; + return frame; +} + +typedef struct { + u16 prim; + + union { + struct { + u16 iip : 1; + u16 tme : 1; + u16 fge : 1; + u16 abe : 1; + u16 aa1 : 1; + u16 fst : 1; + u16 ctxt : 1; + u16 fix : 1; + u16 resv : 8; + }; + u16 _val; + }; +} primInfo; + +extern primInfo *prim; + +typedef union { + struct { + u32 ate : 1; + u32 atst : 3; + u32 aref : 8; + u32 afail : 2; + u32 date : 1; + u32 datm : 1; + u32 zte : 1; + u32 ztst : 2; + u32 resv : 13; + }; + u32 _val; +} pixTest; + +typedef struct { + int bp; + int bw; + int psm; +} bufInfo; + +typedef struct { + int tbp0; + int tbw; + int cbp; + u16 tw, th; + u8 psm; + u8 tcc; + u8 tfx; + u8 cpsm; + u8 csm; + u8 csa; + u8 cld; +} tex0Info; + +#define TEX_MODULATE 0 +#define TEX_DECAL 1 +#define TEX_HIGHLIGHT 2 +#define TEX_HIGHLIGHT2 3 + +typedef struct { + int lcm; + int mxl; + int mmag; + int mmin; + int mtba; + int l; + int k; +} tex1Info; + +typedef struct { + int wms; + int wmt; + int minu; + int maxu; + int minv; + int maxv; +} clampInfo; + +typedef struct { + int cbw; + int cou; + int cov; +} clutInfo; + +typedef struct { + int tbp[3]; + int tbw[3]; +} miptbpInfo; + +typedef struct { + u16 aem; + u8 ta[2]; + float fta[2]; +} texaInfo; + +typedef struct { + int sx; + int sy; + int dx; + int dy; + int dir; +} trxposInfo; + +typedef struct { + union { + struct { + u8 a : 2; + u8 b : 2; + u8 c : 2; + u8 d : 2; + }; + u8 abcd; + }; + + u8 fix : 8; +} alphaInfo; + +typedef struct { + u16 zbp; // u16 address / 64 + u8 psm; + u8 zmsk; +} zbufInfo; + +typedef struct { + int fba; +} fbaInfo; + +typedef struct { + Vertex gsvertex[3]; + u32 rgba; + float q; + Vertex vertexregs; + + int primC; // number of verts current storing + int primIndex; // current prim index + int nTriFanVert; + + int prac; + int dthe; + int colclamp; + int fogcol; + int smask; + int pabe; + u64 buff[2]; + int buffsize; + int cbp[2]; // internal cbp registers + + u32 CSRw; + + primInfo _prim[2]; + bufInfo srcbuf, srcbufnew; + bufInfo dstbuf, dstbufnew; + + clutInfo clut; + + texaInfo texa; + trxposInfo trxpos, trxposnew; + + int imageWtemp, imageHtemp; + + int imageTransfer; + int imageWnew, imageHnew, imageX, imageY, imageEndX, imageEndY; + + pathInfo path1; + pathInfo path2; + pathInfo path3; + +} GSinternal; + +extern GSinternal gs; + +extern FILE *gsLog; + +void __Log(const char *fmt, ...); +void __LogToConsole(const char *fmt, ...); + +void LoadConfig(); +void SaveConfig(); + +extern void (*GSirq)(); + +void *SysLoadLibrary(char *lib); // Loads Library +void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +char *SysLibError(); // Gets previous error loading sysbols +void SysCloseLibrary(void *lib); // Closes Library +void SysMessage(const char *fmt, ...); + +extern "C" void * memcpy_amd(void *dest, const void *src, size_t n); +extern "C" u8 memcmp_mmx(const void *dest, const void *src, int n); + +template +class CInterfacePtr +{ +public: + inline CInterfacePtr() : ptr(NULL) {} + inline explicit CInterfacePtr(T* newptr) : ptr(newptr) { if ( ptr != NULL ) ptr->AddRef(); } + inline ~CInterfacePtr() { if( ptr != NULL ) ptr->Release(); } + + inline T* operator* () { assert( ptr != NULL); return *ptr; } + inline T* operator->() { return ptr; } + inline T* get() { return ptr; } + + inline void release() { + if( ptr != NULL ) { ptr->Release(); ptr = NULL; } + } + + inline operator T*() { return ptr; } + + inline bool operator==(T* rhs) { return ptr == rhs; } + inline bool operator!=(T* rhs) { return ptr != rhs; } + + inline CInterfacePtr& operator= (T* newptr) { + if( ptr != NULL ) ptr->Release(); + ptr = newptr; + + if( ptr != NULL ) ptr->AddRef(); + return *this; + } + +private: + T* ptr; +}; + +#define RGBA32to16(c) \ + (u16)((((c) & 0x000000f8) >> 3) | \ + (((c) & 0x0000f800) >> 6) | \ + (((c) & 0x00f80000) >> 9) | \ + (((c) & 0x80000000) >> 16)) \ + +#define RGBA16to32(c) \ + (((c) & 0x001f) << 3) | \ + (((c) & 0x03e0) << 6) | \ + (((c) & 0x7c00) << 9) | \ + (((c) & 0x8000) ? 0xff000000 : 0) \ + +// converts float16 [0,1] to BYTE [0,255] (assumes value is in range, otherwise will take lower 8bits) +// f is a u16 +static __forceinline u16 Float16ToBYTE(u16 f) { + //assert( !(f & 0x8000) ); + if( f & 0x8000 ) return 0; + + u16 d = ((((f&0x3ff)|0x400)*255)>>(10-((f>>10)&0x1f)+15)); + return d > 255 ? 255 : d; +} + +static __forceinline u16 Float16ToALPHA(u16 f) { + //assert( !(f & 0x8000) ); + if( f & 0x8000 ) return 0; + + // round up instead of down (crash and burn), too much and charlie breaks + u16 d = (((((f&0x3ff)|0x400))*255)>>(10-((f>>10)&0x1f)+15)); + d = (d)>>1; + return d > 255 ? 255 : d; +} + +#ifndef COLOR_ARGB +#define COLOR_ARGB(a,r,g,b) \ + ((u32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) +#endif + +// assumes that positive in [1,2] (then extracts fraction by just looking at the specified bits) +#define Float16ToBYTE_2(f) ((u8)(*(u16*)&f>>2)) +#define Float16To5BIT(f) (Float16ToBYTE(f)>>3) + +#define Float16Alpha(f) (((*(u16*)&f&0x7c00)>=0x3900)?0x8000:0) // alpha is >= 1 + +// converts an array of 4 u16s to a u32 color +// f is a pointer to a u16 +#define Float16ToARGB(f) COLOR_ARGB(Float16ToALPHA(f.w), Float16ToBYTE(f.x), Float16ToBYTE(f.y), Float16ToBYTE(f.z)); + +#define Float16ToARGB16(f) (Float16Alpha(f.w)|(Float16To5BIT(f.x)<<10)|(Float16To5BIT(f.y)<<5)|Float16To5BIT(f.z)) + +// used for Z values +#define Float16ToARGB_Z(f) COLOR_ARGB((u32)Float16ToBYTE_2(f.w), Float16ToBYTE_2(f.x), Float16ToBYTE_2(f.y), Float16ToBYTE_2(f.z)) +#define Float16ToARGB16_Z(f) ((Float16ToBYTE_2(f.y)<<8)|Float16ToBYTE_2(f.z)) + + +inline float Clamp(float fx, float fmin, float fmax) +{ + if( fx < fmin ) return fmin; + return fx > fmax ? fmax : fx; +} + +// IMPORTANT: For every Register there must be an End +void DVProfRegister(char* pname); // first checks if this profiler exists in g_listProfilers +void DVProfEnd(u32 dwUserData); +void DVProfWrite(char* pfilename, u32 frames = 0); +void DVProfClear(); // clears all the profilers + +#define DVPROFILE +#ifdef DVPROFILE + +class DVProfileFunc +{ +public: + u32 dwUserData; + DVProfileFunc(char* pname) { DVProfRegister(pname); dwUserData = 0; } + DVProfileFunc(char* pname, u32 dwUserData) : dwUserData(dwUserData) { DVProfRegister(pname); } + ~DVProfileFunc() { DVProfEnd(dwUserData); } +}; + +#else + +class DVProfileFunc +{ +public: + u32 dwUserData; + static __forceinline DVProfileFunc(char* pname) {} + static __forceinline DVProfileFunc(char* pname, u32 dwUserData) { } + ~DVProfileFunc() {} +}; + +#endif + +// PSMT16, 16S have shorter color per pixel, also cluted textures with half storage. +inline bool PSMT_ISHALF_STORAGE(const tex0Info& tex0) { + if (PSMT_IS16BIT(tex0.psm) || (PSMT_ISCLUT(tex0.psm) && tex0.cpsm > 1)) + return true; + else + return false; +} + +//--------------------------- Inlines for bitwise ops +//--------------------------- textures +// Tex0Info (TEXD_x registers) bits, lower word +// The register is really 64-bit, but we use 2 32bit ones to represent it +// Obtain tbp0 -- Texture Buffer Base Pointer (Word Address/64) -- from data. Bits 0-13. +inline int +ZZOglGet_tbp0_TexBits(u32 data) { + return (data ) & 0x3fff; +} + +// Obtain tbw -- Texture Buffer Width (Texels/64) -- from data, do not multiply to 64. Bits 14-19 +// ( data & 0xfc000 ) >> 14 +inline int +ZZOglGet_tbw_TexBits(u32 data) { + return (data >> 14) & 0x3f; +} + +// Obtain tbw -- Texture Buffer Width (Texels) -- from data, do multiply to 64, never return 0. +inline int +ZZOglGet_tbw_TexBitsMult(u32 data) { + int result = ZZOglGet_tbw_TexBits(data); + if (result == 0) + return 64; + else + return (result << 6); +} + +// Obtain psm -- Pixel Storage Format -- from data. Bits 20-25. +// (data & 0x3f00000) >> 20 +inline int +ZZOglGet_psm_TexBits(u32 data) { + return ((data >> 20) & 0x3f); +} + +// Obtain psm -- Pixel Storage Format -- from data. Bits 20-25. Fix incorrect psm == 9 +inline int +ZZOglGet_psm_TexBitsFix(u32 data) { + int result = ZZOglGet_psm_TexBits(data) ; +// printf ("result %d\n", result); + if ( result == 9 ) + result = 1; + return result; +} + +// Obtain tw -- Texture Width (Width = 2^TW) -- from data. Bits 26-29 +// (data & 0x3c000000)>>26 +inline u16 +ZZOglGet_tw_TexBits(u32 data) { + return ((data >> 26) & 0xf); +} + +// Obtain tw -- Texture Width (Width = TW) -- from data. Width could newer be more than 1024. +inline u16 +ZZOglGet_tw_TexBitsExp(u32 data) { + u16 result = ZZOglGet_tw_TexBits(data); + if (result > 10) + result = 10; + return (1<> 30 + (dataHI & 0x3) * 0x4 +inline u16 +ZZOglGet_th_TexBits(u32 dataLO, u32 dataHI) { + return (((dataLO >> 30) & 0x3) | ((dataHI & 0x3) << 2)); +} + +// Obtain th --Texture Height (Height = 2^TH) -- from data. Height could newer be more than 1024. +inline u16 +ZZOglGet_th_TexBitsExp(u32 dataLO, u32 dataHI) { + u16 result = ZZOglGet_th_TexBits(dataLO, dataHI); + if (result > 10) + result = 10; + return (1<>2 +inline u8 +ZZOglGet_tcc_TexBits(u32 data) { + return ((data >> 2) & 0x1); +} + +// Obtain tfx -- Texture Function (0=modulate, 1=decal, 2=hilight, 3=hilight2) -- from data. Bit 4-5 +// (data & 0x18)>>3 +inline u8 +ZZOglGet_tfx_TexBits(u32 data) { + return ((data >> 3) & 0x3); +} + +// Obtain cbp from data -- Clut Buffer Base Pointer (Address/256) -- Bits 5-18 +// (data & 0x7ffe0)>>5 +inline int +ZZOglGet_cbp_TexBits(u32 data) { + return ((data >> 5) & 0x3fff); +} + +// Obtain cpsm from data -- Clut pixel Storage Format -- Bits 19-22. 22nd is at no use. +// (data & 0x700000)>>19 +inline u8 +ZZOglGet_cpsm_TexBits(u32 data) { + return ((data >> 19) & 0xe); +} + +// Obtain csm -- I don't know what is it -- from data. Bit 23 +// (data & 0x800000)>>23 +inline u8 +ZZOglGet_csm_TexBits(u32 data) { + return ((data >> 23) & 0x1); +} + +// Obtain csa -- -- from data. Bits 24-28 +// (data & 0x1f000000)>>24 +inline u8 +ZZOglGet_csa_TexBits(u32 data) { + if ((data & 0x700000) == 0 ) // it is cpsm < 2 check + return ((data >> 24) & 0xf); + else + return ((data >> 24) & 0x1f); +} + +// Obtain cld -- -- from data. Bits 29-31 +// (data & 0xe0000000)>>29 +inline u8 +ZZOglGet_cld_TexBits(u32 data) { + return ((data >> 29) & 0x7); +} + +//-------------------------- frames +// FrameInfo bits. +// Obtain fbp -- frame Buffer Base Pointer (Word Address/2048) -- from data. Bits 0-15 +inline int +ZZOglGet_fbp_FrameBits(u32 data) { + return ((data ) & 0x1ff); +} + +// So we got adress / 64, henceby frame fbp and tex tbp have the same dimension -- "real adress" is x64. +inline int +ZZOglGet_fbp_FrameBitsMult(u32 data) { + return (ZZOglGet_fbp_FrameBits(data) << 5); +} + +// Obtain fbw -- width (Texels/64) -- from data. Bits 16-23 +inline int +ZZOglGet_fbw_FrameBits(u32 data) { + return ((data >> 16) & 0x3f); +} + +inline int +ZZOglGet_fbw_FrameBitsMult(u32 data) { + return (ZZOglGet_fbw_FrameBits(data) << 6); +} + + +// Obtain psm -- Pixel Storage Format -- from data. Bits 24-29. +// (data & 0x3f000000) >> 24 +inline int +ZZOglGet_psm_FrameBits(u32 data) { + return ((data >> 24) & 0x3f); +} + +// Function for calculating overal height from frame data. +inline int +ZZOgl_fbh_Calc (int fbp, int fbw, int psm) { + int fbh = ( 1024 * 1024 - 64 * fbp ) / fbw; + fbh &= ~0x1f; + if (PSMT_ISHALF(psm)) + fbh *= 2; + if (fbh > 1024) + fbh = 1024; + return fbh ; +} +inline int +ZZOgl_fbh_Calc (frameInfo frame) { + return ZZOgl_fbh_Calc(frame.fbp, frame.fbw, frame.psm); +} + +// Calculate fbh from data, It does not set in register +inline int +ZZOglGet_fbh_FrameBitsCalc (u32 data) { + int fbh = 0; + int fbp = ZZOglGet_fbp_FrameBits(data); + int fbw = ZZOglGet_fbw_FrameBits(data); + int psm = ZZOglGet_psm_FrameBits(data); + if (fbw > 0) + fbh = ZZOgl_fbh_Calc(fbp, fbw, psm) ; + return fbh ; +} + +// Obtain fbm -- frame mask -- from data. All higher word. +inline u32 +ZZOglGet_fbm_FrameBits(u32 data) { + return (data); +} + +// Obtain fbm -- frame mask -- from data. All higher word. Fixed from psm == PCMT24 (without alpha) +inline u32 +ZZOglGet_fbm_FrameBitsFix(u32 dataLO, u32 dataHI) { + if (PSMT_BITMODE(ZZOglGet_psm_FrameBits(dataLO)) == 1) + return (dataHI | 0xff000000); + else + return dataHI; +} + +// obtain colormask RED +inline u32 +ZZOglGet_fbmRed_FrameBits(u32 data) { + return (data & 0xff); +} + +// obtain colormask Green +inline u32 +ZZOglGet_fbmGreen_FrameBits(u32 data) { + return ((data >> 8) & 0xff); +} + +// obtain colormask Blue +inline u32 +ZZOglGet_fbmBlue_FrameBits(u32 data) { + return ((data >> 16) & 0xff); +} + +// obtain colormask Alpha +inline u32 +ZZOglGet_fbmAlpha_FrameBits(u32 data) { + return ((data >> 24) & 0xff); +} + +// obtain colormask Alpha +inline u32 +ZZOglGet_fbmHighByte(u32 data) { + return (!!(data & 0x80000000)); +} + + + +//-------------------------- tex0 comparison +// Check if old and new tex0 registers have only clut difference +inline bool +ZZOglAllExceptClutIsSame( u32* oldtex, u32* newtex) { + return ((oldtex[0] == newtex[0]) && ((oldtex[1] & 0x1f) == (newtex[1] & 0x1f))); +} + +// Check if the CLUT registers are same, except CLD +inline bool +ZZOglClutMinusCLDunchanged( u32* oldtex, u32* newtex) { + return ((oldtex[1] & 0x1fffffe0) == (newtex[1] & 0x1fffffe0)); +} + +// Check if CLUT storage mode is not changed (CSA, CSM and CSPM) +inline bool +ZZOglClutStorageUnchanged( u32* oldtex, u32* newtex) { + return ((oldtex[1] & 0x1ff10000) == (newtex[1] & 0x1ff10000)); +} + +// CSA and CPSM bitmask 0001 1111 0111 1000 ... +// 60 56 52 +#define CPSM_CSA_BITMASK 0x1f780000 +#define CPSM_CSA_NOTMASK 0xe0870000 + +#endif diff --git a/plugins/zzogl-pg/opengl/GSmain.cpp b/plugins/zzogl-pg/opengl/GSmain.cpp new file mode 100644 index 0000000000..b511b613df --- /dev/null +++ b/plugins/zzogl-pg/opengl/GSmain.cpp @@ -0,0 +1,1603 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if defined(_WIN32) +#include +#include "Win32.h" +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +using namespace std; + +#include "GS.h" +#include "Mem.h" +#include "Regs.h" + +#include "zerogs.h" +#include "targets.h" +#include "ZeroGSShaders/zerogsshaders.h" + +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif + +GSinternal gs; +char GStitle[256]; +GSconf conf; +int ppf; +primInfo *prim; +FILE *gsLog; +int g_GSMultiThreaded = 0; +void (*GSirq)(); +u8* g_pBasePS2Mem = NULL; +int g_TransferredToGPU = 0; +std::string s_strIniPath("inis/"); // Air's new ini path (r2361) + +static BOOL g_bHidden = 0; +int g_GameSettings = 0; +int CurrentSavestate = 0; // Number of SaveSlot. Default is 0 +bool SaveStateExists = true; // We could not know save slot status before first change occured +const char* SaveStateFile = NULL; // Name of SaveFile for access check. + +// statistics +u32 g_nGenVars = 0, g_nTexVars = 0, g_nAlphaVars = 0, g_nResolve = 0; + +#define VER 21 +const unsigned char zgsversion = PS2E_GS_VERSION; +unsigned char zgsrevision = 0; // revision and build gives plugin version +unsigned char zgsbuild = VER; +unsigned char zgsminor = 209; + +#ifdef _DEBUG +char *libraryName = "ZZ Ogl (Debug) "; +#elif defined(RELEASE_TO_PUBLIC) +char *libraryName = "ZZ Ogl "; +#else +char *libraryName = "ZZ Ogl (Dev) "; +#endif + +static const char* s_aa[5] = { "AA none |", "AA 2x |", "AA 4x |", "AA 8x |", "AA 16x |" }; +static const char* s_naa[3] = { "nattive res |", "res /2 |", "res /4 |" }; +static const char* pbilinear[] = { "off", "normal", "forced" }; + +extern GIFRegHandler g_GIFPackedRegHandlers[]; +extern GIFRegHandler g_GIFRegHandlers[]; +GIFRegHandler g_GIFTempRegHandlers[16] = {0}; +extern int g_nPixelShaderVer; +extern int g_nFrameRender; +extern int g_nFramesSkipped; + +#ifdef RELEASE_TO_PUBLIC +#define g_bWriteProfile 0 +#else +BOOL g_bWriteProfile = 0; +#endif + +int s_frameskipping = 0; +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_GS; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (zgsversion<<16) | (zgsrevision<<8) | zgsbuild | (zgsminor << 24); +} + +static u64 luPerfFreq; + +#ifdef _WIN32 + +HWND GShwnd = NULL; + +void SysMessage(const char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "GSsoftdx Msg", 0); +} +#else + +GLWindow GLWin; +u32 THR_KeyEvent = 0; // Value for key event processing between threads +bool THR_bShift = false; + +#endif + +void __Log(const char *fmt, ...) { + va_list list; + + // gsLog can be null if the config dialog is used prior to Pcsx2 an emulation session. + // (GSinit won't have been called then) + + if (gsLog == NULL || !conf.log) return; + + va_start(list, fmt); + vfprintf(gsLog, fmt, list); + va_end(list); +} + +void __LogToConsole(const char *fmt, ...) { + va_list list; + + va_start(list, fmt); + + // gsLog can be null if the config dialog is used prior to Pcsx2 an emulation session. + // (GSinit won't have been called then) + + if( gsLog != NULL ) + vfprintf(gsLog, fmt, list); + + printf("ZZogl: "); + vprintf(fmt, list); + va_end(list); +} + +void CALLBACK GSsetBaseMem(void* pmem) { + g_pBasePS2Mem = (u8*)pmem; +} + +void CALLBACK GSsetSettingsDir(const char* dir) { + s_strIniPath = (dir==NULL) ? "inis/" : dir; +} + +extern int VALIDATE_THRESH; +extern u32 TEXDESTROY_THRESH; +int g_LastCRC = 0; +void CALLBACK GSsetGameCRC(int crc, int options) +{ + VALIDATE_THRESH = 8; + conf.mrtdepth = (conf.gamesettings&GAME_DISABLEMRTDEPTH !=0); + + if (!conf.mrtdepth) + ERROR_LOG("Disabling MRT depth writing\n"); + else + ERROR_LOG("Enabling MRT depth writing\n"); + + g_GameSettings |= GAME_PATH3HACK; + + bool RunningFirstTime = (g_LastCRC == crc); + g_LastCRC = crc; + + if (RunningFirstTime) { + switch(crc) { + case 0x54A548B4: // crash n burn + // overbright + break; + + case 0xA3D63039: // xenosaga(j) + case 0x0E7807B2: // xenosaga(u) + g_GameSettings |= GAME_DOPARALLELCTX; + VALIDATE_THRESH = 64; + TEXDESTROY_THRESH = 32; + break; + + case 0x7D2FE035: // espgaluda (j) + VALIDATE_THRESH = 24; + //g_GameSettings |= GAME_BIGVALIDATE; + break; + + case 0x21068223: //Okami, US, + case 0x891f223f: //Okami, FR + case 0xC5DEFEA0: //Okami, JP, + case 0xe0426fc6: //Okage Shadow King + conf.gamesettings |= 0x01000000; // Specular highlight; + break; + + case 0xD6385328: // GodOfWar + case 0xFB0E6D72: // GodOfWar, EU, + case 0xEB001875: // GodOfWar, EU, + case 0xA61A4C6D: // GodOfWar, + case 0xE23D532B: // GodOfWar, + conf.gamesettings |= 0x00010000; // full 16 bit + break; + + case 0xF0A6D880: // HarvestMoon, US + conf.gamesettings |= 0x00002000; // Disable stencil buffer + break; + + case 0xFB236A46: // SonicUnleashed, US + case 0xa5d29941: // Shadow the Hedgehog + conf.gamesettings |= 0x00040100; // Fast update + no Alpha fail + + case 0x7acf7e03: // Atelier Iris 1 + case 0x9AC65D6A: // Atelier Iris 2, US + case 0x4ccc9212: // Atelier Iris 3 + case 0xF95F37EE: // Ar Tonelico 2, US + case 0x77b0236f: // Mana Khemia + case 0x433951e7: // Mana Khemia 2 + conf.gamesettings |= 0x10000000; // GustFix + + case 0xbaa8dd8: // Dark Cloud 1 + conf.gamesettings |= 0x00000010; // No Target Resolves + + case 0x95cc86ef: // Ghost in the Shell + conf.gamesettings |= 0x00000100; // no Alpha fail + } + } + + g_GameSettings = conf.gamesettings|options; +} + +void CALLBACK GSsetFrameSkip(int frameskip) +{ + FUNCLOG + s_frameskipping |= frameskip; + if( frameskip && g_nFrameRender > 1 ) { + + for(int i = 0; i < 16; ++i) { + g_GIFPackedRegHandlers[i] = GIFPackedRegHandlerNOP; + } + + // still keep certain handlers + g_GIFPackedRegHandlers[6] = GIFRegHandlerTEX0_1; + g_GIFPackedRegHandlers[7] = GIFRegHandlerTEX0_2; + g_GIFPackedRegHandlers[14] = GIFPackedRegHandlerA_D; + + g_GIFRegHandlers[0] = GIFRegHandlerNOP; + g_GIFRegHandlers[1] = GIFRegHandlerNOP; + g_GIFRegHandlers[2] = GIFRegHandlerNOP; + g_GIFRegHandlers[3] = GIFRegHandlerNOP; + g_GIFRegHandlers[4] = GIFRegHandlerNOP; + g_GIFRegHandlers[5] = GIFRegHandlerNOP; + g_GIFRegHandlers[12] = GIFRegHandlerNOP; + g_GIFRegHandlers[13] = GIFRegHandlerNOP; + g_GIFRegHandlers[26] = GIFRegHandlerNOP; + g_GIFRegHandlers[27] = GIFRegHandlerNOP; + g_nFrameRender = 0; + } + else if( !frameskip && g_nFrameRender <= 0 ) { + g_nFrameRender = 1; + + if( g_GIFTempRegHandlers[0] == NULL ) return; // not init yet + + // restore + memcpy(g_GIFPackedRegHandlers, g_GIFTempRegHandlers, sizeof(g_GIFTempRegHandlers)); + + g_GIFRegHandlers[0] = GIFRegHandlerPRIM; + g_GIFRegHandlers[1] = GIFRegHandlerRGBAQ; + g_GIFRegHandlers[2] = GIFRegHandlerST; + g_GIFRegHandlers[3] = GIFRegHandlerUV; + g_GIFRegHandlers[4] = GIFRegHandlerXYZF2; + g_GIFRegHandlers[5] = GIFRegHandlerXYZ2; + g_GIFRegHandlers[12] = GIFRegHandlerXYZF3; + g_GIFRegHandlers[13] = GIFRegHandlerXYZ2; + g_GIFRegHandlers[26] = GIFRegHandlerPRMODECONT; + g_GIFRegHandlers[27] = GIFRegHandlerPRMODE; + } +} + +void CALLBACK GSreset() { + FUNCLOG + + memset(&gs, 0, sizeof(gs)); + + ZeroGS::GSStateReset(); + + gs.prac = 1; + prim = &gs._prim[0]; + gs.nTriFanVert = -1; + gs.imageTransfer = -1; + gs.q = 1; +} + +void CALLBACK GSgifSoftReset(u32 mask){ + FUNCLOG + + if( mask & 1 ) memset(&gs.path1, 0, sizeof(gs.path1)); + if( mask & 2 ) memset(&gs.path2, 0, sizeof(gs.path2)); + if( mask & 4 ) memset(&gs.path3, 0, sizeof(gs.path3)); + gs.imageTransfer = -1; + gs.q = 1; + gs.nTriFanVert = -1; +} + +s32 CALLBACK GSinit() +{ + FUNCLOG + + memcpy(g_GIFTempRegHandlers, g_GIFPackedRegHandlers, sizeof(g_GIFTempRegHandlers)); + +#ifdef GS_LOG + gsLog = fopen("logs/gsLog.txt", "w"); + if (gsLog == NULL) { + gsLog = fopen("gsLog.txt", "w"); + if (gsLog == NULL) { + SysMessage("Can't create gsLog.txt"); return -1; + } + } + setvbuf(gsLog, NULL, _IONBF, 0); + GS_LOG("GSinit\n"); +#endif + + GSreset(); + GS_LOG("GSinit ok\n"); + return 0; +} + +void CALLBACK GSshutdown() +{ + FUNCLOG + +#ifdef GS_LOG + if (gsLog != NULL) + fclose(gsLog); +#endif +} + +// keyboard functions +void OnKeyboardF5(int shift) +{ + FUNCLOG + + char strtitle[256]; + if( shift ) { + if( g_nPixelShaderVer == SHADER_REDUCED ) { + conf.bilinear = 0; + sprintf(strtitle, "reduced shaders don't support bilinear filtering"); + } + else { + conf.bilinear = (conf.bilinear+1)%3; + sprintf(strtitle, "bilinear filtering - %s", pbilinear[conf.bilinear]); + } + } + else { + conf.interlace++; + if( conf.interlace > 2 ) conf.interlace = 0; + if( conf.interlace < 2 ) sprintf(strtitle, "interlace on - mode %d", conf.interlace); + else sprintf(strtitle, "interlace off"); + } + + ZeroGS::AddMessage(strtitle); + SaveConfig(); +} + +void OnKeyboardF6(int shift) +{ + FUNCLOG + + char strtitle[256]; + if( shift ) { + conf.aa--; // -1 + if( conf.aa > 4 ) conf.aa = 4; // u8 in unsigned, so negative value is 255. + sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa]); + ZeroGS::SetAA(conf.aa); + } + else { + conf.aa++; + if( conf.aa > 4 ) conf.aa = 0; + sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa]); + ZeroGS::SetAA(conf.aa); + } + + ZeroGS::AddMessage(strtitle); + SaveConfig(); +} + +void OnKeyboardF7(int shift) +{ + FUNCLOG + + char strtitle[256]; + if( !shift ) { + extern BOOL g_bDisplayFPS; + g_bDisplayFPS ^= 1; + } + else { + conf.options ^= GSOPTION_WIREFRAME; + glPolygonMode(GL_FRONT_AND_BACK, (conf.options&GSOPTION_WIREFRAME)?GL_LINE:GL_FILL); + sprintf(strtitle, "wireframe rendering - %s", (conf.options&GSOPTION_WIREFRAME)?"on":"off"); + } +} + +void OnKeyboardF61(int shift) { + FUNCLOG + + char strtitle[256]; + if( shift ) { + conf.negaa--; // -1 + if( conf.negaa > 2 ) conf.negaa = 2; // u8 in unsigned, so negative value is 255. + sprintf(strtitle, "down resolution - %s", s_naa[conf.negaa]); + ZeroGS::SetNegAA(conf.negaa); + } + else { + conf.negaa++; + if( conf.negaa > 2 ) conf.negaa = 0; + sprintf(strtitle, "down resolution - %s", s_naa[conf.negaa]); + ZeroGS::SetNegAA(conf.negaa); + } + + ZeroGS::AddMessage(strtitle); + SaveConfig(); +} + +typedef struct GameHackStruct { + const char HackName[40]; + u32 HackMask; +} GameHack; +#define HACK_NUMBER 30 + +GameHack HackinshTable[HACK_NUMBER] = { + {"*** 0 No Hack", 0}, + {"*** 1 TexTargets Check", GAME_TEXTURETARGS}, + {"*** 2 Autoreset Targets", GAME_AUTORESET}, + {"*** 3 Interlace 2x", GAME_INTERLACE2X}, + {"*** 4 TexA hack", GAME_TEXAHACK}, + {"*** 5 No Target Resolve", GAME_NOTARGETRESOLVE}, + {"*** 6 Exact color", GAME_EXACTCOLOR}, + {"*** 7 No color clamp", GAME_NOCOLORCLAMP}, + {"*** 8 FFX hack", GAME_FFXHACK}, + {"*** 9 No Alpha Fail", GAME_NOALPHAFAIL}, + {"***10 No Depth Update", GAME_NODEPTHUPDATE}, + {"***11 Quick Resolve 1", GAME_QUICKRESOLVE1}, + {"***12 No quick resolve", GAME_NOQUICKRESOLVE}, + {"***13 Notaget clut", GAME_NOTARGETCLUT}, + {"***14 No Stencil", GAME_NOSTENCIL}, + {"***15 No Depth resolve", GAME_NODEPTHRESOLVE}, + {"***16 Full 16 bit", GAME_FULL16BITRES}, + {"***17 Resolve promoted", GAME_RESOLVEPROMOTED}, + {"***18 Fast Update", GAME_FASTUPDATE}, + {"***19 No Apha Test", GAME_NOALPHATEST}, + {"***20 Disable MRT deprh", GAME_DISABLEMRTDEPTH}, + {"***21 32 bit targes", GAME_32BITTARGS}, + {"***22 path 3 hack", GAME_PATH3HACK}, + {"***23 parallelise calls", GAME_DOPARALLELCTX}, + {"***24 specular highligths", GAME_XENOSPECHACK}, + {"***25 partial pointers", GAME_PARTIALPOINTERS}, + {"***26 partial depth", GAME_PARTIALDEPTH}, + {"***27 reget hack", GAME_REGETHACK}, + {"***28 gust hack", GAME_GUSTHACK}, + {"***29 log-Z", GAME_NOLOGZ} +}; + +int CurrentHackSetting = 0; + +void OnKeyboardF9(int shift) { + FUNCLOG + +// printf ("A %d\n", HackinshTable[CurrentHackSetting].HackMask); + conf.gamesettings &= !(HackinshTable[CurrentHackSetting].HackMask); + if( shift ) { + CurrentHackSetting--; + if (CurrentHackSetting == -1) + CurrentHackSetting = HACK_NUMBER-1; + } + else { + CurrentHackSetting++; + if (CurrentHackSetting == HACK_NUMBER) + CurrentHackSetting = 0; + } + conf.gamesettings |= HackinshTable[CurrentHackSetting].HackMask; + g_GameSettings = conf.gamesettings; + ZeroGS::AddMessage(HackinshTable[CurrentHackSetting].HackName); + SaveConfig(); +} + +void OnKeyboardF1(int shift) { + FUNCLOG + char strtitle[256]; + sprintf(strtitle, "Saving in savestate %d", CurrentSavestate); + SaveStateExists = true; + ZeroGS::AddMessage(HackinshTable[CurrentHackSetting].HackName); +} + +#ifdef _WIN32 + +#ifdef _DEBUG +HANDLE g_hCurrentThread = NULL; +#endif + +LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) +{ + static int nWindowWidth = 0, nWindowHeight = 0; + + switch( msg ) { + case WM_DESTROY: + PostQuitMessage( 0 ); + return 0; + + case WM_KEYDOWN: +// switch(wParam) { +// case VK_ESCAPE: +// SendMessage(hWnd, WM_DESTROY, 0L, 0L); +// break; +// } + break; + + case WM_ACTIVATE: + + if( wParam != WA_INACTIVE ) { + //DEBUG_LOG("restoring device\n"); + ZeroGS::Restore(); + } + + break; + + case WM_SIZE: + nWindowWidth = lParam&0xffff; + nWindowHeight = lParam>>16; + ZeroGS::ChangeWindowSize(nWindowWidth, nWindowHeight); + + break; + + case WM_SIZING: + // if button is 0, then just released so can resize + if( GetSystemMetrics(SM_SWAPBUTTON) ? !GetAsyncKeyState(VK_RBUTTON) : !GetAsyncKeyState(VK_LBUTTON) ) { + ZeroGS::SetChangeDeviceSize(nWindowWidth, nWindowHeight); + } + break; + + case WM_SETCURSOR: + SetCursor(NULL); + break; + } + + return DefWindowProc( hWnd, msg, wParam, lParam ); +} + +extern HINSTANCE hInst; +void CALLBACK GSconfigure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); + + if( g_nPixelShaderVer == SHADER_REDUCED ) + conf.bilinear = 0; +} + + +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread) { + + g_GSMultiThreaded = multithread; + + GS_LOG("GSopen\n"); + +#ifdef _DEBUG + g_hCurrentThread = GetCurrentThread(); +#endif + +// assert( GSirq != NULL ); + LoadConfig(); + + strcpy(GStitle, Title); + + RECT rc, rcdesktop; + rc.left = 0; rc.top = 0; + rc.right = conf.width; rc.bottom = conf.height; + + WNDCLASSEX wc; + HINSTANCE hInstance = GetModuleHandle(NULL); + DWORD dwExStyle, dwStyle; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_CLASSDC; + wc.lpfnWndProc = (WNDPROC) MsgProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = NULL; + wc.hIconSm = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = "PS2EMU_ZEROGS"; + + RegisterClassEx( &wc ); + + if( conf.options & GSOPTION_FULLSCREEN) + { + dwExStyle = WS_EX_APPWINDOW; + dwStyle = WS_POPUP; + } + else + { + dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dwStyle = WS_OVERLAPPEDWINDOW; + } + + AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); + GetWindowRect(GetDesktopWindow(), &rcdesktop); + + GShwnd = CreateWindowEx( + dwExStyle, + "PS2EMU_ZEROGS", + "ZeroGS", + dwStyle, + (rcdesktop.right - (rc.right - rc.left)) / 2, + (rcdesktop.bottom - (rc.bottom - rc.top)) / 2, + rc.right - rc.left, + rc.bottom - rc.top, + NULL, + NULL, + hInstance, + NULL); + + if(GShwnd == NULL) { + GS_LOG("Failed to create window. Exiting..."); + return -1; + } + + if( pDsp != NULL ) + *(HWND*)pDsp = GShwnd; + + ERROR_LOG("Using %s:%d.%d.%d\n", libraryName, zgsrevision, zgsbuild, zgsminor); + ERROR_LOG("creating zerogs\n"); + //if (conf.record) recOpen(); + if( !ZeroGS::Create(conf.width, conf.height) ) + return -1; + + ERROR_LOG("initialization successful\n"); + + if( conf.bilinear == 2 ) { + ZeroGS::AddMessage("forced bilinear filtering - on", 1000); + } + else if( conf.bilinear == 1 ) { + ZeroGS::AddMessage("normal bilinear filtering - on", 1000); + } + if( conf.aa ) { + char strtitle[64]; + sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa], 1000); + ZeroGS::AddMessage(strtitle); + } + + // set just in case + SetWindowLongPtr(GShwnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)MsgProc); + + ShowWindow( GShwnd, SW_SHOWDEFAULT ); + UpdateWindow( GShwnd ); + SetFocus(GShwnd); + + GS_LOG("GSopen ok\n"); + + LARGE_INTEGER temp; + QueryPerformanceFrequency(&temp); + luPerfFreq = temp.QuadPart; + + gs.path1.mode = 0; + gs.path2.mode = 0; + gs.path3.mode = 0; + + return 0; +} + +void ProcessMessages() +{ + MSG msg; + ZeroMemory( &msg, sizeof(msg) ); + while( 1 ) { + if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) + { + switch( msg.message ) { + case WM_KEYDOWN : + if( msg.wParam == VK_F5 ) { + OnKeyboardF5(GetKeyState(VK_SHIFT)&0x8000); + } + else if( msg.wParam == VK_F6 ) { + OnKeyboardF6(GetKeyState(VK_SHIFT)&0x8000); + } + else if( msg.wParam == VK_F7 ) { + OnKeyboardF7(GetKeyState(VK_SHIFT)&0x8000); + } + else if( msg.wParam == VK_F9 ) { + OnKeyboardF9(GetKeyState(VK_SHIFT)&0x8000); + } + else if( msg.wParam == VK_ESCAPE ) { + + if( conf.options & GSOPTION_FULLSCREEN ) { + // destroy that msg + conf.options &= ~GSOPTION_FULLSCREEN; + ZeroGS::ChangeDeviceSize(conf.width, conf.height); + UpdateWindow(GShwnd); + continue; // so that msg doesn't get sent + } + else { + SendMessage(GShwnd, WM_DESTROY, 0, 0); + g_bHidden = 1; + return; + } + } + + break; + } + + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + else + break; + } + + if( (GetKeyState(VK_MENU)&0x8000) && (GetKeyState(VK_RETURN)&0x8000) ) { + conf.options ^= GSOPTION_FULLSCREEN; + + ZeroGS::SetChangeDeviceSize( + (conf.options&GSOPTION_FULLSCREEN) ? 1280 : conf.width, + (conf.options&GSOPTION_FULLSCREEN) ? 960 : conf.height); + } + +// if( conf.fullscreen && (GetKeyState(VK_ESCAPE)&0x8000)) { +// conf.fullscreen &= ~GSOPTION_FULLSCREEN; +// ZeroGS::SetChangeDeviceSize(conf.width, conf.height); +// } + + //if( conf.interlace && g_nGenVars + g_nTexVars + g_nAlphaVars + g_nResolve == 0 ) + // CSR->FIELD = 0; // 0 should always be the repeating at 0 +} + +#else // linux + +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread) +{ + FUNCLOG + + GS_LOG("GSopen\n"); + +// assert( GSirq != NULL ); + LoadConfig(); + + strcpy(GStitle, Title); + + GLWin.dpy = XOpenDisplay(0); + GLWin.screen = DefaultScreen(GLWin.dpy); + + if( pDsp != NULL ) + *(Display**)pDsp = GLWin.dpy; + + ERROR_LOG("Using %s:%d.%d.%d\n", libraryName, zgsrevision, zgsbuild, zgsminor); + ERROR_LOG("creating zerogs\n"); + //if (conf.record) recOpen(); + if( !ZeroGS::Create(conf.width, conf.height) ) + return -1; + + ERROR_LOG("initialization successful\n"); + + if( conf.bilinear == 2 ) { + ZeroGS::AddMessage("bilinear filtering - forced", 1000); + } + else if( conf.bilinear == 1 ) { + ZeroGS::AddMessage("bilinear filtering - normal", 1000); + } + if( conf.aa ) { + char strtitle[64]; + sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa]); + ZeroGS::AddMessage(strtitle,1000); + } + + GS_LOG("GSopen ok\n"); + + gs.path1.mode = 0; + gs.path2.mode = 0; + gs.path3.mode = 0; + luPerfFreq = 1; + + return 0; +} + +void ProcessMessages() +{ + FUNCLOG + + XEvent event; + // check resizing + while(XCheckTypedEvent(GLWin.dpy, ConfigureNotify, &event)) { + if ((event.xconfigure.width != GLWin.width) || (event.xconfigure.height != GLWin.height)) { + ZeroGS::ChangeWindowSize(event.xconfigure.width, event.xconfigure.height); + GLWin.width = event.xconfigure.width; + GLWin.height = event.xconfigure.height; + } + } + + if ( THR_KeyEvent ) { // This values was passed from GSKeyEvents witch could be in another thread + int my_KeyEvent = THR_KeyEvent; + bool my_bShift = THR_bShift; + THR_KeyEvent = 0; + switch ( my_KeyEvent ) { + case XK_F5: + OnKeyboardF5(my_bShift); + break; + case XK_F6: + OnKeyboardF6(my_bShift); + break; + case XK_F7: + OnKeyboardF7(my_bShift); + break; + case XK_F9: + OnKeyboardF9(my_bShift); + break; + } + } +} + +#endif // linux + +void CALLBACK GSclose() { + FUNCLOG + + ZeroGS::Destroy(1); + +#ifdef _WIN32 + if( GShwnd != NULL ) { + DestroyWindow(GShwnd); + GShwnd = NULL; + } +#else + if( GLWin.dpy != NULL ) { + XCloseDisplay(GLWin.dpy); + GLWin.dpy = NULL; + } +#endif + SaveStateFile = NULL; + SaveStateExists = true; // default value +} + +void CALLBACK GSirqCallback(void (*callback)()) { + FUNCLOG + + GSirq = callback; +} + +void CALLBACK GSwriteCSR(u32 write) +{ + FUNCLOG + + gs.CSRw = write; +} + +void CALLBACK GSchangeSaveState(int newstate, const char* filename) +{ + FUNCLOG + + char str[255]; + sprintf(str, "save state %d", newstate); + ZeroGS::AddMessage(str); + CurrentSavestate = newstate; + + SaveStateFile = filename; + SaveStateExists = (access(SaveStateFile, 0) == 0); +} + +void CALLBACK GSmakeSnapshot(char *path) +{ + FUNCLOG + + FILE *bmpfile; + char filename[256]; + u32 snapshotnr = 0; + + // increment snapshot value & try to get filename + for (;;) { + snapshotnr++; + + sprintf(filename,"%ssnap%03ld.%s", path, snapshotnr, (conf.options&GSOPTION_TGASNAP)?"bmp":"jpg"); + + bmpfile=fopen(filename,"rb"); + if (bmpfile == NULL) break; + fclose(bmpfile); + } + + // try opening new snapshot file + if((bmpfile=fopen(filename,"wb"))==NULL) { + char strdir[255]; + +#ifdef _WIN32 + sprintf(strdir, "%s", path); + CreateDirectory(strdir, NULL); +#else + sprintf(strdir, "mkdir %s", path); + system(strdir); +#endif + + if((bmpfile=fopen(filename,"wb"))==NULL) return; + } + + fclose(bmpfile); + + // get the bits + ZeroGS::SaveSnapshot(filename); +} + +int UPDATE_FRAMES = 16; +int g_nFrame = 0; +int g_nRealFrame = 0; + +float fFPS = 0; + +void CALLBACK GSvsync(int interlace) +{ + FUNCLOG + + GS_LOG("\nGSvsync\n\n"); + + static u32 dwTime = timeGetTime(); + static int nToNextUpdate = 1; + char strtitle[256]; + + GL_REPORT_ERRORD(); + + g_nRealFrame++; + + ZeroGS::RenderCRTC(!interlace); + + ProcessMessages(); + + if( --nToNextUpdate <= 0 ) { + + u32 d = timeGetTime(); + fFPS = UPDATE_FRAMES * 1000.0f / (float)max(d-dwTime,1); + dwTime = d; + g_nFrame += UPDATE_FRAMES; + +#ifdef RELEASE_TO_PUBLIC + const char* g_pShaders[4] = { "full", "reduced", "accurate", "accurate-reduced" }; + const char* g_pInterlace[3] = { "interlace 0 |", "interlace 1 |", "" }; + const char* g_pBilinear[3] = { "", "bilinear |", "forced bilinear |" }; + if (SaveStateFile != NULL && !SaveStateExists) + SaveStateExists = (access(SaveStateFile, 0) == 0); + else + SaveStateExists = true; + + sprintf(strtitle, "ZZ Open GL 0.%d.%d | %.1f fps | %s%s%s savestate %d%s | shaders %s | (%.1f)", zgsbuild, zgsminor, fFPS, + g_pInterlace[conf.interlace], g_pBilinear[conf.bilinear], + (conf.aa >= conf.negaa) ? (conf.aa ? s_aa[conf.aa - conf.negaa] : "") : (conf.negaa ? s_naa[conf.negaa - conf.aa] : ""), + CurrentSavestate, (SaveStateExists ? "": "*" ), + g_pShaders[g_nPixelShaderVer], (ppf&0xfffff)/(float)UPDATE_FRAMES); +#else + sprintf(strtitle, "%d | %.1f fps (sk:%d%%) | g: %.1f, t: %.1f, a: %.1f, r: %.1f | p: %.1f | tex: %d %d (%d kbpf)", g_nFrame, fFPS, + 100*g_nFramesSkipped/g_nFrame, + g_nGenVars/(float)UPDATE_FRAMES, g_nTexVars/(float)UPDATE_FRAMES, g_nAlphaVars/(float)UPDATE_FRAMES, + g_nResolve/(float)UPDATE_FRAMES, (ppf&0xfffff)/(float)UPDATE_FRAMES, + ZeroGS::g_MemTargs.listTargets.size(), ZeroGS::g_MemTargs.listClearedTargets.size(), g_TransferredToGPU>>10); + //_snprintf(strtitle, 512, "%x %x", *(int*)(g_pbyGSMemory + 256 * 0x3e0c + 4), *(int*)(g_pbyGSMemory + 256 * 0x3e04 + 4)); + +#endif + +// if( g_nFrame > 100 && fFPS > 60.0f ) { +// DEBUG_LOG("set profile\n"); +// g_bWriteProfile = 1; +// } + +#ifdef _WIN32 + if( !(conf.options&GSOPTION_FULLSCREEN) ) + SetWindowText(GShwnd, strtitle); +#else // linux + XTextProperty prop; + memset(&prop, 0, sizeof(prop)); + char* ptitle = strtitle; + if( XStringListToTextProperty(&ptitle, 1, &prop) ) + XSetWMName(GLWin.dpy, GLWin.win, &prop); + XFree(prop.value); +#endif + + if( fFPS < 16 ) UPDATE_FRAMES = 4; + else if( fFPS < 32 ) UPDATE_FRAMES = 8; + else UPDATE_FRAMES = 16; + + nToNextUpdate = UPDATE_FRAMES; + + g_TransferredToGPU = 0; + g_nGenVars = 0; + g_nTexVars = 0; + g_nAlphaVars = 0; + g_nResolve = 0; + ppf = 0; + g_nFramesSkipped = 0; + } + +#ifndef RELEASE_TO_PUBLIC + if( g_bWriteProfile ) { + //g_bWriteProfile = 0; + DVProfWrite("prof.txt", UPDATE_FRAMES); + DVProfClear(); + } +#endif + GL_REPORT_ERRORD(); +} + +void GIFtag(pathInfo *path, u32 *data) { + FUNCLOG + + path->tag.nloop = data[0] & 0x7fff; + path->tag.eop = (data[0] >> 15) & 0x1; + u32 tagpre = (data[1] >> 14) & 0x1; + u32 tagprim = (data[1] >> 15) & 0x7ff; + u32 tagflg = (data[1] >> 26) & 0x3; + path->tag.nreg = (data[1] >> 28)<<2; + + if (path->tag.nreg == 0) path->tag.nreg = 64; + + gs.q = 1; + +// GS_LOG("GIFtag: %8.8lx_%8.8lx_%8.8lx_%8.8lx: EOP=%d, NLOOP=%x, FLG=%x, NREG=%d, PRE=%d\n", +// data[3], data[2], data[1], data[0], +// path->tag.eop, path->tag.nloop, tagflg, path->tag.nreg, tagpre); + + path->mode = tagflg+1; + + switch (tagflg) { + case 0x0: + path->regs = *(u64 *)(data+2); + path->regn = 0; + if (tagpre) + GIFRegHandlerPRIM((u32*)&tagprim); + + break; + + case 0x1: + path->regs = *(u64 *)(data+2); + path->regn = 0; + break; + } +} + +void _GSgifPacket(pathInfo *path, u32 *pMem) { // 128bit + FUNCLOG + + int reg = (int)((path->regs >> path->regn) & 0xf); + g_GIFPackedRegHandlers[reg](pMem); + + path->regn += 4; + if (path->tag.nreg == path->regn) { + path->regn = 0; + path->tag.nloop--; + } +} + +void _GSgifRegList(pathInfo *path, u32 *pMem) { // 64bit + FUNCLOG + + int reg; + + reg = (int)((path->regs >> path->regn) & 0xf); + + g_GIFRegHandlers[reg](pMem); + path->regn += 4; + if (path->tag.nreg == path->regn) { + path->regn = 0; + path->tag.nloop--; + } +} + +static int nPath3Hack = 0; + +void CALLBACK GSgetLastTag(u64* ptag) +{ + FUNCLOG + + *(u32*)ptag = nPath3Hack; + nPath3Hack = 0; +} + +void _GSgifTransfer(pathInfo *path, u32 *pMem, u32 size) +{ + FUNCLOG + +#ifdef _WIN32 + assert( g_hCurrentThread == GetCurrentThread() ); +#endif + +#ifdef _DEBUG + if( conf.log & 0x20 ) { + static int nSaveIndex=0; + GS_LOG("%d: p:%d %x\n", nSaveIndex++, (path==&gs.path3)?3:(path==&gs.path2?2:1), size); + int vals[4] = {0}; + for(int i = 0; i < size; i++) { + for(int j = 0; j < 4; ++j ) + vals[j] ^= pMem[4*i+j]; + } + GS_LOG("%x %x %x %x\n", vals[0], vals[1], vals[2], vals[3]); + } +#endif + + while(size > 0) + { + //LOG(_T("Transfer(%08x, %d) START\n"), pMem, size); + if (path->tag.nloop == 0) + { + GIFtag(path, pMem); + pMem+= 4; + size--; + + if ((g_GameSettings & GAME_PATH3HACK) && path == &gs.path3 && gs.path3.tag.eop) + nPath3Hack = 1; + + if (path == &gs.path1) + { + if (path->mode == 1) + { + // check if 0xb is in any reg, if yes, exit (kh2) + for(int i = 0; i < path->tag.nreg; i += 4) + { + if (((path->regs >> i)&0xf) == 11) + { + ERROR_LOG_SPAM("Invalid unpack type\n"); + path->tag.nloop = 0; + return; + } + } + } + } + + if(path->tag.nloop == 0 ) + { + if( path == &gs.path1 ) + { + // ffx hack + if( path->tag.eop ) + return; + continue; + } + + if( !path->tag.eop ) + { + //DEBUG_LOG("continuing from eop\n"); + continue; + } + + // Issue 174 fix! + continue; + } + } + + switch(path->mode) { + case 1: // PACKED + { + assert( path->tag.nloop > 0 ); + for(; size > 0; size--, pMem += 4) + { + int reg = (int)((path->regs >> path->regn) & 0xf); + + g_GIFPackedRegHandlers[reg](pMem); + + path->regn += 4; + if (path->tag.nreg == path->regn) + { + path->regn = 0; + if( path->tag.nloop-- <= 1 ) + { + size--; + pMem += 4; + break; + } + } + } + break; + } + case 2: // REGLIST + { + //GS_LOG("%8.8x%8.8x %d L\n", ((u32*)&gs.regs)[1], *(u32*)&gs.regs, path->tag.nreg/4); + assert( path->tag.nloop > 0 ); + size *= 2; + for(; size > 0; pMem+= 2, size--) + { + int reg = (int)((path->regs >> path->regn) & 0xf); + g_GIFRegHandlers[reg](pMem); + path->regn += 4; + if (path->tag.nreg == path->regn) + { + path->regn = 0; + if( path->tag.nloop-- <= 1 ) + { + size--; + pMem += 2; + break; + } + } + } + + if( size & 1 ) pMem += 2; + size /= 2; + break; + } + case 3: // GIF_IMAGE (FROM_VFRAM) + case 4: // Used in the DirectX version, so we'll use it here too. + { + if(gs.imageTransfer >= 0 && gs.imageTransfer <= 1) + { + int process = min((int)size, path->tag.nloop); + + if( process > 0 ) + { + if ( gs.imageTransfer ) + ZeroGS::TransferLocalHost(pMem, process); + else + ZeroGS::TransferHostLocal(pMem, process*4); + + path->tag.nloop -= process; + pMem += process*4; size -= process; + + assert( size == 0 || path->tag.nloop == 0 ); + } + break; + } + else + { + // simulate + int process = min((int)size, path->tag.nloop); + path->tag.nloop -= process; + pMem += process*4; size -= process; + } + + break; + } + default: // GIF_IMAGE + GS_LOG("*** WARNING **** Unexpected GIFTag flag\n"); + assert(0); + path->tag.nloop = 0; + break; + } + + if( path == &gs.path1 && path->tag.eop ) + return; + } + + // This is case when not all data was readed from one try: VU1 to much data. + // So we should redone reading from start + if (path == &gs.path1 && size == 0 && path->tag.nloop > 0) { + ERROR_LOG_SPAMA("VU1 too much data, ignore if gfx are fine %d\n", path->tag.nloop) +// TODO: this code is not working correctly. Anyway, ringing work only in single-threadred mode. +// _GSgifTransfer(&gs.path1, (u32*)((u8*)pMem-0x4000), (0x4000)/16); + } +} + +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size) +{ + FUNCLOG + + //GS_LOG("GSgifTransfer2 size = %lx (mode %d, gs.path2.tag.nloop = %d)\n", size, gs.path2.mode, gs.path2.tag.nloop); + + _GSgifTransfer(&gs.path2, pMem, size); +} + +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size) +{ + FUNCLOG + + //GS_LOG("GSgifTransfer3 size = %lx (mode %d, gs.path3.tag.nloop = %d)\n", size, gs.path3.mode, gs.path3.tag.nloop); + + nPath3Hack = 0; + _GSgifTransfer(&gs.path3, pMem, size); +} + +static int count = 0; +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr) +{ + FUNCLOG + + pathInfo *path = &gs.path1; + + //GS_LOG("GSgifTransfer1 0x%x (mode %d)\n", addr, path->mode); + +// addr &= 0x3fff; + +#ifdef _DEBUG + PRIM_LOG("count: %d\n", count); + count++; +#endif + + gs.path1.tag.nloop = 0; + gs.path1.tag.eop = 0; + _GSgifTransfer(&gs.path1, (u32*)((u8*)pMem+addr), (0x4000 - addr)/16); + + if( !gs.path1.tag.eop && gs.path1.tag.nloop > 0 ) { + assert( (addr&0xf) == 0 ); //BUG + gs.path1.tag.nloop = 0; + ERROR_LOG("Transfer1 - 2\n"); + return; + } +} + +void CALLBACK GSreadFIFO(u64 *pMem) +{ + FUNCLOG + + //GS_LOG("GSreadFIFO\n"); + + ZeroGS::TransferLocalHost((u32*)pMem, 1); +} + +void CALLBACK GSreadFIFO2(u64 *pMem, int qwc) +{ + FUNCLOG + + //GS_LOG("GSreadFIFO2\n"); + + ZeroGS::TransferLocalHost((u32*)pMem, qwc); +} + +int CALLBACK GSsetupRecording(int start, void* pData) +{ + FUNCLOG + + if( start ) { + if( conf.options & GSOPTION_CAPTUREAVI ) + return 1; + ZeroGS::StartCapture(); + conf.options |= GSOPTION_CAPTUREAVI; + WARN_LOG("ZeroGS: started recording at zerogs.avi\n"); + } + else { + if( !(conf.options & GSOPTION_CAPTUREAVI) ) + return 1; + conf.options &= ~GSOPTION_CAPTUREAVI; + ZeroGS::StopCapture(); + WARN_LOG("ZeroGS: stopped recording\n"); + } + + return 1; +} + +s32 CALLBACK GSfreeze(int mode, freezeData *data) +{ + FUNCLOG + + switch (mode) + { + case FREEZE_LOAD: + if (!ZeroGS::Load(data->data)) ERROR_LOG("GS: Bad load format!"); + g_nRealFrame += 100; + break; + case FREEZE_SAVE: + ZeroGS::Save(data->data); + break; + case FREEZE_SIZE: + data->size = ZeroGS::Save(NULL); + break; + default: + break; + } + + return 0; +} + +//////////////////// +// Small profiler // +//////////////////// +#include +#include +#include +using namespace std; + +#ifdef _WIN32 + +__forceinline u64 GET_PROFILE_TIME() +{ + LARGE_INTEGER lu; + QueryPerformanceCounter(&lu); + return lu.QuadPart; +} +#else +#define GET_PROFILE_TIME() //GetCpuTick() +#endif + + +struct DVPROFSTRUCT; + +struct DVPROFSTRUCT +{ + struct DATA + { + DATA(u64 time, u32 user = 0) : dwTime(time), dwUserData(user) {} + DATA() : dwTime(0), dwUserData(0) {} + + u64 dwTime; + u32 dwUserData; + }; + + ~DVPROFSTRUCT() { + list::iterator it = listpChild.begin(); + while(it != listpChild.end() ) { + SAFE_DELETE(*it); + ++it; + } + } + + list listTimes; // before DVProfEnd is called, contains the global time it started + // after DVProfEnd is called, contains the time it lasted + // the list contains all the tracked times + char pname[256]; + + list listpChild; // other profilers called during this profiler period +}; + +struct DVPROFTRACK +{ + u32 dwUserData; + DVPROFSTRUCT::DATA* pdwTime; + DVPROFSTRUCT* pprof; +}; + +list g_listCurTracking; // the current profiling functions, the back element is the + // one that will first get popped off the list when DVProfEnd is called + // the pointer is an element in DVPROFSTRUCT::listTimes +list g_listProfilers; // the current profilers, note that these are the parents + // any profiler started during the time of another is held in + // DVPROFSTRUCT::listpChild +list g_listAllProfilers; // ignores the hierarchy, pointer to elements in g_listProfilers + +void DVProfRegister(char* pname) +{ + if( !g_bWriteProfile ) + return; + + list::iterator it = g_listAllProfilers.begin(); + +// while(it != g_listAllProfilers.end() ) { +// +// if( _tcscmp(pname, (*it)->pname) == 0 ) { +// (*it)->listTimes.push_back(timeGetTime()); +// DVPROFTRACK dvtrack; +// dvtrack.pdwTime = &(*it)->listTimes.back(); +// dvtrack.pprof = *it; +// g_listCurTracking.push_back(dvtrack); +// return; +// } +// +// ++it; +// } + + // else add in a new profiler to the appropriate parent profiler + DVPROFSTRUCT* pprof = NULL; + + if( g_listCurTracking.size() > 0 ) { + assert( g_listCurTracking.back().pprof != NULL ); + g_listCurTracking.back().pprof->listpChild.push_back(new DVPROFSTRUCT()); + pprof = g_listCurTracking.back().pprof->listpChild.back(); + } + else { + g_listProfilers.push_back(DVPROFSTRUCT()); + pprof = &g_listProfilers.back(); + } + + strncpy(pprof->pname, pname, 256); + + // setup the profiler for tracking + pprof->listTimes.push_back(DVPROFSTRUCT::DATA(GET_PROFILE_TIME())); + + DVPROFTRACK dvtrack; + dvtrack.pdwTime = &pprof->listTimes.back(); + dvtrack.pprof = pprof; + dvtrack.dwUserData = 0; + + g_listCurTracking.push_back(dvtrack); + + // add to all profiler list + g_listAllProfilers.push_back(pprof); +} + +void DVProfEnd(u32 dwUserData) +{ + if( !g_bWriteProfile ) + return; + B_RETURN( g_listCurTracking.size() > 0 ); + + DVPROFTRACK dvtrack = g_listCurTracking.back(); + + assert( dvtrack.pdwTime != NULL && dvtrack.pprof != NULL ); + + dvtrack.pdwTime->dwTime = 1000000 * (GET_PROFILE_TIME()- dvtrack.pdwTime->dwTime) / luPerfFreq; + dvtrack.pdwTime->dwUserData= dwUserData; + + g_listCurTracking.pop_back(); +} + +struct DVTIMEINFO +{ + DVTIMEINFO() : uInclusive(0), uExclusive(0) {} + u64 uInclusive, uExclusive; +}; + +map mapAggregateTimes; + +u64 DVProfWriteStruct(FILE* f, DVPROFSTRUCT* p, int ident) +{ + fprintf(f, "%*s%s - ", ident, "", p->pname); + + list::iterator ittime = p->listTimes.begin(); + + u32 utime = 0; + + while(ittime != p->listTimes.end() ) { + utime += (u32)ittime->dwTime; + + if( ittime->dwUserData ) + fprintf(f, "time: %d, user: 0x%8.8x", (u32)ittime->dwTime, ittime->dwUserData); + else + fprintf(f, "time: %d", (u32)ittime->dwTime); + ++ittime; + } + + mapAggregateTimes[p->pname].uInclusive += utime; + + fprintf(f, "\n"); + + list::iterator itprof = p->listpChild.begin(); + + u32 uex = utime; + while(itprof != p->listpChild.end() ) { + + uex -= DVProfWriteStruct(f, *itprof, ident+4); + ++itprof; + } + + mapAggregateTimes[p->pname].uExclusive += uex; + return utime; +} + +void DVProfWrite(char* pfilename, u32 frames) +{ + assert( pfilename != NULL ); + FILE* f = fopen(pfilename, "wb"); + + mapAggregateTimes.clear(); + list::iterator it = g_listProfilers.begin(); + + while(it != g_listProfilers.end() ) { + DVProfWriteStruct(f, &(*it), 0); + ++it; + } + + { + map::iterator it; + fprintf(f, "\n\n-------------------------------------------------------------------\n\n"); + + u64 uTotal[2] = {0}; + double fiTotalTime[2]; + + for(it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) { + uTotal[0] += it->second.uExclusive; + uTotal[1] += it->second.uInclusive; + } + + fprintf(f, "total times (%d): ex: %Lu ", frames, uTotal[0]/frames); + fprintf(f, "inc: %Lu\n", uTotal[1]/frames); + + fiTotalTime[0] = 1.0 / (double)uTotal[0]; + fiTotalTime[1] = 1.0 / (double)uTotal[1]; + + // output the combined times + for(it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) { + fprintf(f, "%s - ex: %f inc: %f\n", it->first.c_str(), (double)it->second.uExclusive * fiTotalTime[0], + (double)it->second.uInclusive * fiTotalTime[1]); + } + } + + + fclose(f); +} + +void DVProfClear() +{ + g_listCurTracking.clear(); + g_listProfilers.clear(); + g_listAllProfilers.clear(); +} diff --git a/plugins/zzogl-pg/opengl/Linux/CMakeLists.txt b/plugins/zzogl-pg/opengl/Linux/CMakeLists.txt new file mode 100644 index 0000000000..ad3698d43a --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/CMakeLists.txt @@ -0,0 +1,8 @@ +project(ZeroGSLinux) + +# maybe less is possible but i'm writing this on cmake 2.6 :) +cmake_minimum_required(VERSION 2.6) + +include_directories(${ZeroGSLinux_SOURCE_DIR}/..) + +add_library(ZeroGSLinux callbacks.c Conf.cpp interface.c Linux.cpp support.c) diff --git a/plugins/zzogl-pg/opengl/Linux/Conf.cpp b/plugins/zzogl-pg/opengl/Linux/Conf.cpp new file mode 100644 index 0000000000..2b0070bc6d --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/Conf.cpp @@ -0,0 +1,110 @@ +/* GSsoft + * Copyright (C) 2002-2004 GSsoft Team + * + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include "GS.h" + +void SaveConfig() +{ + const std::string iniFile( s_strIniPath + "zerogs.ini" ); + FILE* f = fopen(iniFile.c_str(),"w"); + + if (f == NULL) + { + printf("failed to open %s\n", iniFile.c_str()); + return; + } + + fprintf(f, "interlace = %hhx\n", conf.interlace); + fprintf(f, "mrtdepth = %hhx\n", conf.mrtdepth); + fprintf(f, "options = %x\n", conf.options); //u32 + fprintf(f, "bilinear = %hhx\n", conf.bilinear); + fprintf(f, "aliasing = %hhx\n", conf.aa); + fprintf(f, "gamesettings = %x\n", conf.gamesettings); //u32 + fclose(f); +} + +void LoadConfig() +{ + char cfg[255]; + + memset(&conf, 0, sizeof(conf)); + conf.interlace = 0; // on, mode 1 + conf.mrtdepth = 1; + conf.options = 0; + conf.bilinear = 1; + conf.width = 640; + conf.height = 480; + conf.aa = 0; + + const std::string iniFile( s_strIniPath + "zerogs.ini" ); + FILE* f = fopen(iniFile.c_str(), "r"); + if (f == NULL) + { + printf("failed to open %s\n", iniFile.c_str()); + SaveConfig();//save and return + return; + } + fscanf(f, "interlace = %hhx\n", &conf.interlace); + fscanf(f, "mrtdepth = %hhx\n", &conf.mrtdepth); + fscanf(f, "options = %x\n", &conf.options);//u32 + fscanf(f, "bilinear = %hhx\n", &conf.bilinear); + fscanf(f, "aliasing = %hhx\n", &conf.aa); + fscanf(f, "gamesettings = %x\n", &conf.gamesettings);//u32 + fclose(f); + + // filter bad files + if ((conf.aa < 0) || (conf.aa > 4)) conf.aa = 0; + + conf.isWideScreen = conf.options & GSOPTION_WIDESCREEN; + switch(conf.options & GSOPTION_WINDIMS) + { + case GSOPTION_WIN640: + conf.width = 640; + conf.height = conf.isWideScreen ? 360 : 480; + break; + case GSOPTION_WIN800: + conf.width = 800; + conf.height = conf.isWideScreen ? 450 : 600; + break; + case GSOPTION_WIN1024: + conf.width = 1024; + conf.height = conf.isWideScreen ? 576 : 768; + break; + case GSOPTION_WIN1280: + conf.width = 1280; + conf.height = conf.isWideScreen ? 720 : 960; + break; + } + + // turn off all hacks by default + conf.options &= ~(GSOPTION_WIREFRAME | GSOPTION_CAPTUREAVI); + conf.options |= GSOPTION_LOADED; + + if( conf.width <= 0 || conf.height <= 0 ) + { + conf.width = 640; + conf.height = 480; + } +} + diff --git a/plugins/zzogl-pg/opengl/Linux/Linux.cpp b/plugins/zzogl-pg/opengl/Linux/Linux.cpp new file mode 100644 index 0000000000..0f35001b98 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/Linux.cpp @@ -0,0 +1,441 @@ +/* ZeroGS + * Copyright (C) 2002-2004 GSsoft Team + * + * 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 + */ + +#include +#include +#include +#include +#include + +#include "GS.h" + +extern "C" { +#include "interface.h" +#include "support.h" +#include "callbacks.h" +} + +#include "Linux.h" + +#include + +GtkWidget *Conf, *Logging, *About; +GList *fresl, *wresl, *cachesizel, *codecl, *filtersl; + +static int prevbilinearfilter; + +struct confOptsStruct +{ + int value; + const char *desc; +} confOpts; + +static map mapConfOpts; + +void CALLBACK GSkeyEvent(keyEvent *ev) +{ + //static bool bShift = false; + static bool bAlt = false; + + switch(ev->evt) { + case KEYPRESS: + switch(ev->key) { + case XK_F5: + case XK_F6: + case XK_F7: + case XK_F9: + THR_KeyEvent = ev->key ; + break; + case XK_Escape: + if (conf.options & GSOPTION_FULLSCREEN) + GSclose(); + break; + case XK_Shift_L: + case XK_Shift_R: + //bShift = true; + THR_bShift = true; + break; + case XK_Alt_L: + case XK_Alt_R: + bAlt = true; + break; + } + break; + case KEYRELEASE: + switch(ev->key) { + case XK_Shift_L: + case XK_Shift_R: + //bShift = false; + THR_bShift = false; + break; + case XK_Alt_L: + case XK_Alt_R: + bAlt = false; + break; + } + } +} + +void OnConf_Ok(GtkButton *button, gpointer user_data) +{ + GtkWidget *Btn; + GtkWidget *treeview; + GtkTreeModel *treemodel; + GtkTreeIter treeiter; + gboolean treeoptval; + gchar *gbuf; + char *str; + int i; + + conf.bilinear = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkBilinear"))); + // restore + if (conf.bilinear && prevbilinearfilter) + conf.bilinear = prevbilinearfilter; + + //conf.mrtdepth = 1;//IsDlgButtonChecked(hW, IDC_CONFIG_DEPTHWRITE); + + if is_checked(Conf, "radioAANone") + conf.aa = 0; + else if is_checked(Conf, "radioAA2X") + conf.aa = 1; + else if is_checked(Conf, "radioAA4X") + conf.aa = 2; + else if is_checked(Conf, "radioAA8X") + conf.aa = 3; + else + conf.aa = 4; + conf.negaa = 0; + + conf.options = 0; + conf.options |= is_checked(Conf, "checkAVI") ? GSOPTION_CAPTUREAVI : 0; + conf.options |= is_checked(Conf, "checkWireframe") ? GSOPTION_WIREFRAME : 0; + conf.options |= is_checked(Conf, "checkfullscreen") ? GSOPTION_FULLSCREEN : 0; + conf.options |= is_checked(Conf, "checkwidescreen") ? GSOPTION_WIDESCREEN : 0; + conf.options |= is_checked(Conf, "checkTGA") ? GSOPTION_TGASNAP : 0; + + if is_checked(Conf, "radiointerlace0") + conf.interlace = 0; + else if is_checked(Conf, "radiointerlace1") + conf.interlace = 1; + else + conf.interlace = 2; + + //------- get advanced options from the treeview model -------// + treeview = lookup_widget(Conf,"treeview1"); + treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); + gtk_tree_model_get_iter_first(treemodel, &treeiter); + + conf.gamesettings = 0; + for(map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) + { + treeoptval = FALSE; + gtk_tree_model_get(treemodel, &treeiter, 0, &treeoptval, -1); + + if(treeoptval) conf.gamesettings |= it->second.value; + + gtk_tree_model_iter_next(treemodel,&treeiter); + } + + GSsetGameCRC(0, conf.gamesettings); + //---------- done getting advanced options ---------// + + if is_checked(Conf, "radioSize640") + conf.options |= GSOPTION_WIN640; + else if is_checked(Conf, "radioSize800") + conf.options |= GSOPTION_WIN800; + else if is_checked(Conf, "radioSize1024") + conf.options |= GSOPTION_WIN1024; + else if is_checked(Conf, "radioSize1280") + conf.options |= GSOPTION_WIN1280; + + SaveConfig(); + + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel(GtkButton *button, gpointer user_data) +{ + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void CALLBACK GSconfigure() +{ + char name[32]; + char descbuf[255]; + int nmodes, i; + bool itval; + GtkWidget *treeview; + GtkCellRenderer *treerend; + GtkListStore *treestore;//Gets typecast as GtkTreeModel as needed. + GtkTreeIter treeiter; + GtkTreeViewColumn *treecol; + + char strcurdir[256]; + getcwd(strcurdir, 256); + + if (!(conf.options & GSOPTION_LOADED)) LoadConfig(); + Conf = create_Config(); + + // fixme; Need to check "checkInterlace" as well. + if (conf.interlace == 0) + set_checked(Conf, "radiointerlace0", true); + else if (conf.interlace == 1) + set_checked(Conf, "radiointerlace1", true); + else + set_checked(Conf, "radionointerlace", true); + + set_checked(Conf, "checkBilinear", !!conf.bilinear); + //set_checked(Conf, "checkbutton6", conf.mrtdepth); + set_checked(Conf, "radioAANone", (conf.aa==0)); + set_checked(Conf, "radioAA2X", (conf.aa==1)); + set_checked(Conf, "radioAA4X", (conf.aa==2)); + set_checked(Conf, "radioAA8X", (conf.aa==3)); + set_checked(Conf, "radioAA16X", (conf.aa==4)); + set_checked(Conf, "checkWireframe", (conf.options&GSOPTION_WIREFRAME)?1:0); + set_checked(Conf, "checkAVI", (conf.options&GSOPTION_CAPTUREAVI)?1:0); + set_checked(Conf, "checkfullscreen", (conf.options&GSOPTION_FULLSCREEN)?1:0); + set_checked(Conf, "checkwidescreen", (conf.options&GSOPTION_WIDESCREEN)?1:0); + set_checked(Conf, "checkTGA", (conf.options&GSOPTION_TGASNAP)?1:0); + + set_checked(Conf, "radioSize640", ((conf.options&GSOPTION_WINDIMS)>>4)==0); + set_checked(Conf, "radioSize800", ((conf.options&GSOPTION_WINDIMS)>>4)==1); + set_checked(Conf, "radioSize1024", ((conf.options&GSOPTION_WINDIMS)>>4)==2); + set_checked(Conf, "radioSize1280", ((conf.options&GSOPTION_WINDIMS)>>4)==3); + + prevbilinearfilter = conf.bilinear; + + //--------- Let's build a treeview for our advanced options! --------// + treeview = lookup_widget(Conf,"treeview1"); + treestore = gtk_list_store_new(2,G_TYPE_BOOLEAN, G_TYPE_STRING); + + //setup columns in treeview + //COLUMN 0 is the checkboxes + treecol = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(treecol, "Select"); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), treecol); + treerend = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(treecol, treerend, TRUE); + gtk_tree_view_column_add_attribute(treecol, treerend, "active", 0);//link 'active' attrib to first column of model + g_object_set(treerend, "activatable", TRUE, NULL);//set 'activatable' attrib true by default for all rows regardless of model. + g_signal_connect(treerend, "toggled", (GCallback) OnToggle_advopts, treestore);//set a global callback, we also pass a reference to our treestore. + + //COLUMN 1 is the text descriptions + treecol = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(treecol, "Description"); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), treecol); + treerend = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(treecol, treerend, TRUE); + gtk_tree_view_column_add_attribute(treecol, treerend, "text", 1);//link 'text' attrib to second column of model + + //setup the model with all our rows of option data + mapConfOpts.clear(); + confOpts.value = 0x00000001; + confOpts.desc = "Tex Target checking - 00000001\nLego Racers"; + mapConfOpts["00000001"] = confOpts; + confOpts.value = 0x00000002; + confOpts.desc = "Auto reset targs - 00000002\nShadow Hearts, Samurai Warriors. Use when game is slow and toggling AA fixes it."; + mapConfOpts["00000002"] = confOpts; + confOpts.value = 0x00000010; + confOpts.desc = "No target resolves - 00000010\nStops all resolving of targets. Try this first for really slow games. Dark Cloud 1"; + mapConfOpts["00000010"] = confOpts; + confOpts.value = 0x00000020; + confOpts.desc = "Exact color testing - 00000020\nFixes overbright or shadow/black artifacts (Crash 'n Burn)."; + mapConfOpts["00000020"] = confOpts; + confOpts.value = 0x00000040; + confOpts.desc = "No color clamping - 00000040\nSpeeds up games, but might be too bright or too dim."; + mapConfOpts["00000040"] = confOpts; + confOpts.value = 0x00000100; + confOpts.desc = "Alpha Fail hack - 00000100\nFor Sonic Unleashed, Shadow the Hedgehog, Ghost in the Shell. Remove vertical stripes or other coloring artefacts. Break Persona 4 and MGS3"; + mapConfOpts["00000100"] = confOpts; + confOpts.value = 0x00000200; + confOpts.desc = "Disable depth updates - 00000200"; + mapConfOpts["00000200"] = confOpts; + confOpts.value = 0x00000400; + confOpts.desc = "Resolve Hack #1 - 00000400\nKingdom Hearts. Speeds some games."; + mapConfOpts["00000400"] = confOpts; + confOpts.value = 0x00000800; + confOpts.desc = "Resolve Hack #2 - 00000800\nShadow Hearts, Urbz. Destroy FFX"; + mapConfOpts["00000800"] = confOpts; + confOpts.value = 0x00001000; + confOpts.desc = "No target CLUT - 00001000\nResident Evil 4, or foggy scenes."; + mapConfOpts["00001000"] = confOpts; + confOpts.value = 0x00002000; + confOpts.desc = "Disable stencil buffer - 00002000\nUsually safe to do for simple scenes. Harvest Moon"; + mapConfOpts["00002000"] = confOpts; + confOpts.value = 0x00008000; + confOpts.desc = "No depth resolve - 00008000\nMight give z buffer artifacts."; + mapConfOpts["00008000"] = confOpts; + confOpts.value = 0x00010000; + confOpts.desc = "Full 16 bit resolution - 00010000\nUse when half the screen is missing."; + mapConfOpts["00010000"] = confOpts; + confOpts.value = 0x00020000; + confOpts.desc = "Resolve Hack #3 - 00020000\nNeopets"; + mapConfOpts["00020000"] = confOpts; + confOpts.value = 0x00040000; + confOpts.desc = "Fast Update - 00040000\nOkami. Speeds some games. Needs for Sonic Unleashed"; + mapConfOpts["00040000"] = confOpts; + confOpts.value = 0x00080000; + confOpts.desc = "Disable alpha testing - 00080000"; + mapConfOpts["00080000"] = confOpts; + confOpts.value = 0x00100000; + confOpts.desc = "Enable Multiple RTs - 00100000"; + mapConfOpts["00100000"] = confOpts; + confOpts.value = 0x01000000; + confOpts.desc = "Specular Highlights - 01000000\nMakes xenosaga and Okage graphics faster by removing highlights"; + mapConfOpts["01000000"] = confOpts; + confOpts.value = 0x02000000; + confOpts.desc = "Partial targets - 02000000"; + mapConfOpts["00200000"] = confOpts; + confOpts.value = 0x04000000; + confOpts.desc = "Partial depth - 04000000"; + mapConfOpts["04000000"] = confOpts; + confOpts.value = 0x10000000; + confOpts.desc = "Gust fix, made gustgame more clean and fast - 10000000"; + mapConfOpts["10000000"] = confOpts; + confOpts.value = 0x20000000; + confOpts.desc = "No logarphmic Z, could decrease number of Z-artefacts - 20000000"; + mapConfOpts["20000000"] = confOpts; + + confOpts.value = 0x00000004; + confOpts.desc = "Interlace 2X - 00000004\nFixes 2x bigger screen (Gradius 3)."; + mapConfOpts["00000004"] = confOpts; + + for(map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) + { + gtk_list_store_append(treestore, &treeiter);//new row + itval = (conf.gamesettings&it->second.value)?TRUE:FALSE; + snprintf(descbuf, 254, "%s", it->second.desc); + gtk_list_store_set(treestore, &treeiter, 0, itval, 1, descbuf, -1); + } + + gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(treestore));//NB: store is cast as tree model. + g_object_unref(treestore);//allow model to be destroyed when the tree is destroyed. + + //don't select/highlight rows + gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), GTK_SELECTION_NONE); + //------treeview done -------// + + //Let's do it! + gtk_widget_show_all(Conf); + gtk_main(); +} + +void OnToggle_advopts(GtkCellRendererToggle *cell, gchar *path, gpointer user_data) +{ + GtkTreeIter treeiter; + gboolean val; + + gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(user_data), &treeiter, path); + gtk_tree_model_get(GTK_TREE_MODEL(user_data), &treeiter, 0, &val, -1); + val = !val; + gtk_list_store_set(GTK_LIST_STORE(user_data), &treeiter, 0, val, -1); + +} + +void OnAbout_Ok(GtkButton *button, gpointer user_data) +{ + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CALLBACK GSabout() +{ + About = create_About(); + + gtk_widget_show_all(About); + gtk_main(); +} + +s32 CALLBACK GStest() +{ + return 0; +} + +GtkWidget *MsgDlg; + +void OnMsg_Ok() +{ + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(const char *fmt, ...) +{ + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "GSsoft Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +void *SysLoadLibrary(char *lib) +{ + return dlopen(lib, RTLD_NOW | RTLD_GLOBAL); +} + +void *SysLoadSym(void *lib, char *sym) +{ + void *ret = dlsym(lib, sym); + if (ret == NULL) printf("null: %s\n", sym); + return dlsym(lib, sym); +} + +char *SysLibError() +{ + return dlerror(); +} + +void SysCloseLibrary(void *lib) +{ + dlclose(lib); +} diff --git a/plugins/zzogl-pg/opengl/Linux/Linux.h b/plugins/zzogl-pg/opengl/Linux/Linux.h new file mode 100644 index 0000000000..cfead3b7ee --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/Linux.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2002-2004 GSsoft Team + * + * 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 + */ + +#ifndef __LINUX_H__ +#define __LINUX_H__ +#endif + +void OnToggle_advopts(GtkCellRendererToggle *cell, gchar *path, gpointer user_data); + +#define is_checked(main_widget, widget_name) (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(main_widget, widget_name)))) +#define set_checked(main_widget,widget_name, state) gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(main_widget, widget_name)), state) diff --git a/plugins/zzogl-pg/opengl/Linux/Makefile b/plugins/zzogl-pg/opengl/Linux/Makefile new file mode 100644 index 0000000000..d738a199d5 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/Makefile @@ -0,0 +1,531 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Linux/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + +pkgdatadir = $(datadir)/ZZOgl-pg +pkgincludedir = $(includedir)/ZZOgl-pg +pkglibdir = $(libdir)/ZZOgl-pg +pkglibexecdir = $(libexecdir)/ZZOgl-pg +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = Linux +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libZeroGSLinux_a_AR = $(AR) $(ARFLAGS) +libZeroGSLinux_a_LIBADD = +am_libZeroGSLinux_a_OBJECTS = libZeroGSLinux_a-callbacks.$(OBJEXT) \ + libZeroGSLinux_a-Conf.$(OBJEXT) \ + libZeroGSLinux_a-interface.$(OBJEXT) \ + libZeroGSLinux_a-Linux.$(OBJEXT) \ + libZeroGSLinux_a-support.$(OBJEXT) +libZeroGSLinux_a_OBJECTS = $(am_libZeroGSLinux_a_OBJECTS) +DEFAULT_INCLUDES = -I. +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libZeroGSLinux_a_SOURCES) +DIST_SOURCES = $(libZeroGSLinux_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run aclocal-1.11 +AMTAR = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run tar +AUTOCONF = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run autoconf +AUTOHEADER = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run autoheader +AUTOMAKE = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run automake-1.11 +AWK = gawk +CC = gcc +CCAS = gcc +CCASDEPMODE = depmode=gcc3 +CCASFLAGS = -g -O2 +CCDEPMODE = depmode=gcc3 +CFLAGS = -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused -O2 -msse2 +CPP = gcc -E +CPPFLAGS = -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused -O2 -msse2 +CXX = gcc +CXXDEPMODE = depmode=gcc3 +CXXFLAGS = -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused -O2 -msse2 -fno-regmove +CYGPATH_W = echo +DEFS = -DPACKAGE_NAME=\"ZZOgl-pg\" -DPACKAGE_TARNAME=\"zzogl-pg\" -DPACKAGE_VERSION=\"0.1.0\" -DPACKAGE_STRING=\"ZZOgl-pg\ 0.1.0\" -DPACKAGE_BUGREPORT=\"arcum42@gmail.com\" -DPACKAGE_URL=\"\" -DPACKAGE=\"ZZOgl-pg\" -DVERSION=\"0.1.0\" -DNDEBUG=1 -DRELEASE_TO_PUBLIC=1 -DZEROGS_SSE2=1 -DHAVE_GL_GL_H=1 -DHAVE_GL_GLU_H=1 -DHAVE_GL_GLEXT_H=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_CG_CG_H=1 -DHAVE_CG_CGGL_H=1 -DHAVE_JPEGLIB_H=1 +DEPDIR = .deps +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /bin/grep -E +EXEEXT = +GREP = /bin/grep +GTK_CONFIG = pkg-config +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +LDFLAGS = +LIBOBJS = +LIBS = -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 -lGL -lGLU -lGLEW -ljpeg -lpthread -lstdc++ -lz -ldl -lXxf86vm -lCg -lCgGL +LTLIBOBJS = +MAKEINFO = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run makeinfo +MKDIR_P = /bin/mkdir -p +OBJEXT = o +PACKAGE = ZZOgl-pg +PACKAGE_BUGREPORT = arcum42@gmail.com +PACKAGE_NAME = ZZOgl-pg +PACKAGE_STRING = ZZOgl-pg 0.1.0 +PACKAGE_TARNAME = zzogl-pg +PACKAGE_URL = +PACKAGE_VERSION = 0.1.0 +PATH_SEPARATOR = : +RANLIB = ranlib +SET_MAKE = +SHARED_LDFLAGS = -shared +SHELL = /bin/sh +STRIP = +VERSION = 0.1.0 +ZEROGS_AGE = 0 +ZEROGS_CURRENT = 0 +ZEROGS_RELEASE = 0.1.0 +ZEROGS_REVISION = 1 +ZEROGS_SONAME = libzzoglpg.so.0.1.0 +abs_builddir = /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/Linux +abs_srcdir = /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/Linux +abs_top_builddir = /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl +abs_top_srcdir = /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl +ac_ct_CC = gcc +ac_ct_CXX = gcc +am__include = include +am__leading_dot = . +am__quote = +am__tar = ${AMTAR} chof - "$$tardir" +am__untar = ${AMTAR} xf - +bindir = ${exec_prefix}/bin +build_alias = +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +host_alias = +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = /bin/mkdir -p +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = +program_transform_name = s,x,x, +psdir = ${docdir} +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +so_ext = .so.0.1.0 +srcdir = . +sysconfdir = ${prefix}/etc +target_alias = +top_build_prefix = ../ +top_builddir = .. +top_srcdir = .. +noinst_LIBRARIES = libZeroGSLinux.a +#libZeroGSLinux_a_CPPFLAGS = -fPIC +#libZeroGSLinux_a_CXXFLAGS = -fPIC +#libZeroGSLinux_a_CFLAGS = -fPIC +INCLUDES = $(shell pkg-config --cflags gtk+-2.0) -I./../ -I./../../../../common/include +libZeroGSLinux_a_SOURCES = callbacks.c Conf.cpp interface.c Linux.cpp support.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Linux/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Linux/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libZeroGSLinux.a: $(libZeroGSLinux_a_OBJECTS) $(libZeroGSLinux_a_DEPENDENCIES) + -rm -f libZeroGSLinux.a + $(libZeroGSLinux_a_AR) libZeroGSLinux.a $(libZeroGSLinux_a_OBJECTS) $(libZeroGSLinux_a_LIBADD) + $(RANLIB) libZeroGSLinux.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/libZeroGSLinux_a-Conf.Po +include ./$(DEPDIR)/libZeroGSLinux_a-Linux.Po +include ./$(DEPDIR)/libZeroGSLinux_a-callbacks.Po +include ./$(DEPDIR)/libZeroGSLinux_a-interface.Po +include ./$(DEPDIR)/libZeroGSLinux_a-support.Po + +.c.o: + $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c $< + +.c.obj: + $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c `$(CYGPATH_W) '$<'` + +libZeroGSLinux_a-callbacks.o: callbacks.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-callbacks.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-callbacks.Tpo -c -o libZeroGSLinux_a-callbacks.o `test -f 'callbacks.c' || echo '$(srcdir)/'`callbacks.c + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-callbacks.Tpo $(DEPDIR)/libZeroGSLinux_a-callbacks.Po +# source='callbacks.c' object='libZeroGSLinux_a-callbacks.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-callbacks.o `test -f 'callbacks.c' || echo '$(srcdir)/'`callbacks.c + +libZeroGSLinux_a-callbacks.obj: callbacks.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-callbacks.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-callbacks.Tpo -c -o libZeroGSLinux_a-callbacks.obj `if test -f 'callbacks.c'; then $(CYGPATH_W) 'callbacks.c'; else $(CYGPATH_W) '$(srcdir)/callbacks.c'; fi` + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-callbacks.Tpo $(DEPDIR)/libZeroGSLinux_a-callbacks.Po +# source='callbacks.c' object='libZeroGSLinux_a-callbacks.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-callbacks.obj `if test -f 'callbacks.c'; then $(CYGPATH_W) 'callbacks.c'; else $(CYGPATH_W) '$(srcdir)/callbacks.c'; fi` + +libZeroGSLinux_a-interface.o: interface.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-interface.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-interface.Tpo -c -o libZeroGSLinux_a-interface.o `test -f 'interface.c' || echo '$(srcdir)/'`interface.c + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-interface.Tpo $(DEPDIR)/libZeroGSLinux_a-interface.Po +# source='interface.c' object='libZeroGSLinux_a-interface.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-interface.o `test -f 'interface.c' || echo '$(srcdir)/'`interface.c + +libZeroGSLinux_a-interface.obj: interface.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-interface.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-interface.Tpo -c -o libZeroGSLinux_a-interface.obj `if test -f 'interface.c'; then $(CYGPATH_W) 'interface.c'; else $(CYGPATH_W) '$(srcdir)/interface.c'; fi` + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-interface.Tpo $(DEPDIR)/libZeroGSLinux_a-interface.Po +# source='interface.c' object='libZeroGSLinux_a-interface.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-interface.obj `if test -f 'interface.c'; then $(CYGPATH_W) 'interface.c'; else $(CYGPATH_W) '$(srcdir)/interface.c'; fi` + +libZeroGSLinux_a-support.o: support.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-support.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-support.Tpo -c -o libZeroGSLinux_a-support.o `test -f 'support.c' || echo '$(srcdir)/'`support.c + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-support.Tpo $(DEPDIR)/libZeroGSLinux_a-support.Po +# source='support.c' object='libZeroGSLinux_a-support.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-support.o `test -f 'support.c' || echo '$(srcdir)/'`support.c + +libZeroGSLinux_a-support.obj: support.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-support.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-support.Tpo -c -o libZeroGSLinux_a-support.obj `if test -f 'support.c'; then $(CYGPATH_W) 'support.c'; else $(CYGPATH_W) '$(srcdir)/support.c'; fi` + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-support.Tpo $(DEPDIR)/libZeroGSLinux_a-support.Po +# source='support.c' object='libZeroGSLinux_a-support.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-support.obj `if test -f 'support.c'; then $(CYGPATH_W) 'support.c'; else $(CYGPATH_W) '$(srcdir)/support.c'; fi` + +.cpp.o: + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +libZeroGSLinux_a-Conf.o: Conf.cpp + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -MT libZeroGSLinux_a-Conf.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-Conf.Tpo -c -o libZeroGSLinux_a-Conf.o `test -f 'Conf.cpp' || echo '$(srcdir)/'`Conf.cpp + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-Conf.Tpo $(DEPDIR)/libZeroGSLinux_a-Conf.Po +# source='Conf.cpp' object='libZeroGSLinux_a-Conf.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -c -o libZeroGSLinux_a-Conf.o `test -f 'Conf.cpp' || echo '$(srcdir)/'`Conf.cpp + +libZeroGSLinux_a-Conf.obj: Conf.cpp + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -MT libZeroGSLinux_a-Conf.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-Conf.Tpo -c -o libZeroGSLinux_a-Conf.obj `if test -f 'Conf.cpp'; then $(CYGPATH_W) 'Conf.cpp'; else $(CYGPATH_W) '$(srcdir)/Conf.cpp'; fi` + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-Conf.Tpo $(DEPDIR)/libZeroGSLinux_a-Conf.Po +# source='Conf.cpp' object='libZeroGSLinux_a-Conf.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -c -o libZeroGSLinux_a-Conf.obj `if test -f 'Conf.cpp'; then $(CYGPATH_W) 'Conf.cpp'; else $(CYGPATH_W) '$(srcdir)/Conf.cpp'; fi` + +libZeroGSLinux_a-Linux.o: Linux.cpp + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -MT libZeroGSLinux_a-Linux.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-Linux.Tpo -c -o libZeroGSLinux_a-Linux.o `test -f 'Linux.cpp' || echo '$(srcdir)/'`Linux.cpp + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-Linux.Tpo $(DEPDIR)/libZeroGSLinux_a-Linux.Po +# source='Linux.cpp' object='libZeroGSLinux_a-Linux.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -c -o libZeroGSLinux_a-Linux.o `test -f 'Linux.cpp' || echo '$(srcdir)/'`Linux.cpp + +libZeroGSLinux_a-Linux.obj: Linux.cpp + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -MT libZeroGSLinux_a-Linux.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-Linux.Tpo -c -o libZeroGSLinux_a-Linux.obj `if test -f 'Linux.cpp'; then $(CYGPATH_W) 'Linux.cpp'; else $(CYGPATH_W) '$(srcdir)/Linux.cpp'; fi` + $(am__mv) $(DEPDIR)/libZeroGSLinux_a-Linux.Tpo $(DEPDIR)/libZeroGSLinux_a-Linux.Po +# source='Linux.cpp' object='libZeroGSLinux_a-Linux.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -c -o libZeroGSLinux_a-Linux.obj `if test -f 'Linux.cpp'; then $(CYGPATH_W) 'Linux.cpp'; else $(CYGPATH_W) '$(srcdir)/Linux.cpp'; fi` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/zzogl-pg/opengl/Linux/Makefile.am b/plugins/zzogl-pg/opengl/Linux/Makefile.am new file mode 100644 index 0000000000..8200d1f6d3 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/Makefile.am @@ -0,0 +1,10 @@ +noinst_LIBRARIES = libZeroGSLinux.a + +if X86_64 +libZeroGSLinux_a_CPPFLAGS = -fPIC +libZeroGSLinux_a_CXXFLAGS = -fPIC +libZeroGSLinux_a_CFLAGS = -fPIC +endif + +INCLUDES = $(shell pkg-config --cflags gtk+-2.0) -I@srcdir@/../ -I@srcdir@/../../../../common/include +libZeroGSLinux_a_SOURCES = callbacks.c Conf.cpp interface.c Linux.cpp support.c diff --git a/plugins/zzogl-pg/opengl/Linux/Makefile.in b/plugins/zzogl-pg/opengl/Linux/Makefile.in new file mode 100644 index 0000000000..635c80710d --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/Makefile.in @@ -0,0 +1,531 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = Linux +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libZeroGSLinux_a_AR = $(AR) $(ARFLAGS) +libZeroGSLinux_a_LIBADD = +am_libZeroGSLinux_a_OBJECTS = libZeroGSLinux_a-callbacks.$(OBJEXT) \ + libZeroGSLinux_a-Conf.$(OBJEXT) \ + libZeroGSLinux_a-interface.$(OBJEXT) \ + libZeroGSLinux_a-Linux.$(OBJEXT) \ + libZeroGSLinux_a-support.$(OBJEXT) +libZeroGSLinux_a_OBJECTS = $(am_libZeroGSLinux_a_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libZeroGSLinux_a_SOURCES) +DIST_SOURCES = $(libZeroGSLinux_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +GTK_CONFIG = @GTK_CONFIG@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHARED_LDFLAGS = @SHARED_LDFLAGS@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ZEROGS_AGE = @ZEROGS_AGE@ +ZEROGS_CURRENT = @ZEROGS_CURRENT@ +ZEROGS_RELEASE = @ZEROGS_RELEASE@ +ZEROGS_REVISION = @ZEROGS_REVISION@ +ZEROGS_SONAME = @ZEROGS_SONAME@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +so_ext = @so_ext@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LIBRARIES = libZeroGSLinux.a +@X86_64_TRUE@libZeroGSLinux_a_CPPFLAGS = -fPIC +@X86_64_TRUE@libZeroGSLinux_a_CXXFLAGS = -fPIC +@X86_64_TRUE@libZeroGSLinux_a_CFLAGS = -fPIC +INCLUDES = $(shell pkg-config --cflags gtk+-2.0) -I@srcdir@/../ -I@srcdir@/../../../../common/include +libZeroGSLinux_a_SOURCES = callbacks.c Conf.cpp interface.c Linux.cpp support.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Linux/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Linux/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libZeroGSLinux.a: $(libZeroGSLinux_a_OBJECTS) $(libZeroGSLinux_a_DEPENDENCIES) + -rm -f libZeroGSLinux.a + $(libZeroGSLinux_a_AR) libZeroGSLinux.a $(libZeroGSLinux_a_OBJECTS) $(libZeroGSLinux_a_LIBADD) + $(RANLIB) libZeroGSLinux.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libZeroGSLinux_a-Conf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libZeroGSLinux_a-Linux.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libZeroGSLinux_a-callbacks.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libZeroGSLinux_a-interface.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libZeroGSLinux_a-support.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +libZeroGSLinux_a-callbacks.o: callbacks.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-callbacks.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-callbacks.Tpo -c -o libZeroGSLinux_a-callbacks.o `test -f 'callbacks.c' || echo '$(srcdir)/'`callbacks.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-callbacks.Tpo $(DEPDIR)/libZeroGSLinux_a-callbacks.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='callbacks.c' object='libZeroGSLinux_a-callbacks.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-callbacks.o `test -f 'callbacks.c' || echo '$(srcdir)/'`callbacks.c + +libZeroGSLinux_a-callbacks.obj: callbacks.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-callbacks.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-callbacks.Tpo -c -o libZeroGSLinux_a-callbacks.obj `if test -f 'callbacks.c'; then $(CYGPATH_W) 'callbacks.c'; else $(CYGPATH_W) '$(srcdir)/callbacks.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-callbacks.Tpo $(DEPDIR)/libZeroGSLinux_a-callbacks.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='callbacks.c' object='libZeroGSLinux_a-callbacks.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-callbacks.obj `if test -f 'callbacks.c'; then $(CYGPATH_W) 'callbacks.c'; else $(CYGPATH_W) '$(srcdir)/callbacks.c'; fi` + +libZeroGSLinux_a-interface.o: interface.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-interface.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-interface.Tpo -c -o libZeroGSLinux_a-interface.o `test -f 'interface.c' || echo '$(srcdir)/'`interface.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-interface.Tpo $(DEPDIR)/libZeroGSLinux_a-interface.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='interface.c' object='libZeroGSLinux_a-interface.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-interface.o `test -f 'interface.c' || echo '$(srcdir)/'`interface.c + +libZeroGSLinux_a-interface.obj: interface.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-interface.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-interface.Tpo -c -o libZeroGSLinux_a-interface.obj `if test -f 'interface.c'; then $(CYGPATH_W) 'interface.c'; else $(CYGPATH_W) '$(srcdir)/interface.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-interface.Tpo $(DEPDIR)/libZeroGSLinux_a-interface.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='interface.c' object='libZeroGSLinux_a-interface.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-interface.obj `if test -f 'interface.c'; then $(CYGPATH_W) 'interface.c'; else $(CYGPATH_W) '$(srcdir)/interface.c'; fi` + +libZeroGSLinux_a-support.o: support.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-support.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-support.Tpo -c -o libZeroGSLinux_a-support.o `test -f 'support.c' || echo '$(srcdir)/'`support.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-support.Tpo $(DEPDIR)/libZeroGSLinux_a-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='support.c' object='libZeroGSLinux_a-support.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-support.o `test -f 'support.c' || echo '$(srcdir)/'`support.c + +libZeroGSLinux_a-support.obj: support.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -MT libZeroGSLinux_a-support.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-support.Tpo -c -o libZeroGSLinux_a-support.obj `if test -f 'support.c'; then $(CYGPATH_W) 'support.c'; else $(CYGPATH_W) '$(srcdir)/support.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-support.Tpo $(DEPDIR)/libZeroGSLinux_a-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='support.c' object='libZeroGSLinux_a-support.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CFLAGS) $(CFLAGS) -c -o libZeroGSLinux_a-support.obj `if test -f 'support.c'; then $(CYGPATH_W) 'support.c'; else $(CYGPATH_W) '$(srcdir)/support.c'; fi` + +.cpp.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +libZeroGSLinux_a-Conf.o: Conf.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -MT libZeroGSLinux_a-Conf.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-Conf.Tpo -c -o libZeroGSLinux_a-Conf.o `test -f 'Conf.cpp' || echo '$(srcdir)/'`Conf.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-Conf.Tpo $(DEPDIR)/libZeroGSLinux_a-Conf.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Conf.cpp' object='libZeroGSLinux_a-Conf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -c -o libZeroGSLinux_a-Conf.o `test -f 'Conf.cpp' || echo '$(srcdir)/'`Conf.cpp + +libZeroGSLinux_a-Conf.obj: Conf.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -MT libZeroGSLinux_a-Conf.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-Conf.Tpo -c -o libZeroGSLinux_a-Conf.obj `if test -f 'Conf.cpp'; then $(CYGPATH_W) 'Conf.cpp'; else $(CYGPATH_W) '$(srcdir)/Conf.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-Conf.Tpo $(DEPDIR)/libZeroGSLinux_a-Conf.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Conf.cpp' object='libZeroGSLinux_a-Conf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -c -o libZeroGSLinux_a-Conf.obj `if test -f 'Conf.cpp'; then $(CYGPATH_W) 'Conf.cpp'; else $(CYGPATH_W) '$(srcdir)/Conf.cpp'; fi` + +libZeroGSLinux_a-Linux.o: Linux.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -MT libZeroGSLinux_a-Linux.o -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-Linux.Tpo -c -o libZeroGSLinux_a-Linux.o `test -f 'Linux.cpp' || echo '$(srcdir)/'`Linux.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-Linux.Tpo $(DEPDIR)/libZeroGSLinux_a-Linux.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Linux.cpp' object='libZeroGSLinux_a-Linux.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -c -o libZeroGSLinux_a-Linux.o `test -f 'Linux.cpp' || echo '$(srcdir)/'`Linux.cpp + +libZeroGSLinux_a-Linux.obj: Linux.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -MT libZeroGSLinux_a-Linux.obj -MD -MP -MF $(DEPDIR)/libZeroGSLinux_a-Linux.Tpo -c -o libZeroGSLinux_a-Linux.obj `if test -f 'Linux.cpp'; then $(CYGPATH_W) 'Linux.cpp'; else $(CYGPATH_W) '$(srcdir)/Linux.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libZeroGSLinux_a-Linux.Tpo $(DEPDIR)/libZeroGSLinux_a-Linux.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Linux.cpp' object='libZeroGSLinux_a-Linux.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libZeroGSLinux_a_CPPFLAGS) $(CPPFLAGS) $(libZeroGSLinux_a_CXXFLAGS) $(CXXFLAGS) -c -o libZeroGSLinux_a-Linux.obj `if test -f 'Linux.cpp'; then $(CYGPATH_W) 'Linux.cpp'; else $(CYGPATH_W) '$(srcdir)/Linux.cpp'; fi` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/zzogl-pg/opengl/Linux/buildgui.sh b/plugins/zzogl-pg/opengl/Linux/buildgui.sh new file mode 100644 index 0000000000..9f0d1fcefb --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/buildgui.sh @@ -0,0 +1,9 @@ +# builds the GUI C classes +mkdir temp +cp zerogs.glade temp/ +cd temp +glade-2 --write-source zerogs.glade +rm src/main.c +cp src/*.h src/*.c ../ +cd .. +/bin/rm -rf temp diff --git a/plugins/zzogl-pg/opengl/Linux/callbacks.c b/plugins/zzogl-pg/opengl/Linux/callbacks.c new file mode 100644 index 0000000000..e87ed8be2d --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/callbacks.c @@ -0,0 +1,34 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/zzogl-pg/opengl/Linux/callbacks.h b/plugins/zzogl-pg/opengl/Linux/callbacks.h new file mode 100644 index 0000000000..e606c242f0 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/callbacks.h @@ -0,0 +1,14 @@ +#include + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data); diff --git a/plugins/zzogl-pg/opengl/Linux/cmake_install.cmake b/plugins/zzogl-pg/opengl/Linux/cmake_install.cmake new file mode 100644 index 0000000000..10adb5a351 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/cmake_install.cmake @@ -0,0 +1,34 @@ +# Install script for directory: /usr/local/src/pcsx2-4/plugins/zzogl/opengl/Linux + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "/usr/local") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +# Install shared libraries without execute permission? +IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + SET(CMAKE_INSTALL_SO_NO_EXE "0") +ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + diff --git a/plugins/zzogl-pg/opengl/Linux/interface.c b/plugins/zzogl-pg/opengl/Linux/interface.c new file mode 100644 index 0000000000..544c54063f --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/interface.c @@ -0,0 +1,392 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox4; + GtkWidget *frame7; + GtkWidget *alignment4; + GtkWidget *hbox8; + GtkWidget *radionointerlace; + GSList *radionointerlace_group = NULL; + GtkWidget *radiointerlace0; + GtkWidget *radiointerlace1; + GtkWidget *label13; + GtkWidget *checkBilinear; + GtkWidget *frame4; + GtkWidget *alignment1; + GtkWidget *hbox6; + GtkWidget *radioAANone; + GSList *radioAANone_group = NULL; + GtkWidget *radioAA2X; + GtkWidget *radioAA4X; + GtkWidget *radioAA8X; + GtkWidget *radioAA16X; + GtkWidget *label9; + GtkWidget *checkWireframe; + GtkWidget *checkAVI; + GtkWidget *checkTGA; + GtkWidget *checkfullscreen; + GtkWidget *checkwidescreen; + GtkWidget *frame5; + GtkWidget *alignment2; + GtkWidget *hbox7; + GtkWidget *radioSize640; + GSList *radioSize640_group = NULL; + GtkWidget *radioSize800; + GtkWidget *radioSize1024; + GtkWidget *radioSize1280; + GtkWidget *label10; + GtkWidget *frame6; + GtkWidget *alignment3; + GtkWidget *scrolledwindow1; + GtkWidget *treeview1; + GtkWidget *label12; + GtkWidget *label11; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), _("ZeroOGS Configuration")); + + vbox4 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox4); + gtk_container_add (GTK_CONTAINER (Config), vbox4); + + frame7 = gtk_frame_new (NULL); + gtk_widget_show (frame7); + gtk_box_pack_start (GTK_BOX (vbox4), frame7, FALSE, FALSE, 0); + + alignment4 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment4); + gtk_container_add (GTK_CONTAINER (frame7), alignment4); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment4), 0, 0, 12, 0); + + hbox8 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox8); + gtk_container_add (GTK_CONTAINER (alignment4), hbox8); + + radionointerlace = gtk_radio_button_new_with_mnemonic (NULL, _("Interlace Off")); + gtk_widget_show (radionointerlace); + gtk_box_pack_start (GTK_BOX (hbox8), radionointerlace, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radionointerlace), radionointerlace_group); + radionointerlace_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radionointerlace)); + + radiointerlace0 = gtk_radio_button_new_with_mnemonic (NULL, _("Interlace 0")); + gtk_widget_show (radiointerlace0); + gtk_box_pack_start (GTK_BOX (hbox8), radiointerlace0, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiointerlace0), radionointerlace_group); + radionointerlace_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiointerlace0)); + + radiointerlace1 = gtk_radio_button_new_with_mnemonic (NULL, _("Interlace 1")); + gtk_widget_show (radiointerlace1); + gtk_box_pack_start (GTK_BOX (hbox8), radiointerlace1, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiointerlace1), radionointerlace_group); + radionointerlace_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiointerlace1)); + + label13 = gtk_label_new (_("Interlacing (F5 to toggle)")); + gtk_widget_show (label13); + gtk_frame_set_label_widget (GTK_FRAME (frame7), label13); + gtk_label_set_use_markup (GTK_LABEL (label13), TRUE); + + checkBilinear = gtk_check_button_new_with_mnemonic (_("Bilinear Filtering (Shift+F5)\n Best quality is on, turn off for speed")); + gtk_widget_show (checkBilinear); + gtk_box_pack_start (GTK_BOX (vbox4), checkBilinear, FALSE, FALSE, 0); + + frame4 = gtk_frame_new (NULL); + gtk_widget_show (frame4); + gtk_box_pack_start (GTK_BOX (vbox4), frame4, FALSE, FALSE, 0); + + alignment1 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment1); + gtk_container_add (GTK_CONTAINER (frame4), alignment1); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment1), 0, 0, 12, 0); + + hbox6 = gtk_hbox_new (TRUE, 0); + gtk_widget_show (hbox6); + gtk_container_add (GTK_CONTAINER (alignment1), hbox6); + + radioAANone = gtk_radio_button_new_with_mnemonic (NULL, _("None")); + gtk_widget_show (radioAANone); + gtk_box_pack_start (GTK_BOX (hbox6), radioAANone, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioAANone), radioAANone_group); + radioAANone_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioAANone)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radioAANone), TRUE); + + radioAA2X = gtk_radio_button_new_with_mnemonic (NULL, _("2X")); + gtk_widget_show (radioAA2X); + gtk_box_pack_start (GTK_BOX (hbox6), radioAA2X, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioAA2X), radioAANone_group); + radioAANone_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioAA2X)); + + radioAA4X = gtk_radio_button_new_with_mnemonic (NULL, _("4X")); + gtk_widget_show (radioAA4X); + gtk_box_pack_start (GTK_BOX (hbox6), radioAA4X, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioAA4X), radioAANone_group); + radioAANone_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioAA4X)); + + radioAA8X = gtk_radio_button_new_with_mnemonic (NULL, _("8X")); + gtk_widget_show (radioAA8X); + gtk_box_pack_start (GTK_BOX (hbox6), radioAA8X, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioAA8X), radioAANone_group); + radioAANone_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioAA8X)); + + radioAA16X = gtk_radio_button_new_with_mnemonic (NULL, _("16X")); + gtk_widget_show (radioAA16X); + gtk_box_pack_start (GTK_BOX (hbox6), radioAA16X, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioAA16X), radioAANone_group); + radioAANone_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioAA16X)); + + label9 = gtk_label_new (_("Anti-aliasing for higher quality (F6)")); + gtk_widget_show (label9); + gtk_frame_set_label_widget (GTK_FRAME (frame4), label9); + gtk_label_set_use_markup (GTK_LABEL (label9), TRUE); + + checkWireframe = gtk_check_button_new_with_mnemonic (_("Wireframe rendering (Shift+F6)")); + gtk_widget_show (checkWireframe); + gtk_box_pack_start (GTK_BOX (vbox4), checkWireframe, FALSE, FALSE, 0); + + checkAVI = gtk_check_button_new_with_mnemonic (_("Capture Avi (zerogs.avi)(F7)")); + gtk_widget_show (checkAVI); + gtk_box_pack_start (GTK_BOX (vbox4), checkAVI, FALSE, FALSE, 0); + + checkTGA = gtk_check_button_new_with_mnemonic (_("Save Snapshots as TGAs (default is JPG)")); + gtk_widget_show (checkTGA); + gtk_box_pack_start (GTK_BOX (vbox4), checkTGA, FALSE, FALSE, 0); + + checkfullscreen = gtk_check_button_new_with_mnemonic (_("Fullscreen (Alt+Enter)\n to get out press Alt+Enter again (or ESC)")); + gtk_widget_show (checkfullscreen); + gtk_box_pack_start (GTK_BOX (vbox4), checkfullscreen, FALSE, FALSE, 0); + + checkwidescreen = gtk_check_button_new_with_mnemonic (_("Wide Screen")); + gtk_widget_show (checkwidescreen); + gtk_box_pack_start (GTK_BOX (vbox4), checkwidescreen, FALSE, FALSE, 0); + + frame5 = gtk_frame_new (NULL); + gtk_widget_show (frame5); + gtk_box_pack_start (GTK_BOX (vbox4), frame5, FALSE, FALSE, 0); + + alignment2 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment2); + gtk_container_add (GTK_CONTAINER (frame5), alignment2); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment2), 0, 0, 12, 0); + + hbox7 = gtk_hbox_new (TRUE, 0); + gtk_widget_show (hbox7); + gtk_container_add (GTK_CONTAINER (alignment2), hbox7); + + radioSize640 = gtk_radio_button_new_with_mnemonic (NULL, _("640x480")); + gtk_widget_show (radioSize640); + gtk_box_pack_start (GTK_BOX (hbox7), radioSize640, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioSize640), radioSize640_group); + radioSize640_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioSize640)); + + radioSize800 = gtk_radio_button_new_with_mnemonic (NULL, _("800x600")); + gtk_widget_show (radioSize800); + gtk_box_pack_start (GTK_BOX (hbox7), radioSize800, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioSize800), radioSize640_group); + radioSize640_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioSize800)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radioSize800), TRUE); + + radioSize1024 = gtk_radio_button_new_with_mnemonic (NULL, _("1024x768")); + gtk_widget_show (radioSize1024); + gtk_box_pack_start (GTK_BOX (hbox7), radioSize1024, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioSize1024), radioSize640_group); + radioSize640_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioSize1024)); + + radioSize1280 = gtk_radio_button_new_with_mnemonic (NULL, _("1280x960")); + gtk_widget_show (radioSize1280); + gtk_box_pack_start (GTK_BOX (hbox7), radioSize1280, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioSize1280), radioSize640_group); + radioSize640_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioSize1280)); + + label10 = gtk_label_new (_("Default Window Size (no speed impact)")); + gtk_widget_show (label10); + gtk_frame_set_label_widget (GTK_FRAME (frame5), label10); + gtk_label_set_use_markup (GTK_LABEL (label10), TRUE); + + frame6 = gtk_frame_new (NULL); + gtk_widget_show (frame6); + gtk_box_pack_start (GTK_BOX (vbox4), frame6, TRUE, TRUE, 0); + + alignment3 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment3); + gtk_container_add (GTK_CONTAINER (frame6), alignment3); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment3), 0, 0, 12, 0); + + scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolledwindow1); + gtk_container_add (GTK_CONTAINER (alignment3), scrolledwindow1); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_SHADOW_IN); + + treeview1 = gtk_tree_view_new (); + gtk_widget_show (treeview1); + gtk_container_add (GTK_CONTAINER (scrolledwindow1), treeview1); + + label12 = gtk_label_new (_("Advanced Options")); + gtk_widget_show (label12); + gtk_frame_set_label_widget (GTK_FRAME (frame6), label12); + gtk_label_set_use_markup (GTK_LABEL (label12), TRUE); + + label11 = gtk_label_new (_("Show Frames Per Second (Shift+F7)\n (value is the average over 4-16 PS2 frames)")); + gtk_widget_show (label11); + gtk_box_pack_start (GTK_BOX (vbox4), label11, FALSE, FALSE, 0); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox4), hbuttonbox1, FALSE, FALSE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_SPREAD); + gtk_box_set_spacing (GTK_BOX (hbuttonbox1), 30); + + button1 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button1, "clicked", + G_CALLBACK (OnConf_Ok), + NULL); + g_signal_connect ((gpointer) button2, "clicked", + G_CALLBACK (OnConf_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (Config, Config, "Config"); + GLADE_HOOKUP_OBJECT (Config, vbox4, "vbox4"); + GLADE_HOOKUP_OBJECT (Config, frame7, "frame7"); + GLADE_HOOKUP_OBJECT (Config, alignment4, "alignment4"); + GLADE_HOOKUP_OBJECT (Config, hbox8, "hbox8"); + GLADE_HOOKUP_OBJECT (Config, radionointerlace, "radionointerlace"); + GLADE_HOOKUP_OBJECT (Config, radiointerlace0, "radiointerlace0"); + GLADE_HOOKUP_OBJECT (Config, radiointerlace1, "radiointerlace1"); + GLADE_HOOKUP_OBJECT (Config, label13, "label13"); + GLADE_HOOKUP_OBJECT (Config, checkBilinear, "checkBilinear"); + GLADE_HOOKUP_OBJECT (Config, frame4, "frame4"); + GLADE_HOOKUP_OBJECT (Config, alignment1, "alignment1"); + GLADE_HOOKUP_OBJECT (Config, hbox6, "hbox6"); + GLADE_HOOKUP_OBJECT (Config, radioAANone, "radioAANone"); + GLADE_HOOKUP_OBJECT (Config, radioAA2X, "radioAA2X"); + GLADE_HOOKUP_OBJECT (Config, radioAA4X, "radioAA4X"); + GLADE_HOOKUP_OBJECT (Config, radioAA8X, "radioAA8X"); + GLADE_HOOKUP_OBJECT (Config, radioAA16X, "radioAA16X"); + GLADE_HOOKUP_OBJECT (Config, label9, "label9"); + GLADE_HOOKUP_OBJECT (Config, checkWireframe, "checkWireframe"); + GLADE_HOOKUP_OBJECT (Config, checkAVI, "checkAVI"); + GLADE_HOOKUP_OBJECT (Config, checkTGA, "checkTGA"); + GLADE_HOOKUP_OBJECT (Config, checkfullscreen, "checkfullscreen"); + GLADE_HOOKUP_OBJECT (Config, checkwidescreen, "checkwidescreen"); + GLADE_HOOKUP_OBJECT (Config, frame5, "frame5"); + GLADE_HOOKUP_OBJECT (Config, alignment2, "alignment2"); + GLADE_HOOKUP_OBJECT (Config, hbox7, "hbox7"); + GLADE_HOOKUP_OBJECT (Config, radioSize640, "radioSize640"); + GLADE_HOOKUP_OBJECT (Config, radioSize800, "radioSize800"); + GLADE_HOOKUP_OBJECT (Config, radioSize1024, "radioSize1024"); + GLADE_HOOKUP_OBJECT (Config, radioSize1280, "radioSize1280"); + GLADE_HOOKUP_OBJECT (Config, label10, "label10"); + GLADE_HOOKUP_OBJECT (Config, frame6, "frame6"); + GLADE_HOOKUP_OBJECT (Config, alignment3, "alignment3"); + GLADE_HOOKUP_OBJECT (Config, scrolledwindow1, "scrolledwindow1"); + GLADE_HOOKUP_OBJECT (Config, treeview1, "treeview1"); + GLADE_HOOKUP_OBJECT (Config, label12, "label12"); + GLADE_HOOKUP_OBJECT (Config, label11, "label11"); + GLADE_HOOKUP_OBJECT (Config, hbuttonbox1, "hbuttonbox1"); + GLADE_HOOKUP_OBJECT (Config, button1, "button1"); + GLADE_HOOKUP_OBJECT (Config, button2, "button2"); + + return Config; +} + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + GtkWidget *vbox2; + GtkWidget *label2; + GtkWidget *label3; + GtkWidget *label4; + GtkWidget *hbuttonbox2; + GtkWidget *button3; + + About = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (About), 5); + gtk_window_set_title (GTK_WINDOW (About), _("ZZogl About")); + + vbox2 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (About), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + label2 = gtk_label_new (_("OpenGL version")); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox2), label2, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_CENTER); + + label3 = gtk_label_new (_("Author: Zeydlitz(@gmail.com)")); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (vbox2), label3, FALSE, FALSE, 0); + + label4 = gtk_label_new (_("Many thanks to the Pcsx2 testing team")); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (vbox2), label4, FALSE, FALSE, 0); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox2, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox2), 30); + + button3 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button3); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button3); + GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button3, "clicked", + G_CALLBACK (OnAbout_Ok), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (About, About, "About"); + GLADE_HOOKUP_OBJECT (About, vbox2, "vbox2"); + GLADE_HOOKUP_OBJECT (About, label2, "label2"); + GLADE_HOOKUP_OBJECT (About, label3, "label3"); + GLADE_HOOKUP_OBJECT (About, label4, "label4"); + GLADE_HOOKUP_OBJECT (About, hbuttonbox2, "hbuttonbox2"); + GLADE_HOOKUP_OBJECT (About, button3, "button3"); + + return About; +} + diff --git a/plugins/zzogl-pg/opengl/Linux/interface.h b/plugins/zzogl-pg/opengl/Linux/interface.h new file mode 100644 index 0000000000..69c303ba3b --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); +GtkWidget* create_About (void); diff --git a/plugins/zzogl-pg/opengl/Linux/support.c b/plugins/zzogl-pg/opengl/Linux/support.c new file mode 100644 index 0000000000..00aff29822 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/support.c @@ -0,0 +1,144 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "support.h" + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to find pixmap files. */ +static gchar* +find_pixmap_file (const gchar *filename) +{ + GList *elem; + + /* We step through each of the pixmaps directory to find it. */ + elem = pixmaps_directories; + while (elem) + { + gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, + G_DIR_SEPARATOR_S, filename); + if (g_file_test (pathname, G_FILE_TEST_EXISTS)) + return pathname; + g_free (pathname); + elem = elem->next; + } + return NULL; +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *pathname = NULL; + GtkWidget *pixmap; + + if (!filename || !filename[0]) + return gtk_image_new (); + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return gtk_image_new (); + } + + pixmap = gtk_image_new_from_file (pathname); + g_free (pathname); + return pixmap; +} + +/* This is an internally used function to create pixmaps. */ +GdkPixbuf* +create_pixbuf (const gchar *filename) +{ + gchar *pathname = NULL; + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (!filename || !filename[0]) + return NULL; + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return NULL; + } + + pixbuf = gdk_pixbuf_new_from_file (pathname, &error); + if (!pixbuf) + { + fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", + pathname, error->message); + g_error_free (error); + } + g_free (pathname); + return pixbuf; +} + +/* This is used to set ATK action descriptions. */ +void +glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description) +{ + gint n_actions, i; + + n_actions = atk_action_get_n_actions (action); + for (i = 0; i < n_actions; i++) + { + if (!strcmp (atk_action_get_name (action, i), action_name)) + atk_action_set_description (action, i, description); + } +} + diff --git a/plugins/zzogl-pg/opengl/Linux/support.h b/plugins/zzogl-pg/opengl/Linux/support.h new file mode 100644 index 0000000000..a32649e53c --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/support.h @@ -0,0 +1,69 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Standard gettext macros. + */ +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# define Q_(String) g_strip_context ((String), gettext (String)) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define Q_(String) g_strip_context ((String), (String)) +# define N_(String) (String) +#endif + + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps used in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + +/* This is used to create the pixbufs used in the interface. */ +GdkPixbuf* create_pixbuf (const gchar *filename); + +/* This is used to set ATK action descriptions. */ +void glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description); + diff --git a/plugins/zzogl-pg/opengl/Linux/zerogs.glade b/plugins/zzogl-pg/opengl/Linux/zerogs.glade new file mode 100644 index 0000000000..bc5980493f --- /dev/null +++ b/plugins/zzogl-pg/opengl/Linux/zerogs.glade @@ -0,0 +1,812 @@ + + + + + + + 5 + True + ZeroOGS Configuration + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + Interlace Off + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Interlace 0 + True + GTK_RELIEF_NORMAL + True + False + False + True + radionointerlace + + + 0 + False + False + + + + + + True + True + Interlace 1 + True + GTK_RELIEF_NORMAL + True + False + False + True + radionointerlace + + + 0 + False + False + + + + + + + + + + True + <b>Interlacing (F5 to toggle)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + True + True + Bilinear Filtering (Shift+F5) + Best quality is on, turn off for speed + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + True + 0 + + + + True + True + None + True + GTK_RELIEF_NORMAL + True + True + False + True + + + 0 + False + False + + + + + + True + True + 2X + True + GTK_RELIEF_NORMAL + True + False + False + True + radioAANone + + + 0 + False + False + + + + + + True + True + 4X + True + GTK_RELIEF_NORMAL + True + False + False + True + radioAANone + + + 0 + False + False + + + + + + True + True + 8X + True + GTK_RELIEF_NORMAL + True + False + False + True + radioAANone + + + 0 + False + False + + + + + + True + True + 16X + True + GTK_RELIEF_NORMAL + True + False + False + True + radioAANone + + + 0 + False + False + + + + + + + + + + True + <b>Anti-aliasing for higher quality (F6)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + True + True + Wireframe rendering (Shift+F6) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Capture Avi (zerogs.avi)(F7) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Save Snapshots as TGAs (default is JPG) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Fullscreen (Alt+Enter) + to get out press Alt+Enter again (or ESC) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + True + 0 + + + + True + True + 640x480 + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + 800x600 + True + GTK_RELIEF_NORMAL + True + True + False + True + radioSize640 + + + 0 + False + False + + + + + + True + True + 1024x768 + True + GTK_RELIEF_NORMAL + True + False + False + True + radioSize640 + + + 0 + False + False + + + + + + True + True + 1280x960 + True + GTK_RELIEF_NORMAL + True + False + False + True + radioSize640 + + + 0 + False + False + + + + + + + + + + True + <b>Default Window Size (no speed impact)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + + + + + + True + <b>Advanced Options</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + Show Frames Per Second (Shift+F7) + (value is the average over 4-16 PS2 frames) + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_SPREAD + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + False + False + + + + + + + + 5 + True + ZeroGS KOSMOS About + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + True + OpenGL version + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Author: zerofrog(@gmail.com) + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Many thanks to the Pcsx2 testing team + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + diff --git a/plugins/zzogl-pg/opengl/Makefile.am b/plugins/zzogl-pg/opengl/Makefile.am new file mode 100644 index 0000000000..200328ed7c --- /dev/null +++ b/plugins/zzogl-pg/opengl/Makefile.am @@ -0,0 +1,50 @@ +# Create a shared library libzzoglpg +AUTOMAKE_OPTIONS = foreign +noinst_LIBRARIES = libzzoglpg.a +INCLUDES = -I@srcdir@/../../../common/include -I@srcdir@/common + +libzzoglpg_a_CPPFLAGS = $(shell pkg-config --cflags gtk+-2.0) +libzzoglpg_a_CXXFLAGS = $(shell pkg-config --cflags gtk+-2.0) + +if X86_64 +libzzoglpg_a_CPPFLAGS += -fPIC +libzzoglpg_a_CXXFLAGS += -fPIC +CCASFLAGS += -fPIC +endif + +# Create a shared object by faking an exe (thanks to ODE makefiles) +traplibdir=$(prefix) + + +if RELEASE_TO_PUBLIC +preext=r +endif + +EXEEXT=$(preext)@so_ext@ + +traplib_PROGRAMS=libzzoglpg +libzzoglpg_SOURCES= +libzzoglpg_DEPENDENCIES = libzzoglpg.a +libzzoglpg_LDFLAGS= @SHARED_LDFLAGS@ +libzzoglpg_LDFLAGS+=-Wl,-soname,@ZEROGS_SONAME@ +libzzoglpg_LDADD=$(libzzoglpg_a_OBJECTS) + +libzzoglpg_a_SOURCES = \ +GSmain.cpp memcpy_amd.cpp Regs.cpp x86.cpp zpipe.cpp Mem.cpp \ +rasterfont.cpp targets.cpp zerogs.cpp ZZoglVB.cpp ZZoglShoots.cpp ZZoglCreate.cpp \ +ZZoglShaders.cpp ZZoglCRTC.cpp ZZoglSave.cpp ZZoglFlush.cpp + +if X86_64 +libzzoglpg_a_SOURCES += x86-64.S +else +libzzoglpg_a_SOURCES += x86-32.S +endif + +if SSE2 +CCASFLAGS+= -DZEROGS_SSE2 +endif + +libzzoglpg_a_DEPENDENCIES = Linux/libZeroGSLinux.a +libzzoglpg_LDADD += Linux/libZeroGSLinux.a + +SUBDIRS = Linux ZeroGSShaders . diff --git a/plugins/zzogl-pg/opengl/Mem.cpp b/plugins/zzogl-pg/opengl/Mem.cpp new file mode 100644 index 0000000000..245d734a11 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Mem.cpp @@ -0,0 +1,902 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GS.h" +#include "Mem.h" +#include "zerogs.h" +#include "targets.h" +#include "x86.h" + +u32 g_blockTable32[4][8] = { + { 0, 1, 4, 5, 16, 17, 20, 21}, + { 2, 3, 6, 7, 18, 19, 22, 23}, + { 8, 9, 12, 13, 24, 25, 28, 29}, + { 10, 11, 14, 15, 26, 27, 30, 31} +}; + +u32 g_blockTable32Z[4][8] = { + { 24, 25, 28, 29, 8, 9, 12, 13}, + { 26, 27, 30, 31, 10, 11, 14, 15}, + { 16, 17, 20, 21, 0, 1, 4, 5}, + { 18, 19, 22, 23, 2, 3, 6, 7} +}; + +u32 g_blockTable16[8][4] = { + { 0, 2, 8, 10 }, + { 1, 3, 9, 11 }, + { 4, 6, 12, 14 }, + { 5, 7, 13, 15 }, + { 16, 18, 24, 26 }, + { 17, 19, 25, 27 }, + { 20, 22, 28, 30 }, + { 21, 23, 29, 31 } +}; + +u32 g_blockTable16S[8][4] = { + { 0, 2, 16, 18 }, + { 1, 3, 17, 19 }, + { 8, 10, 24, 26 }, + { 9, 11, 25, 27 }, + { 4, 6, 20, 22 }, + { 5, 7, 21, 23 }, + { 12, 14, 28, 30 }, + { 13, 15, 29, 31 } +}; + +u32 g_blockTable16Z[8][4] = { + { 24, 26, 16, 18 }, + { 25, 27, 17, 19 }, + { 28, 30, 20, 22 }, + { 29, 31, 21, 23 }, + { 8, 10, 0, 2 }, + { 9, 11, 1, 3 }, + { 12, 14, 4, 6 }, + { 13, 15, 5, 7 } +}; + +u32 g_blockTable16SZ[8][4] = { + { 24, 26, 8, 10 }, + { 25, 27, 9, 11 }, + { 16, 18, 0, 2 }, + { 17, 19, 1, 3 }, + { 28, 30, 12, 14 }, + { 29, 31, 13, 15 }, + { 20, 22, 4, 6 }, + { 21, 23, 5, 7 } +}; + +u32 g_blockTable8[4][8] = { + { 0, 1, 4, 5, 16, 17, 20, 21}, + { 2, 3, 6, 7, 18, 19, 22, 23}, + { 8, 9, 12, 13, 24, 25, 28, 29}, + { 10, 11, 14, 15, 26, 27, 30, 31} +}; + +u32 g_blockTable4[8][4] = { + { 0, 2, 8, 10 }, + { 1, 3, 9, 11 }, + { 4, 6, 12, 14 }, + { 5, 7, 13, 15 }, + { 16, 18, 24, 26 }, + { 17, 19, 25, 27 }, + { 20, 22, 28, 30 }, + { 21, 23, 29, 31 } +}; + +u32 g_columnTable32[8][8] = { + { 0, 1, 4, 5, 8, 9, 12, 13 }, + { 2, 3, 6, 7, 10, 11, 14, 15 }, + { 16, 17, 20, 21, 24, 25, 28, 29 }, + { 18, 19, 22, 23, 26, 27, 30, 31 }, + { 32, 33, 36, 37, 40, 41, 44, 45 }, + { 34, 35, 38, 39, 42, 43, 46, 47 }, + { 48, 49, 52, 53, 56, 57, 60, 61 }, + { 50, 51, 54, 55, 58, 59, 62, 63 }, +}; + +u32 g_columnTable16[8][16] = { + { 0, 2, 8, 10, 16, 18, 24, 26, + 1, 3, 9, 11, 17, 19, 25, 27 }, + { 4, 6, 12, 14, 20, 22, 28, 30, + 5, 7, 13, 15, 21, 23, 29, 31 }, + { 32, 34, 40, 42, 48, 50, 56, 58, + 33, 35, 41, 43, 49, 51, 57, 59 }, + { 36, 38, 44, 46, 52, 54, 60, 62, + 37, 39, 45, 47, 53, 55, 61, 63 }, + { 64, 66, 72, 74, 80, 82, 88, 90, + 65, 67, 73, 75, 81, 83, 89, 91 }, + { 68, 70, 76, 78, 84, 86, 92, 94, + 69, 71, 77, 79, 85, 87, 93, 95 }, + { 96, 98, 104, 106, 112, 114, 120, 122, + 97, 99, 105, 107, 113, 115, 121, 123 }, + { 100, 102, 108, 110, 116, 118, 124, 126, + 101, 103, 109, 111, 117, 119, 125, 127 }, +}; + +u32 g_columnTable8[16][16] = { + { 0, 4, 16, 20, 32, 36, 48, 52, // column 0 + 2, 6, 18, 22, 34, 38, 50, 54 }, + { 8, 12, 24, 28, 40, 44, 56, 60, + 10, 14, 26, 30, 42, 46, 58, 62 }, + { 33, 37, 49, 53, 1, 5, 17, 21, + 35, 39, 51, 55, 3, 7, 19, 23 }, + { 41, 45, 57, 61, 9, 13, 25, 29, + 43, 47, 59, 63, 11, 15, 27, 31 }, + { 96, 100, 112, 116, 64, 68, 80, 84, // column 1 + 98, 102, 114, 118, 66, 70, 82, 86 }, + { 104, 108, 120, 124, 72, 76, 88, 92, + 106, 110, 122, 126, 74, 78, 90, 94 }, + { 65, 69, 81, 85, 97, 101, 113, 117, + 67, 71, 83, 87, 99, 103, 115, 119 }, + { 73, 77, 89, 93, 105, 109, 121, 125, + 75, 79, 91, 95, 107, 111, 123, 127 }, + { 128, 132, 144, 148, 160, 164, 176, 180, // column 2 + 130, 134, 146, 150, 162, 166, 178, 182 }, + { 136, 140, 152, 156, 168, 172, 184, 188, + 138, 142, 154, 158, 170, 174, 186, 190 }, + { 161, 165, 177, 181, 129, 133, 145, 149, + 163, 167, 179, 183, 131, 135, 147, 151 }, + { 169, 173, 185, 189, 137, 141, 153, 157, + 171, 175, 187, 191, 139, 143, 155, 159 }, + { 224, 228, 240, 244, 192, 196, 208, 212, // column 3 + 226, 230, 242, 246, 194, 198, 210, 214 }, + { 232, 236, 248, 252, 200, 204, 216, 220, + 234, 238, 250, 254, 202, 206, 218, 222 }, + { 193, 197, 209, 213, 225, 229, 241, 245, + 195, 199, 211, 215, 227, 231, 243, 247 }, + { 201, 205, 217, 221, 233, 237, 249, 253, + 203, 207, 219, 223, 235, 239, 251, 255 }, +}; + +u32 g_columnTable4[16][32] = { + { 0, 8, 32, 40, 64, 72, 96, 104, // column 0 + 2, 10, 34, 42, 66, 74, 98, 106, + 4, 12, 36, 44, 68, 76, 100, 108, + 6, 14, 38, 46, 70, 78, 102, 110 }, + { 16, 24, 48, 56, 80, 88, 112, 120, + 18, 26, 50, 58, 82, 90, 114, 122, + 20, 28, 52, 60, 84, 92, 116, 124, + 22, 30, 54, 62, 86, 94, 118, 126 }, + { 65, 73, 97, 105, 1, 9, 33, 41, + 67, 75, 99, 107, 3, 11, 35, 43, + 69, 77, 101, 109, 5, 13, 37, 45, + 71, 79, 103, 111, 7, 15, 39, 47 }, + { 81, 89, 113, 121, 17, 25, 49, 57, + 83, 91, 115, 123, 19, 27, 51, 59, + 85, 93, 117, 125, 21, 29, 53, 61, + 87, 95, 119, 127, 23, 31, 55, 63 }, + { 192, 200, 224, 232, 128, 136, 160, 168, // column 1 + 194, 202, 226, 234, 130, 138, 162, 170, + 196, 204, 228, 236, 132, 140, 164, 172, + 198, 206, 230, 238, 134, 142, 166, 174 }, + { 208, 216, 240, 248, 144, 152, 176, 184, + 210, 218, 242, 250, 146, 154, 178, 186, + 212, 220, 244, 252, 148, 156, 180, 188, + 214, 222, 246, 254, 150, 158, 182, 190 }, + { 129, 137, 161, 169, 193, 201, 225, 233, + 131, 139, 163, 171, 195, 203, 227, 235, + 133, 141, 165, 173, 197, 205, 229, 237, + 135, 143, 167, 175, 199, 207, 231, 239 }, + { 145, 153, 177, 185, 209, 217, 241, 249, + 147, 155, 179, 187, 211, 219, 243, 251, + 149, 157, 181, 189, 213, 221, 245, 253, + 151, 159, 183, 191, 215, 223, 247, 255 }, + { 256, 264, 288, 296, 320, 328, 352, 360, // column 2 + 258, 266, 290, 298, 322, 330, 354, 362, + 260, 268, 292, 300, 324, 332, 356, 364, + 262, 270, 294, 302, 326, 334, 358, 366 }, + { 272, 280, 304, 312, 336, 344, 368, 376, + 274, 282, 306, 314, 338, 346, 370, 378, + 276, 284, 308, 316, 340, 348, 372, 380, + 278, 286, 310, 318, 342, 350, 374, 382 }, + { 321, 329, 353, 361, 257, 265, 289, 297, + 323, 331, 355, 363, 259, 267, 291, 299, + 325, 333, 357, 365, 261, 269, 293, 301, + 327, 335, 359, 367, 263, 271, 295, 303 }, + { 337, 345, 369, 377, 273, 281, 305, 313, + 339, 347, 371, 379, 275, 283, 307, 315, + 341, 349, 373, 381, 277, 285, 309, 317, + 343, 351, 375, 383, 279, 287, 311, 319 }, + { 448, 456, 480, 488, 384, 392, 416, 424, // column 3 + 450, 458, 482, 490, 386, 394, 418, 426, + 452, 460, 484, 492, 388, 396, 420, 428, + 454, 462, 486, 494, 390, 398, 422, 430 }, + { 464, 472, 496, 504, 400, 408, 432, 440, + 466, 474, 498, 506, 402, 410, 434, 442, + 468, 476, 500, 508, 404, 412, 436, 444, + 470, 478, 502, 510, 406, 414, 438, 446 }, + { 385, 393, 417, 425, 449, 457, 481, 489, + 387, 395, 419, 427, 451, 459, 483, 491, + 389, 397, 421, 429, 453, 461, 485, 493, + 391, 399, 423, 431, 455, 463, 487, 495 }, + { 401, 409, 433, 441, 465, 473, 497, 505, + 403, 411, 435, 443, 467, 475, 499, 507, + 405, 413, 437, 445, 469, 477, 501, 509, + 407, 415, 439, 447, 471, 479, 503, 511 }, +}; + +u32 g_pageTable32[32][64]; +u32 g_pageTable32Z[32][64]; +u32 g_pageTable16[64][64]; +u32 g_pageTable16S[64][64]; +u32 g_pageTable16Z[64][64]; +u32 g_pageTable16SZ[64][64]; +u32 g_pageTable8[64][128]; +u32 g_pageTable4[128][128]; + +BLOCK m_Blocks[0x40]; // do so blocks are indexable +static PCSX2_ALIGNED16(u32 tempblock[64]); + +#define DSTPSM gs.dstbuf.psm + +#define START_HOSTLOCAL() \ + assert( gs.imageTransfer == 0 ); \ + u8* pstart = g_pbyGSMemory + gs.dstbuf.bp*256; \ + \ + const u8* pendbuf = (const u8*)pbyMem + nQWordSize*4; \ + int i = gs.imageY, j = gs.imageX; \ + +#define END_HOSTLOCAL() \ +End: \ + if( i >= gs.imageEndY ) { \ + assert( gs.imageTransfer == -1 || i == gs.imageEndY ); \ + gs.imageTransfer = -1; \ + /*int start, end; \ + ZeroGS::GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); \ + ZeroGS::g_MemTargs.ClearRange(start, end);*/ \ + } \ + else { \ + /* update new params */ \ + gs.imageY = i; \ + gs.imageX = j; \ + } \ + +// transfers whole rows +#define TRANSMIT_HOSTLOCAL_Y_(psm, T, widthlimit, endY) { \ + assert( (nSize%widthlimit) == 0 && widthlimit <= 4 ); \ + if( (gs.imageEndX-gs.trxpos.dx)%widthlimit ) { \ + /*GS_LOG("Bad Transmission! %d %d, psm: %d\n", gs.trxpos.dx, gs.imageEndX, DSTPSM);*/ \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += 1, nSize -= 1, pbuf += 1) { \ + /* write as many pixel at one time as possible */ \ + writePixel##psm##_0(pstart, j%2048, i%2048, pbuf[0], gs.dstbuf.bw); \ + } \ + } \ + } \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += widthlimit, nSize -= widthlimit, pbuf += widthlimit) { \ + /* write as many pixel at one time as possible */ \ + if( nSize < widthlimit ) goto End; \ + writePixel##psm##_0(pstart, j%2048, i%2048, pbuf[0], gs.dstbuf.bw); \ + \ + if( widthlimit > 1 ) { \ + writePixel##psm##_0(pstart, (j+1)%2048, i%2048, pbuf[1], gs.dstbuf.bw); \ + \ + if( widthlimit > 2 ) { \ + writePixel##psm##_0(pstart, (j+2)%2048, i%2048, pbuf[2], gs.dstbuf.bw); \ + \ + if( widthlimit > 3 ) { \ + writePixel##psm##_0(pstart, (j+3)%2048, i%2048, pbuf[3], gs.dstbuf.bw); \ + } \ + } \ + } \ + } \ + \ + if( j >= gs.imageEndX ) { assert(j == gs.imageEndX); j = gs.trxpos.dx; } \ + else { assert( gs.imageTransfer == -1 || nSize*sizeof(T)/4 == 0 ); goto End; } \ + } \ +} \ + +// transmit until endX, don't check size since it has already been prevalidated +#define TRANSMIT_HOSTLOCAL_X_(psm, T, widthlimit, blockheight, startX) { \ + for(int tempi = 0; tempi < blockheight; ++tempi) { \ + for(j = startX; j < gs.imageEndX; j++, pbuf++) { \ + writePixel##psm##_0(pstart, j%2048, (i+tempi)%2048, pbuf[0], gs.dstbuf.bw); \ + } \ + pbuf += pitch-fracX; \ + } \ +} \ + +// transfers whole rows +#define TRANSMIT_HOSTLOCAL_Y_24(psm, T, widthlimit, endY) { \ + if( widthlimit != 8 || ((gs.imageEndX-gs.trxpos.dx)%widthlimit) ) { \ + /*GS_LOG("Bad Transmission! %d %d, psm: %d\n", gs.trxpos.dx, gs.imageEndX, DSTPSM);*/ \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += 1, nSize -= 1, pbuf += 3) { \ + writePixel##psm##_0(pstart, j%2048, i%2048, *(u32*)(pbuf), gs.dstbuf.bw); \ + } \ + \ + if( j >= gs.imageEndX ) { assert(gs.imageTransfer == -1 || j == gs.imageEndX); j = gs.trxpos.dx; } \ + else { assert( gs.imageTransfer == -1 || nSize == 0 ); goto End; } \ + } \ + } \ + else { \ + assert( /*(nSize%widthlimit) == 0 &&*/ widthlimit == 8 ); \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += widthlimit, nSize -= widthlimit, pbuf += 3*widthlimit) { \ + if( nSize < widthlimit ) goto End; \ + /* write as many pixel at one time as possible */ \ + writePixel##psm##_0(pstart, j%2048, i%2048, *(u32*)(pbuf+0), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+1)%2048, i%2048, *(u32*)(pbuf+3), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+2)%2048, i%2048, *(u32*)(pbuf+6), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+3)%2048, i%2048, *(u32*)(pbuf+9), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+4)%2048, i%2048, *(u32*)(pbuf+12), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+5)%2048, i%2048, *(u32*)(pbuf+15), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+6)%2048, i%2048, *(u32*)(pbuf+18), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+7)%2048, i%2048, *(u32*)(pbuf+21), gs.dstbuf.bw); \ + } \ + \ + if( j >= gs.imageEndX ) { assert(gs.imageTransfer == -1 || j == gs.imageEndX); j = gs.trxpos.dx; } \ + else { \ + if( nSize < 0 ) { \ + /* extracted too much */ \ + assert( (nSize%3)==0 && nSize > -24 ); \ + j += nSize/3; \ + nSize = 0; \ + } \ + assert( gs.imageTransfer == -1 || nSize == 0 ); \ + goto End; \ + } \ + } \ + } \ +} \ + +// transmit until endX, don't check size since it has already been prevalidated +#define TRANSMIT_HOSTLOCAL_X_24(psm, T, widthlimit, blockheight, startX) { \ + for(int tempi = 0; tempi < blockheight; ++tempi) { \ + for(j = startX; j < gs.imageEndX; j++, pbuf += 3) { \ + writePixel##psm##_0(pstart, j%2048, (i+tempi)%2048, *(u32*)pbuf, gs.dstbuf.bw); \ + } \ + pbuf += 3*(pitch-fracX); \ + } \ +} \ + +// meant for 4bit transfers +#define TRANSMIT_HOSTLOCAL_Y_4(psm, T, widthlimit, endY) { \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += widthlimit, nSize -= widthlimit) { \ + /* write as many pixel at one time as possible */ \ + writePixel##psm##_0(pstart, j%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+1)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ + pbuf++; \ + if( widthlimit > 2 ) { \ + writePixel##psm##_0(pstart, (j+2)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+3)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ + pbuf++; \ + \ + if( widthlimit > 4 ) { \ + writePixel##psm##_0(pstart, (j+4)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+5)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ + pbuf++; \ + \ + if( widthlimit > 6 ) { \ + writePixel##psm##_0(pstart, (j+6)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+7)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ + pbuf++; \ + } \ + } \ + } \ + } \ + \ + if( j >= gs.imageEndX ) { j = gs.trxpos.dx; } \ + else { assert( gs.imageTransfer == -1 || (nSize/32) == 0 ); goto End; } \ + } \ +} \ + +// transmit until endX, don't check size since it has already been prevalidated +#define TRANSMIT_HOSTLOCAL_X_4(psm, T, widthlimit, blockheight, startX) { \ + for(int tempi = 0; tempi < blockheight; ++tempi) { \ + for(j = startX; j < gs.imageEndX; j+=2, pbuf++) { \ + writePixel##psm##_0(pstart, j%2048, (i+tempi)%2048, pbuf[0]&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+1)%2048, (i+tempi)%2048, pbuf[0]>>4, gs.dstbuf.bw); \ + } \ + pbuf += (pitch-fracX)/2; \ + } \ +} \ + +// calculate pitch in source buffer +#define TRANSMIT_PITCH_(pitch, T) (pitch*sizeof(T)) +#define TRANSMIT_PITCH_24(pitch, T) (pitch*3) +#define TRANSMIT_PITCH_4(pitch, T) (pitch/2) + +// special swizzle macros +#define SwizzleBlock24(dst, src, pitch) { \ + u8* pnewsrc = src; \ + u32* pblock = tempblock; \ + \ + for(int by = 0; by < 7; ++by, pblock += 8, pnewsrc += pitch-24) { \ + for(int bx = 0; bx < 8; ++bx, pnewsrc += 3) { \ + pblock[bx] = *(u32*)pnewsrc; \ + } \ + } \ + for(int bx = 0; bx < 7; ++bx, pnewsrc += 3) { \ + /* might be 1 byte out of bounds of GS memory */ \ + pblock[bx] = *(u32*)pnewsrc; \ + } \ + /* do 3 bytes for the last copy */ \ + *((u8*)pblock+28) = pnewsrc[0]; \ + *((u8*)pblock+29) = pnewsrc[1]; \ + *((u8*)pblock+30) = pnewsrc[2]; \ + SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0x00ffffff); \ +} \ + +#define SwizzleBlock24u SwizzleBlock24 + +#define SwizzleBlock8H(dst, src, pitch) { \ + u8* pnewsrc = src; \ + u32* pblock = tempblock; \ + \ + for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch) { \ + u32 u = *(u32*)pnewsrc; \ + pblock[0] = u<<24; \ + pblock[1] = u<<16; \ + pblock[2] = u<<8; \ + pblock[3] = u; \ + u = *(u32*)(pnewsrc+4); \ + pblock[4] = u<<24; \ + pblock[5] = u<<16; \ + pblock[6] = u<<8; \ + pblock[7] = u; \ + } \ + SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0xff000000); \ +} \ + +#define SwizzleBlock8Hu SwizzleBlock8H + +#define SwizzleBlock4HH(dst, src, pitch) { \ + u8* pnewsrc = src; \ + u32* pblock = tempblock; \ + \ + for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch) { \ + u32 u = *(u32*)pnewsrc; \ + pblock[0] = u<<28; \ + pblock[1] = u<<24; \ + pblock[2] = u<<20; \ + pblock[3] = u<<16; \ + pblock[4] = u<<12; \ + pblock[5] = u<<8; \ + pblock[6] = u<<4; \ + pblock[7] = u; \ + } \ + SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0xf0000000); \ +} \ + +#define SwizzleBlock4HHu SwizzleBlock4HH + +#define SwizzleBlock4HL(dst, src, pitch) { \ + u8* pnewsrc = src; \ + u32* pblock = tempblock; \ + \ + for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch) { \ + u32 u = *(u32*)pnewsrc; \ + pblock[0] = u<<24; \ + pblock[1] = u<<20; \ + pblock[2] = u<<16; \ + pblock[3] = u<<12; \ + pblock[4] = u<<8; \ + pblock[5] = u<<4; \ + pblock[6] = u; \ + pblock[7] = u>>4; \ + } \ + SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0x0f000000); \ +} \ + +#define SwizzleBlock4HLu SwizzleBlock4HL + +// ------------------------ +// | Y | +// ------------------------ +// | block | | +// | aligned area | X | +// | | | +// ------------------------ +// | Y | +// ------------------------ +#define DEFINE_TRANSFERLOCAL(psm, T, widthlimit, blockbits, blockwidth, blockheight, TransSfx, SwizzleBlock) \ +int TransferHostLocal##psm(const void* pbyMem, u32 nQWordSize) \ +{ \ + START_HOSTLOCAL(); \ + \ + const T* pbuf = (const T*)pbyMem; \ + int nLeftOver = (nQWordSize*4*2)%(TRANSMIT_PITCH##TransSfx(2, T)); \ + int nSize = nQWordSize*4*2/TRANSMIT_PITCH##TransSfx(2, T); \ + nSize = min(nSize, gs.imageWnew * gs.imageHnew); \ + \ + int pitch, area, fracX; \ + int endY = ROUND_UPPOW2(i, blockheight); \ + int alignedY = ROUND_DOWNPOW2(gs.imageEndY, blockheight); \ + int alignedX = ROUND_DOWNPOW2(gs.imageEndX, blockwidth); \ + bool bAligned, bCanAlign = MOD_POW2(gs.trxpos.dx, blockwidth) == 0 && (j == gs.trxpos.dx) && (alignedY > endY) && alignedX > gs.trxpos.dx; \ + \ + if( (gs.imageEndX-gs.trxpos.dx)%widthlimit ) { \ + /* hack */ \ + int testwidth = (int)nSize - (gs.imageEndY-i)*(gs.imageEndX-gs.trxpos.dx)+(j-gs.trxpos.dx); \ + if((testwidth <= widthlimit) && (testwidth >= -widthlimit)) { \ + /* don't transfer */ \ + /*DEBUG_LOG("bad texture %s: %d %d %d\n", #psm, gs.trxpos.dx, gs.imageEndX, nQWordSize);*/ \ + gs.imageTransfer = -1; \ + } \ + bCanAlign = false; \ + } \ + \ + /* first align on block boundary */ \ + if( MOD_POW2(i, blockheight) || !bCanAlign ) { \ + \ + if( !bCanAlign ) \ + endY = gs.imageEndY; /* transfer the whole image */ \ + else \ + assert( endY < gs.imageEndY); /* part of alignment condition */ \ + \ + if( ((gs.imageEndX-gs.trxpos.dx)%widthlimit) || ((gs.imageEndX-j)%widthlimit) ) { \ + /* transmit with a width of 1 */ \ + TRANSMIT_HOSTLOCAL_Y##TransSfx(psm, T, (1+(DSTPSM == 0x14)), endY); \ + } \ + else { \ + TRANSMIT_HOSTLOCAL_Y##TransSfx(psm, T, widthlimit, endY); \ + } \ + \ + if( nSize == 0 || i == gs.imageEndY ) \ + goto End; \ + } \ + \ + assert( MOD_POW2(i, blockheight) == 0 && j == gs.trxpos.dx); \ + \ + /* can align! */ \ + pitch = gs.imageEndX-gs.trxpos.dx; \ + area = pitch*blockheight; \ + fracX = gs.imageEndX-alignedX; \ + \ + /* on top of checking whether pbuf is alinged, make sure that the width is at least aligned to its limits (due to bugs in pcsx2) */ \ + bAligned = !((uptr)pbuf & 0xf) && (TRANSMIT_PITCH##TransSfx(pitch, T)&0xf) == 0; \ + \ + /* transfer aligning to blocks */ \ + for(; i < alignedY && nSize >= area; i += blockheight, nSize -= area) { \ + \ + if( bAligned || ((DSTPSM==PSMCT24) || (DSTPSM==PSMT8H) || (DSTPSM==PSMT4HH) || (DSTPSM==PSMT4HL)) ) { \ + for(int tempj = gs.trxpos.dx; tempj < alignedX; tempj += blockwidth, pbuf += TRANSMIT_PITCH##TransSfx(blockwidth, T)/sizeof(T)) { \ + SwizzleBlock(pstart + getPixelAddress##psm##_0(tempj, i, gs.dstbuf.bw)*blockbits/8, \ + (u8*)pbuf, TRANSMIT_PITCH##TransSfx(pitch, T)); \ + } \ + } \ + else { \ + for(int tempj = gs.trxpos.dx; tempj < alignedX; tempj += blockwidth, pbuf += TRANSMIT_PITCH##TransSfx(blockwidth, T)/sizeof(T)) { \ + SwizzleBlock##u(pstart + getPixelAddress##psm##_0(tempj, i, gs.dstbuf.bw)*blockbits/8, \ + (u8*)pbuf, TRANSMIT_PITCH##TransSfx(pitch, T)); \ + } \ + } \ + \ + /* transfer the rest */ \ + if( alignedX < gs.imageEndX ) { \ + TRANSMIT_HOSTLOCAL_X##TransSfx(psm, T, widthlimit, blockheight, alignedX); \ + pbuf -= TRANSMIT_PITCH##TransSfx((alignedX-gs.trxpos.dx), T)/sizeof(T); \ + } \ + else pbuf += (blockheight-1)*TRANSMIT_PITCH##TransSfx(pitch, T)/sizeof(T); \ + j = gs.trxpos.dx; \ + } \ + \ + if( TRANSMIT_PITCH##TransSfx(nSize, T)/4 > 0 ) { \ + TRANSMIT_HOSTLOCAL_Y##TransSfx(psm, T, widthlimit, gs.imageEndY); \ + /* sometimes wrong sizes are sent (tekken tag) */ \ + assert( gs.imageTransfer == -1 || TRANSMIT_PITCH##TransSfx(nSize,T)/4 <= 2 ); \ + } \ + \ + END_HOSTLOCAL(); \ + return (nSize * TRANSMIT_PITCH##TransSfx(2, T) + nLeftOver)/2; \ +} \ + +DEFINE_TRANSFERLOCAL(32, u32, 2, 32, 8, 8, _, SwizzleBlock32); +DEFINE_TRANSFERLOCAL(32Z, u32, 2, 32, 8, 8, _, SwizzleBlock32); +DEFINE_TRANSFERLOCAL(24, u8, 8, 32, 8, 8, _24, SwizzleBlock24); +DEFINE_TRANSFERLOCAL(24Z, u8, 8, 32, 8, 8, _24, SwizzleBlock24); +DEFINE_TRANSFERLOCAL(16, u16, 4, 16, 16, 8, _, SwizzleBlock16); +DEFINE_TRANSFERLOCAL(16S, u16, 4, 16, 16, 8, _, SwizzleBlock16); +DEFINE_TRANSFERLOCAL(16Z, u16, 4, 16, 16, 8, _, SwizzleBlock16); +DEFINE_TRANSFERLOCAL(16SZ, u16, 4, 16, 16, 8, _, SwizzleBlock16); +DEFINE_TRANSFERLOCAL(8, u8, 4, 8, 16, 16, _, SwizzleBlock8); +DEFINE_TRANSFERLOCAL(4, u8, 8, 4, 32, 16, _4, SwizzleBlock4); +DEFINE_TRANSFERLOCAL(8H, u8, 4, 32, 8, 8, _, SwizzleBlock8H); +DEFINE_TRANSFERLOCAL(4HL, u8, 8, 32, 8, 8, _4, SwizzleBlock4HL); +DEFINE_TRANSFERLOCAL(4HH, u8, 8, 32, 8, 8, _4, SwizzleBlock4HH); + +//#define T u8 +//#define widthlimit 8 +//#define blockbits 4 +//#define blockwidth 32 +//#define blockheight 16 +// +//void TransferHostLocal4(const void* pbyMem, u32 nQWordSize) +//{ +// START_HOSTLOCAL(); +// +// const T* pbuf = (const T*)pbyMem; +// u32 nSize = nQWordSize*16*2/TRANSMIT_PITCH_4(2, T); +// nSize = min(nSize, gs.imageWnew * gs.imageHnew); +// +// int endY = ROUND_UPPOW2(i, blockheight); +// int alignedY = ROUND_DOWNPOW2(gs.imageEndY, blockheight); +// int alignedX = ROUND_DOWNPOW2(gs.imageEndX, blockwidth); +// bool bCanAlign = MOD_POW2(gs.trxpos.dx, blockwidth) == 0 && (j == gs.trxpos.dx) && (alignedY > endY) && alignedX > gs.trxpos.dx; +// +// if( (gs.imageEndX-gs.trxpos.dx)%widthlimit ) { +// /* hack */ +// if( abs((int)nSize - (gs.imageEndY-i)*(gs.imageEndX-gs.trxpos.dx)+(j-gs.trxpos.dx)) <= widthlimit ) { +// /* don't transfer */ +// /*DEBUG_LOG("bad texture %s: %d %d %d\n", #psm, gs.trxpos.dx, gs.imageEndX, nQWordSize);*/ +// gs.imageTransfer = -1; +// } +// bCanAlign = false; +// } +// +// /* first align on block boundary */ +// if( MOD_POW2(i, blockheight) || !bCanAlign ) { +// +// if( !bCanAlign ) +// endY = gs.imageEndY; /* transfer the whole image */ +// else +// assert( endY < gs.imageEndY); /* part of alignment condition */ +// +// if( (DSTPSM == 0x13 || DSTPSM == 0x14) && ((gs.imageEndX-gs.trxpos.dx)%widthlimit) ) { +// /* transmit with a width of 1 */ +// TRANSMIT_HOSTLOCAL_Y_4(4, T, (1+(DSTPSM == 0x14)), endY); +// } +// else { +// TRANSMIT_HOSTLOCAL_Y_4(4, T, widthlimit, endY); +// } +// +// if( nSize == 0 || i == gs.imageEndY ) +// goto End; +// } +// +// assert( MOD_POW2(i, blockheight) == 0 && j == gs.trxpos.dx); +// +// /* can align! */ +// int pitch = gs.imageEndX-gs.trxpos.dx; +// u32 area = pitch*blockheight; +// int fracX = gs.imageEndX-alignedX; +// +// /* on top of checking whether pbuf is alinged, make sure that the width is at least aligned to its limits (due to bugs in pcsx2) */ +// bool bAligned = !((u32)pbuf & 0xf) && (TRANSMIT_PITCH_4(pitch, T)&0xf) == 0; +// +// /* transfer aligning to blocks */ +// for(; i < alignedY && nSize >= area; i += blockheight, nSize -= area) { +// +// if( bAligned || ((DSTPSM==PSMCT24) || (DSTPSM==PSMT8H) || (DSTPSM==PSMT4HH) || (DSTPSM==PSMT4HL)) ) { +// for(int tempj = gs.trxpos.dx; tempj < alignedX; tempj += blockwidth, pbuf += TRANSMIT_PITCH_4(blockwidth, T)/sizeof(T)) { +// SwizzleBlock4(pstart + getPixelAddress4_0(tempj, i, gs.dstbuf.bw)*blockbits/8, +// (u8*)pbuf, TRANSMIT_PITCH_4(pitch, T)); +// } +// } +// else { +// for(int tempj = gs.trxpos.dx; tempj < alignedX; tempj += blockwidth, pbuf += TRANSMIT_PITCH_4(blockwidth, T)/sizeof(T)) { +// SwizzleBlock4u(pstart + getPixelAddress4_0(tempj, i, gs.dstbuf.bw)*blockbits/8, +// (u8*)pbuf, TRANSMIT_PITCH_4(pitch, T)); +// } +// } +// +// /* transfer the rest */ +// if( alignedX < gs.imageEndX ) { +// TRANSMIT_HOSTLOCAL_X_4(4, T, widthlimit, blockheight, alignedX); +// pbuf -= TRANSMIT_PITCH_4((alignedX-gs.trxpos.dx), T)/sizeof(T); +// } +// else pbuf += (blockheight-1)*TRANSMIT_PITCH_4(pitch, T)/sizeof(T); +// j = 0; +// } +// +// if( TRANSMIT_PITCH_4(nSize, T)/4 > 0 ) { +// TRANSMIT_HOSTLOCAL_Y_4(4, T, widthlimit, gs.imageEndY); +// /* sometimes wrong sizes are sent (tekken tag) */ +// assert( gs.imageTransfer == -1 || TRANSMIT_PITCH_4(nSize,T)/4 <= 2 ); +// } +// +// END_HOSTLOCAL(); +//} + +void TransferLocalHost32(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost24(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost16(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost16S(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost8(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost4(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost8H(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost4HL(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost4HH(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost32Z(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost24Z(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost16Z(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +void TransferLocalHost16SZ(void* pbyMem, u32 nQWordSize) +{FUNCLOG +} + +#define FILL_BLOCK(bw, bh, ox, oy, mult, psm, psmcol) { \ + b.vTexDims = Vector(BLOCK_TEXWIDTH/(float)(bw), BLOCK_TEXHEIGHT/(float)bh, 0, 0); \ + b.vTexBlock = Vector((float)bw/BLOCK_TEXWIDTH, (float)bh/BLOCK_TEXHEIGHT, ((float)ox+0.2f)/BLOCK_TEXWIDTH, ((float)oy+0.05f)/BLOCK_TEXHEIGHT); \ + b.width = bw; \ + b.height = bh; \ + b.colwidth = bh / 4; \ + b.colheight = bw / 8; \ + b.bpp = 32/mult; \ + \ + b.pageTable = &g_pageTable##psm[0][0]; \ + b.blockTable = &g_blockTable##psm[0][0]; \ + b.columnTable = &g_columnTable##psmcol[0][0]; \ + assert( sizeof(g_pageTable##psm) == bw*bh*sizeof(g_pageTable##psm[0][0]) ); \ + psrcf = (float*)&vBlockData[0] + ox + oy * BLOCK_TEXWIDTH; \ + psrcw = (u16*)&vBlockData[0] + ox + oy * BLOCK_TEXWIDTH; \ + for(i = 0; i < bh; ++i) { \ + for(j = 0; j < bw; ++j) { \ + /* fill the table */ \ + u32 u = g_blockTable##psm[(i / b.colheight)][(j / b.colwidth)] * 64 * mult + g_columnTable##psmcol[i%b.colheight][j%b.colwidth]; \ + b.pageTable[i*bw+j] = u; \ + if( floatfmt ) { \ + psrcf[i*BLOCK_TEXWIDTH+j] = (float)(u) / (float)(GPU_TEXWIDTH*mult); \ + } \ + else { \ + psrcw[i*BLOCK_TEXWIDTH+j] = u; \ + } \ + } \ + } \ + \ + if( floatfmt ) { \ + assert( floatfmt ); \ + psrcv = (Vector*)&vBilinearData[0] + ox + oy * BLOCK_TEXWIDTH; \ + for(i = 0; i < bh; ++i) { \ + for(j = 0; j < bw; ++j) { \ + Vector* pv = &psrcv[i*BLOCK_TEXWIDTH+j]; \ + pv->x = psrcf[i*BLOCK_TEXWIDTH+j]; \ + pv->y = psrcf[i*BLOCK_TEXWIDTH+((j+1)%bw)]; \ + pv->z = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+j]; \ + pv->w = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+((j+1)%bw)]; \ + } \ + } \ + } \ + b.getPixelAddress = getPixelAddress##psm; \ + b.getPixelAddress_0 = getPixelAddress##psm##_0; \ + b.writePixel = writePixel##psm; \ + b.writePixel_0 = writePixel##psm##_0; \ + b.readPixel = readPixel##psm; \ + b.readPixel_0 = readPixel##psm##_0; \ + b.TransferHostLocal = TransferHostLocal##psm; \ + b.TransferLocalHost = TransferLocalHost##psm; \ +} \ + +void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, int floatfmt) +{ + FUNCLOG + vBlockData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * (floatfmt ? 4 : 2)); + if( floatfmt ) + vBilinearData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * sizeof(Vector)); + + int i, j; + BLOCK b; + float* psrcf = NULL; + u16* psrcw = NULL; + Vector* psrcv = NULL; + + memset(m_Blocks, 0, sizeof(m_Blocks)); + + // 32 + FILL_BLOCK(64, 32, 0, 0, 1, 32, 32); + m_Blocks[PSMCT32] = b; + + // 24 (same as 32 except write/readPixel are different) + m_Blocks[PSMCT24] = b; + m_Blocks[PSMCT24].writePixel = writePixel24; + m_Blocks[PSMCT24].writePixel_0 = writePixel24_0; + m_Blocks[PSMCT24].readPixel = readPixel24; + m_Blocks[PSMCT24].readPixel_0 = readPixel24_0; + m_Blocks[PSMCT24].TransferHostLocal = TransferHostLocal24; + m_Blocks[PSMCT24].TransferLocalHost = TransferLocalHost24; + + // 8H (same as 32 except write/readPixel are different) + m_Blocks[PSMT8H] = b; + m_Blocks[PSMT8H].writePixel = writePixel8H; + m_Blocks[PSMT8H].writePixel_0 = writePixel8H_0; + m_Blocks[PSMT8H].readPixel = readPixel8H; + m_Blocks[PSMT8H].readPixel_0 = readPixel8H_0; + m_Blocks[PSMT8H].TransferHostLocal = TransferHostLocal8H; + m_Blocks[PSMT8H].TransferLocalHost = TransferLocalHost8H; + + m_Blocks[PSMT4HL] = b; + m_Blocks[PSMT4HL].writePixel = writePixel4HL; + m_Blocks[PSMT4HL].writePixel_0 = writePixel4HL_0; + m_Blocks[PSMT4HL].readPixel = readPixel4HL; + m_Blocks[PSMT4HL].readPixel_0 = readPixel4HL_0; + m_Blocks[PSMT4HL].TransferHostLocal = TransferHostLocal4HL; + m_Blocks[PSMT4HL].TransferLocalHost = TransferLocalHost4HL; + + m_Blocks[PSMT4HH] = b; + m_Blocks[PSMT4HH].writePixel = writePixel4HH; + m_Blocks[PSMT4HH].writePixel_0 = writePixel4HH_0; + m_Blocks[PSMT4HH].readPixel = readPixel4HH; + m_Blocks[PSMT4HH].readPixel_0 = readPixel4HH_0; + m_Blocks[PSMT4HH].TransferHostLocal = TransferHostLocal4HH; + m_Blocks[PSMT4HH].TransferLocalHost = TransferLocalHost4HH; + + // 32z + FILL_BLOCK(64, 32, 64, 0, 1, 32Z, 32); + m_Blocks[PSMT32Z] = b; + + // 24Z (same as 32Z except write/readPixel are different) + m_Blocks[PSMT24Z] = b; + m_Blocks[PSMT24Z].writePixel = writePixel24Z; + m_Blocks[PSMT24Z].writePixel_0 = writePixel24Z_0; + m_Blocks[PSMT24Z].readPixel = readPixel24Z; + m_Blocks[PSMT24Z].readPixel_0 = readPixel24Z_0; + m_Blocks[PSMT24Z].TransferHostLocal = TransferHostLocal24Z; + m_Blocks[PSMT24Z].TransferLocalHost = TransferLocalHost24Z; + + // 16 + FILL_BLOCK(64, 64, 0, 32, 2, 16, 16); + m_Blocks[PSMCT16] = b; + + // 16s + FILL_BLOCK(64, 64, 64, 32, 2, 16S, 16); + m_Blocks[PSMCT16S] = b; + + // 16z + FILL_BLOCK(64, 64, 0, 96, 2, 16Z, 16); + m_Blocks[PSMT16Z] = b; + + // 16sz + FILL_BLOCK(64, 64, 64, 96, 2, 16SZ, 16); + m_Blocks[PSMT16SZ] = b; + + // 8 + FILL_BLOCK(128, 64, 0, 160, 4, 8, 8); + m_Blocks[PSMT8] = b; + + // 4 + FILL_BLOCK(128, 128, 0, 224, 8, 4, 4); + m_Blocks[PSMT4] = b; +} diff --git a/plugins/zzogl-pg/opengl/Mem.h b/plugins/zzogl-pg/opengl/Mem.h new file mode 100644 index 0000000000..63317313a8 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Mem.h @@ -0,0 +1,487 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MEM_H__ +#define __MEM_H__ + +#include +#include + +// works only when base is a power of 2 +#define ROUND_UPPOW2(val, base) (((val)+(base-1))&~(base-1)) +#define ROUND_DOWNPOW2(val, base) ((val)&~(base-1)) +#define MOD_POW2(val, base) ((val)&(base-1)) + +// d3d texture dims +#define BLOCK_TEXWIDTH 128 +#define BLOCK_TEXHEIGHT 512 + +// rest not visible externally +struct BLOCK +{ + BLOCK() { memset(this, 0, sizeof(BLOCK)); } + + // shader constants for this block + Vector vTexBlock; + Vector vTexDims; + int width, height; // dims of one page in pixels + int bpp; + int colwidth, colheight; + u32* pageTable; // offset inside each page + u32* blockTable; + u32* columnTable; + + u32 (*getPixelAddress)(int x, int y, u32 bp, u32 bw); + u32 (*getPixelAddress_0)(int x, int y, u32 bw); + void (*writePixel)(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw); + void (*writePixel_0)(void* pmem, int x, int y, u32 pixel, u32 bw); + u32 (*readPixel)(const void* pmem, int x, int y, u32 bp, u32 bw); + u32 (*readPixel_0)(const void* pmem, int x, int y, u32 bw); + int (*TransferHostLocal)(const void* pbyMem, u32 nQWordSize); + void (*TransferLocalHost)(void* pbyMem, u32 nQWordSize); + + // texture must be of dims BLOCK_TEXWIDTH and BLOCK_TEXHEIGHT + static void FillBlocks(std::vector& vBlockData, std::vector& vBilinearData, int floatfmt); +}; + +extern BLOCK m_Blocks[]; + +extern u32 g_blockTable32[4][8]; +extern u32 g_blockTable32Z[4][8]; +extern u32 g_blockTable16[8][4]; +extern u32 g_blockTable16S[8][4]; +extern u32 g_blockTable16Z[8][4]; +extern u32 g_blockTable16SZ[8][4]; +extern u32 g_blockTable8[4][8]; +extern u32 g_blockTable4[8][4]; + +extern u32 g_columnTable32[8][8]; +extern u32 g_columnTable16[8][16]; +extern u32 g_columnTable8[16][16]; +extern u32 g_columnTable4[16][32]; + +extern u32 g_pageTable32[32][64]; +extern u32 g_pageTable32Z[32][64]; +extern u32 g_pageTable16[64][64]; +extern u32 g_pageTable16S[64][64]; +extern u32 g_pageTable16Z[64][64]; +extern u32 g_pageTable16SZ[64][64]; +extern u32 g_pageTable8[64][128]; +extern u32 g_pageTable4[128][128]; + +static __forceinline u32 getPixelAddress32(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>5) * (bw>>6)) + (x>>6); + u32 word = bp * 64 + basepage * 2048 + g_pageTable32[y&31][x&63]; + //assert (word < 0x100000); + //word = min(word, 0xfffff); + return word; +} + +static __forceinline u32 getPixelAddress32_0(int x, int y, u32 bw) { + u32 basepage = ((y>>5) * (bw>>6)) + (x>>6); + u32 word = basepage * 2048 + g_pageTable32[y&31][x&63]; + //assert (word < 0x100000); + //word = min(word, 0xfffff); + return word; +} + +#define getPixelAddress24 getPixelAddress32 +#define getPixelAddress24_0 getPixelAddress32_0 +#define getPixelAddress8H getPixelAddress32 +#define getPixelAddress8H_0 getPixelAddress32_0 +#define getPixelAddress4HL getPixelAddress32 +#define getPixelAddress4HL_0 getPixelAddress32_0 +#define getPixelAddress4HH getPixelAddress32 +#define getPixelAddress4HH_0 getPixelAddress32_0 + +static __forceinline u32 getPixelAddress16(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +static __forceinline u32 getPixelAddress16_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = basepage * 4096 + g_pageTable16[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +static __forceinline u32 getPixelAddress16S(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16S[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +static __forceinline u32 getPixelAddress16S_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = basepage * 4096 + g_pageTable16S[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +static __forceinline u32 getPixelAddress8(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * ((bw+127)>>7)) + (x>>7); + u32 word = bp * 256 + basepage * 8192 + g_pageTable8[y&63][x&127]; + //assert (word < 0x400000); + //word = min(word, 0x3fffff); + return word; +} + +static __forceinline u32 getPixelAddress8_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * ((bw+127)>>7)) + (x>>7); + u32 word = basepage * 8192 + g_pageTable8[y&63][x&127]; + //assert (word < 0x400000); + //word = min(word, 0x3fffff); + return word; +} + +static __forceinline u32 getPixelAddress4(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>7) * ((bw+127)>>7)) + (x>>7); + u32 word = bp * 512 + basepage * 16384 + g_pageTable4[y&127][x&127]; + //assert (word < 0x800000); + //word = min(word, 0x7fffff); + return word; +} + +static __forceinline u32 getPixelAddress4_0(int x, int y, u32 bw) { + u32 basepage = ((y>>7) * ((bw+127)>>7)) + (x>>7); + u32 word = basepage * 16384 + g_pageTable4[y&127][x&127]; + //assert (word < 0x800000); + //word = min(word, 0x7fffff); + return word; +} + +static __forceinline u32 getPixelAddress32Z(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>5) * (bw>>6)) + (x>>6); + u32 word = bp * 64 + basepage * 2048 + g_pageTable32Z[y&31][x&63]; + //assert (word < 0x100000); + //word = min(word, 0xfffff); + return word; +} + +static __forceinline u32 getPixelAddress32Z_0(int x, int y, u32 bw) { + u32 basepage = ((y>>5) * (bw>>6)) + (x>>6); + u32 word = basepage * 2048 + g_pageTable32Z[y&31][x&63]; + //assert (word < 0x100000); + //word = min(word, 0xfffff); + return word; +} + +#define getPixelAddress24Z getPixelAddress32Z +#define getPixelAddress24Z_0 getPixelAddress32Z_0 + +static __forceinline u32 getPixelAddress16Z(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16Z[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +static __forceinline u32 getPixelAddress16Z_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = basepage * 4096 + g_pageTable16Z[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +static __forceinline u32 getPixelAddress16SZ(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16SZ[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +static __forceinline u32 getPixelAddress16SZ_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = basepage * 4096 + g_pageTable16SZ[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +static __forceinline void writePixel32(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u32*)pmem)[getPixelAddress32(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel24(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *buf = (u8*)&((u32*)pmem)[getPixelAddress32(x, y, bp, bw)]; + u8 *pix = (u8*)&pixel; + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +} + +static __forceinline void writePixel16(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u16*)pmem)[getPixelAddress16(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel16S(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u16*)pmem)[getPixelAddress16S(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel8(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u8*)pmem)[getPixelAddress8(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel8H(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u8*)pmem)[4*getPixelAddress32(x, y, bp, bw)+3] = pixel; +} + +static __forceinline void writePixel4(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u32 addr = getPixelAddress4(x, y, bp, bw); + u8 pix = ((u8*)pmem)[addr/2]; + if (addr & 0x1) ((u8*)pmem)[addr/2] = (pix & 0x0f) | (pixel << 4); + else ((u8*)pmem)[addr/2] = (pix & 0xf0) | (pixel); +} + +static __forceinline void writePixel4HL(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *p = (u8*)pmem + 4*getPixelAddress4HL(x, y, bp, bw)+3; + *p = (*p & 0xf0) | pixel; +} + +static __forceinline void writePixel4HH(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *p = (u8*)pmem + 4*getPixelAddress4HH(x, y, bp, bw)+3; + *p = (*p & 0x0f) | (pixel<<4); +} + +static __forceinline void writePixel32Z(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u32*)pmem)[getPixelAddress32Z(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel24Z(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *buf = (u8*)pmem + 4*getPixelAddress32Z(x, y, bp, bw); + u8 *pix = (u8*)&pixel; + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +} + +static __forceinline void writePixel16Z(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u16*)pmem)[getPixelAddress16Z(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel16SZ(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u16*)pmem)[getPixelAddress16SZ(x, y, bp, bw)] = pixel; +} + + +/////////////// + +static __forceinline u32 readPixel32(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel24(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32(x, y, bp, bw)] & 0xffffff; +} + +static __forceinline u32 readPixel16(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel16S(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16S(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel8(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u8*)pmem)[getPixelAddress8(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel8H(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u8*)pmem)[4*getPixelAddress32(x, y, bp, bw) + 3]; +} + +static __forceinline u32 readPixel4(const void* pmem, int x, int y, u32 bp, u32 bw) { + u32 addr = getPixelAddress4(x, y, bp, bw); + u8 pix = ((const u8*)pmem)[addr/2]; + if (addr & 0x1) + return pix >> 4; + else return pix & 0xf; +} + +static __forceinline u32 readPixel4HL(const void* pmem, int x, int y, u32 bp, u32 bw) { + const u8 *p = (const u8*)pmem+4*getPixelAddress4HL(x, y, bp, bw)+3; + return *p & 0x0f; +} + +static __forceinline u32 readPixel4HH(const void* pmem, int x, int y, u32 bp, u32 bw) { + const u8 *p = (const u8*)pmem+4*getPixelAddress4HH(x, y, bp, bw) + 3; + return *p >> 4; +} + +/////////////// + +static __forceinline u32 readPixel32Z(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32Z(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel24Z(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32Z(x, y, bp, bw)] & 0xffffff; +} + +static __forceinline u32 readPixel16Z(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16Z(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel16SZ(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16SZ(x, y, bp, bw)]; +} + +/////////////////////////////// +// Functions that take 0 bps // +/////////////////////////////// + +static __forceinline void writePixel32_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u32*)pmem)[getPixelAddress32_0(x, y, bw)] = pixel; +} + +static __forceinline void writePixel24_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u8 *buf = (u8*)&((u32*)pmem)[getPixelAddress32_0(x, y, bw)]; + u8 *pix = (u8*)&pixel; +#if defined(_MSC_VER) && defined(__x86_64__) + memcpy(buf, pix, 3); +#else + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +#endif +} + +static __forceinline void writePixel16_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u16*)pmem)[getPixelAddress16_0(x, y, bw)] = pixel; +} + +static __forceinline void writePixel16S_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u16*)pmem)[getPixelAddress16S_0(x, y, bw)] = pixel; +} + +static __forceinline void writePixel8_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u8*)pmem)[getPixelAddress8_0(x, y, bw)] = pixel; +} + +static __forceinline void writePixel8H_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u8*)pmem)[4*getPixelAddress32_0(x, y, bw)+3] = pixel; +} + +static __forceinline void writePixel4_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u32 addr = getPixelAddress4_0(x, y, bw); + u8 pix = ((u8*)pmem)[addr/2]; + if (addr & 0x1) ((u8*)pmem)[addr/2] = (pix & 0x0f) | (pixel << 4); + else ((u8*)pmem)[addr/2] = (pix & 0xf0) | (pixel); +} + +static __forceinline void writePixel4HL_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u8 *p = (u8*)pmem + 4*getPixelAddress4HL_0(x, y, bw)+3; + *p = (*p & 0xf0) | pixel; +} + +static __forceinline void writePixel4HH_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u8 *p = (u8*)pmem + 4*getPixelAddress4HH_0(x, y, bw)+3; + *p = (*p & 0x0f) | (pixel<<4); +} + +static __forceinline void writePixel32Z_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u32*)pmem)[getPixelAddress32Z_0(x, y, bw)] = pixel; +} + +static __forceinline void writePixel24Z_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u8 *buf = (u8*)pmem + 4*getPixelAddress32Z_0(x, y, bw); + u8 *pix = (u8*)&pixel; +#if defined(_MSC_VER) && defined(__x86_64__) + memcpy(buf, pix, 3); +#else + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +#endif +} + +static __forceinline void writePixel16Z_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u16*)pmem)[getPixelAddress16Z_0(x, y, bw)] = pixel; +} + +static __forceinline void writePixel16SZ_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u16*)pmem)[getPixelAddress16SZ_0(x, y, bw)] = pixel; +} + + +/////////////// + +static __forceinline u32 readPixel32_0(const void* pmem, int x, int y, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32_0(x, y, bw)]; +} + +static __forceinline u32 readPixel24_0(const void* pmem, int x, int y, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32_0(x, y, bw)] & 0xffffff; +} + +static __forceinline u32 readPixel16_0(const void* pmem, int x, int y, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16_0(x, y, bw)]; +} + +static __forceinline u32 readPixel16S_0(const void* pmem, int x, int y, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16S_0(x, y, bw)]; +} + +static __forceinline u32 readPixel8_0(const void* pmem, int x, int y, u32 bw) { + return ((const u8*)pmem)[getPixelAddress8_0(x, y, bw)]; +} + +static __forceinline u32 readPixel8H_0(const void* pmem, int x, int y, u32 bw) { + return ((const u8*)pmem)[4*getPixelAddress32_0(x, y, bw) + 3]; +} + +static __forceinline u32 readPixel4_0(const void* pmem, int x, int y, u32 bw) { + u32 addr = getPixelAddress4_0(x, y, bw); + u8 pix = ((const u8*)pmem)[addr/2]; + if (addr & 0x1) + return pix >> 4; + else return pix & 0xf; +} + +static __forceinline u32 readPixel4HL_0(const void* pmem, int x, int y, u32 bw) { + const u8 *p = (const u8*)pmem+4*getPixelAddress4HL_0(x, y, bw)+3; + return *p & 0x0f; +} + +static __forceinline u32 readPixel4HH_0(const void* pmem, int x, int y, u32 bw) { + const u8 *p = (const u8*)pmem+4*getPixelAddress4HH_0(x, y, bw) + 3; + return *p >> 4; +} + +/////////////// + +static __forceinline u32 readPixel32Z_0(const void* pmem, int x, int y, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32Z_0(x, y, bw)]; +} + +static __forceinline u32 readPixel24Z_0(const void* pmem, int x, int y, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32Z_0(x, y, bw)] & 0xffffff; +} + +static __forceinline u32 readPixel16Z_0(const void* pmem, int x, int y, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16Z_0(x, y, bw)]; +} + +static __forceinline u32 readPixel16SZ_0(const void* pmem, int x, int y, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16SZ_0(x, y, bw)]; +} + +#endif /* __MEM_H__ */ diff --git a/plugins/zzogl-pg/opengl/README.txt b/plugins/zzogl-pg/opengl/README.txt new file mode 100644 index 0000000000..edeb776031 --- /dev/null +++ b/plugins/zzogl-pg/opengl/README.txt @@ -0,0 +1,13 @@ +ZeroGS OpenGL +------------- +author: zerofrog (@gmail.com) + +ZeroGS heavily uses GPU shaders. All the shaders are written in nVidia's Cg language and can be found in ps2hw.fx. + +'Dev' versions of ZeroGS directly read ps2hw.fx +'Release' versions of ZeroGS read a precompiled version of ps2hw.fx from ps2hw.dat. In order to build ps2hw.dat, compile ZeroGSShaders and execute: + +./ZeroGSShaders ps2hw.fx ps2hw.dat + +For Windows users, once ZeroGSShaders is built, run buildshaders.bat directly. It will update all necessary resource files. +Note that ZeroGSShaders has only been tested in Windows so far, but the Windows ps2hw.dat can be used in linux builds. \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/Regs.cpp b/plugins/zzogl-pg/opengl/Regs.cpp new file mode 100644 index 0000000000..4dcfe64f31 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Regs.cpp @@ -0,0 +1,1061 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerorog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "GS.h" +#include "Mem.h" +#include "Regs.h" +#include "PS2Etypes.h" + +#include "zerogs.h" +#include "targets.h" + +const u32 g_primmult[8] = { 1, 2, 2, 3, 3, 3, 2, 0xff }; +const u32 g_primsub[8] = { 1, 2, 1, 3, 1, 1, 2, 0 }; + +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif + +GIFRegHandler g_GIFPackedRegHandlers[16] = { + GIFRegHandlerPRIM, GIFPackedRegHandlerRGBA, GIFPackedRegHandlerSTQ, GIFPackedRegHandlerUV, + GIFPackedRegHandlerXYZF2, GIFPackedRegHandlerXYZ2, GIFRegHandlerTEX0_1, GIFRegHandlerTEX0_2, + GIFRegHandlerCLAMP_1, GIFRegHandlerCLAMP_2, GIFPackedRegHandlerFOG, GIFPackedRegHandlerNull, + GIFRegHandlerXYZF3, GIFRegHandlerXYZ3, GIFPackedRegHandlerA_D, GIFPackedRegHandlerNOP }; + +GIFRegHandler g_GIFRegHandlers[] = { + GIFRegHandlerPRIM, GIFRegHandlerRGBAQ, GIFRegHandlerST, GIFRegHandlerUV, + GIFRegHandlerXYZF2, GIFRegHandlerXYZ2, GIFRegHandlerTEX0_1, GIFRegHandlerTEX0_2, + GIFRegHandlerCLAMP_1, GIFRegHandlerCLAMP_2, GIFRegHandlerFOG, GIFRegHandlerNull, + GIFRegHandlerXYZF3, GIFRegHandlerXYZ3, GIFRegHandlerNOP, GIFRegHandlerNOP, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerTEX1_1, GIFRegHandlerTEX1_2, GIFRegHandlerTEX2_1, GIFRegHandlerTEX2_2, + GIFRegHandlerXYOFFSET_1,GIFRegHandlerXYOFFSET_2,GIFRegHandlerPRMODECONT,GIFRegHandlerPRMODE, + GIFRegHandlerTEXCLUT, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerSCANMSK, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerMIPTBP1_1, GIFRegHandlerMIPTBP1_2, GIFRegHandlerMIPTBP2_1, GIFRegHandlerMIPTBP2_2, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerTEXA, + GIFRegHandlerNull, GIFRegHandlerFOGCOL, GIFRegHandlerNull, GIFRegHandlerTEXFLUSH, + GIFRegHandlerSCISSOR_1, GIFRegHandlerSCISSOR_2, GIFRegHandlerALPHA_1, GIFRegHandlerALPHA_2, + GIFRegHandlerDIMX, GIFRegHandlerDTHE, GIFRegHandlerCOLCLAMP, GIFRegHandlerTEST_1, + GIFRegHandlerTEST_2, GIFRegHandlerPABE, GIFRegHandlerFBA_1, GIFRegHandlerFBA_2, + GIFRegHandlerFRAME_1, GIFRegHandlerFRAME_2, GIFRegHandlerZBUF_1, GIFRegHandlerZBUF_2, + GIFRegHandlerBITBLTBUF, GIFRegHandlerTRXPOS, GIFRegHandlerTRXREG, GIFRegHandlerTRXDIR, + GIFRegHandlerHWREG, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerSIGNAL, GIFRegHandlerFINISH, GIFRegHandlerLABEL, GIFRegHandlerNull }; + +C_ASSERT(sizeof(g_GIFRegHandlers)/sizeof(g_GIFRegHandlers[0]) == 100 ); + +// values for keeping track of changes +u32 s_uTex1Data[2][2] = {{0,}}; +u32 s_uClampData[2] = {0,}; + +u32 results[65535] = {0,}; + +// return true if triangle SHOULD be painted. +inline bool NoHighlights(int i) { +// This is hack-code, I still in search of correct reason, why some triangles should not be drawn. + + int resultA = prim->iip + ((prim->tme) << 1) + ((prim->fge) << 2) + ((prim->abe) << 3) + ((prim->aa1) << 4) + ((prim->fst) << 5) + ((prim->ctxt) << 6) + ((prim->fix)<< 7) + + ((ZeroGS::vb[i].zbuf.psm ) << 8); +// if ( results[resultA] == 0 ) { +// results[resultA] = 1; +// ERROR_LOG("%x = %d %d %d %d %d %d %d %d psm: %x\n", resultA, prim->iip, (prim->tme), (prim->fge), (prim->abe) , (prim->aa1) ,(prim->fst), (prim->ctxt), (prim->fix), ZeroGS::vb[i].zbuf.psm) ; +// } +// if (resultA == 0xb && ZeroGS::vb[i].zbuf.zmsk ) return false; //ATF + + const pixTest curtest = ZeroGS::vb[i].test; + int result = curtest.ate + ((curtest.atst) << 1) +((curtest.afail) << 4) + ((curtest.date) << 6) + ((curtest.datm) << 7) + ((curtest.zte) << 8) + ((curtest.ztst)<< 9); +// if (resultA == 0xb) +// if ( results[result] == 0) { +// results[result] = 1; +// ERROR_LOG("0x%x = %d %d %d %d %d %d %d %d \n", result, curtest.ate, curtest.atst, curtest.aref, curtest.afail, curtest.date, curtest.datm, curtest.zte, curtest.ztst); +// } +// 0, -50b, -500, !-300, -30a, -50a, -5cb, +100 (zte==1), -50d +// if (result == 0x50b && ZeroGS::vb[i].zbuf.zmsk ) return false; //ATF + + if ((resultA == 0x3a2a || resultA == 0x312a) && (result == 0x302 || result == 0x700) && (ZeroGS::vb[i].zbuf.zmsk)) return false; // Silent Hill:SM and Front Mission 5, result != 0x300 + if (((resultA == 0x3100) || (resultA == 0x3108)) && ((result == 0x54c) || (result == 0x50c)) && (ZeroGS::vb[i].zbuf.zmsk)) return false; // Okage + if ((resultA == 0x310a) && (result == 0x0)) return false; // Radiata Stories + if (resultA == 0x3a6a && (result == 0x300 || result == 0x500)&& ZeroGS::vb[i].zbuf.zmsk) return false; // Okami, result != 0x30d +// if ((resultA == 0x300b) && (result == 0x300) && ZeroGS::vb[i].zbuf.zmsk) return false; // ATF, but no Melty Blood + +// Old code + return (!(g_GameSettings&GAME_XENOSPECHACK) || !ZeroGS::vb[i].zbuf.zmsk || prim->iip ) ; +} + +void __fastcall GIFPackedRegHandlerNull(u32* data) +{ + FUNCLOG + DEBUG_LOG("Unexpected packed reg handler %8.8lx_%8.8lx %x\n", data[0], data[1], data[2]); +} + +void __fastcall GIFPackedRegHandlerRGBA(u32* data) +{ + FUNCLOG + gs.rgba = (data[0] & 0xff) | + ((data[1] & 0xff) << 8) | + ((data[2] & 0xff) << 16) | + ((data[3] & 0xff) << 24); + gs.vertexregs.rgba = gs.rgba; + gs.vertexregs.q = gs.q; +} + +void __fastcall GIFPackedRegHandlerSTQ(u32* data) +{ + FUNCLOG + *(u32*)&gs.vertexregs.s = data[0]&0xffffff00; + *(u32*)&gs.vertexregs.t = data[1]&0xffffff00; + *(u32*)&gs.q = data[2]; +} + +void __fastcall GIFPackedRegHandlerUV(u32* data) +{ + FUNCLOG + gs.vertexregs.u = data[0] & 0x3fff; + gs.vertexregs.v = data[1] & 0x3fff; +} + +void __forceinline KICK_VERTEX2() +{ + FUNCLOG + if (++gs.primC >= (int)g_primmult[prim->prim]) + { + if ( NoHighlights(prim->ctxt) ) + (*ZeroGS::drawfn[prim->prim])(); + gs.primC -= g_primsub[prim->prim]; + } +} + +void __forceinline KICK_VERTEX3() +{ + FUNCLOG + if (++gs.primC >= (int)g_primmult[prim->prim]) + { + gs.primC -= g_primsub[prim->prim]; + if (prim->prim == 5) + { + /* tri fans need special processing */ + if (gs.nTriFanVert == gs.primIndex) + gs.primIndex = (gs.primIndex+1)%ArraySize(gs.gsvertex); + } + } +} + +void __fastcall GIFPackedRegHandlerXYZF2(u32* data) +{ + FUNCLOG + gs.vertexregs.x = (data[0] >> 0) & 0xffff; + gs.vertexregs.y = (data[1] >> 0) & 0xffff; + gs.vertexregs.z = (data[2] >> 4) & 0xffffff; + gs.vertexregs.f = (data[3] >> 4) & 0xff; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ArraySize(gs.gsvertex); + + if( data[3] & 0x8000 ) { + KICK_VERTEX3(); + } + else { + KICK_VERTEX2(); + } +} + +void __fastcall GIFPackedRegHandlerXYZ2(u32* data) +{ + FUNCLOG + gs.vertexregs.x = (data[0] >> 0) & 0xffff; + gs.vertexregs.y = (data[1] >> 0) & 0xffff; + gs.vertexregs.z = data[2]; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ArraySize(gs.gsvertex); + + if( data[3] & 0x8000 ) { + KICK_VERTEX3(); + } + else { + KICK_VERTEX2(); + } +} + +void __fastcall GIFPackedRegHandlerFOG(u32* data) +{ + FUNCLOG + gs.vertexregs.f = (data[3]&0xff0)>>4; +} + +void __fastcall GIFPackedRegHandlerA_D(u32* data) +{ + FUNCLOG + if((data[2] & 0xff) < 100) + g_GIFRegHandlers[data[2] & 0xff](data); + else + GIFRegHandlerNull(data); +} + +void __fastcall GIFPackedRegHandlerNOP(u32* data) +{FUNCLOG +} + +extern int g_PrevBitwiseTexX, g_PrevBitwiseTexY; + +void tex0Write(int i, u32 *data) +{ + FUNCLOG + u32 psm = ZZOglGet_psm_TexBitsFix(data[0]); + + if( m_Blocks[psm].bpp == 0 ) { + // kh and others + return; + } + + ZeroGS::vb[i].uNextTex0Data[0] = data[0]; + ZeroGS::vb[i].uNextTex0Data[1] = data[1]; + ZeroGS::vb[i].bNeedTexCheck = 1; + + // don't update unless necessary + if( PSMT_ISCLUT(psm) ) { + if( ZeroGS::CheckChangeInClut(data[1], psm) ) { + // loading clut, so flush whole texture + ZeroGS::vb[i].FlushTexData(); + } + // check if csa is the same!! (ffx bisaid island, grass) + else if( (data[1]&0x1f780000) != (ZeroGS::vb[i].uCurTex0Data[1]&0x1f780000) ) { + ZeroGS::Flush(i); // flush any previous entries + } + } +} + +void tex2Write(int i, u32 *data) { + FUNCLOG + tex0Info& tex0 = ZeroGS::vb[i].tex0; + + if( ZeroGS::vb[i].bNeedTexCheck ) + ZeroGS::vb[i].FlushTexData(); + + u32 psm = ZZOglGet_psm_TexBitsFix(data[0]); + + u32* s_uTex0Data = ZeroGS::vb[i].uCurTex0Data; + + // don't update unless necessary +// if( ZZOglGet_psm_TexBitsFix(*s_uTex0Data) == ZZOglGet_psm_TexBitsFix(data[0]) ) { // psm is the same + if (ZZOglAllExceptClutIsSame(s_uTex0Data, data)) { + if (!PSMT_ISCLUT(psm)) + return; + + // have to write the CLUT again if changed + if (ZZOglClutMinusCLDunchanged(s_uTex0Data, data)) { + tex0.cld = ZZOglGet_cld_TexBits(data[1]); + if (tex0.cld != 0) { + ZeroGS::texClutWrite(i); + // invalidate to make sure target didn't change! + ZeroGS::vb[i].bVarsTexSync = FALSE; + } + return; + } + } + + ZeroGS::Flush(i); + ZeroGS::vb[i].bVarsTexSync = FALSE; + ZeroGS::vb[i].bTexConstsSync = FALSE; + + s_uTex0Data[0] = (s_uTex0Data[0]&~0x03f00000)|(psm<<20); + s_uTex0Data[1] = (s_uTex0Data[1]&0x1f)|(data[1]&~0x1f); + + tex0.psm = ZZOglGet_psm_TexBitsFix(data[0]); + + if( PSMT_ISCLUT(tex0.psm) ) + ZeroGS::CluttingForFlushedTex(&tex0, data[1], i); +} + +__forceinline void frameWrite(int i, u32 *data) { + FUNCLOG + frameInfo& gsfb = ZeroGS::vb[i].gsfb; + + if((gsfb.fbp == ZZOglGet_fbp_FrameBitsMult(data[0])) && (gsfb.fbw == ZZOglGet_fbw_FrameBitsMult(data[0])) && + (gsfb.psm == ZZOglGet_psm_FrameBits(data[0])) && (gsfb.fbm == ZZOglGet_fbm_FrameBits(data[0])) ) { + return; + } + + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + gsfb.fbp = ZZOglGet_fbp_FrameBitsMult(data[0]); + gsfb.fbw = ZZOglGet_fbw_FrameBitsMult(data[0]); + gsfb.psm = ZZOglGet_psm_FrameBits(data[0]); + gsfb.fbm = ZZOglGet_fbm_FrameBitsFix(data[0],data[1]); + gsfb.fbh = ZZOglGet_fbh_FrameBitsCalc(data[0]); +// gsfb.fbhCalc = gsfb.fbh; + + ZeroGS::vb[i].bNeedFrameCheck = 1; +} + +__forceinline void testWrite(int i, u32 *data) +{ + FUNCLOG + pixTest* test = &ZeroGS::vb[i].test; + + if( (*(u32*)test & 0x0007ffff) == (data[0] & 0x0007ffff) ) + return; + + ZeroGS::Flush(i); + *(u32*)test = data[0]; + +// test.ate = (data[0] ) & 0x1; +// test.atst = (data[0] >> 1) & 0x7; +// test.aref = (data[0] >> 4) & 0xff; +// test.afail = (data[0] >> 12) & 0x3; +// test.date = (data[0] >> 14) & 0x1; +// test.datm = (data[0] >> 15) & 0x1; +// test.zte = (data[0] >> 16) & 0x1; +// test.ztst = (data[0] >> 17) & 0x3; +} + +__forceinline void clampWrite(int i, u32 *data) +{ + FUNCLOG + clampInfo& clamp = ZeroGS::vb[i].clamp; + + if ((s_uClampData[i] != data[0]) || (((clamp.minv>>8) | (clamp.maxv<<2)) != (data[1]&0x0fff))) { + + ZeroGS::Flush(i); + s_uClampData[i] = data[0]; + + clamp.wms = (data[0] ) & 0x3; + clamp.wmt = (data[0] >> 2) & 0x3; + clamp.minu = (data[0] >> 4) & 0x3ff; + clamp.maxu = (data[0] >> 14) & 0x3ff; + clamp.minv =((data[0] >> 24) & 0xff) | ((data[1] & 0x3) << 8); + clamp.maxv = (data[1] >> 2) & 0x3ff; + + ZeroGS::vb[i].bTexConstsSync = FALSE; + } +} + +void __fastcall GIFRegHandlerNull(u32* data) +{ + FUNCLOG +#ifdef _DEBUG + if( (((uptr)&data[2])&0xffff) == 0 ) + return; + + // 0x7f happens on a lot of games + if( data[2] != 0x7f && (data[0] || data[1]) ) { + DEBUG_LOG("Unexpected reg handler %x %x %x\n", data[0], data[1], data[2]); + } +#endif +} + +void __fastcall GIFRegHandlerPRIM(u32 *data) +{ + FUNCLOG + if (data[0] & ~0x3ff) { + //WARN_LOG("warning: unknown bits in prim %8.8lx_%8.8lx\n", data[1], data[0]); + } + + gs.nTriFanVert = gs.primIndex; + gs.primC = 0; + prim->prim = (data[0]) & 0x7; + gs._prim[0].prim = (data[0]) & 0x7; + gs._prim[1].prim = (data[0]) & 0x7; + gs._prim[1]._val = (data[0]>>3)&0xff; + + ZeroGS::Prim(); +} + +void __fastcall GIFRegHandlerRGBAQ(u32* data) +{ + FUNCLOG + gs.rgba = data[0]; + gs.vertexregs.rgba = data[0]; + *(u32*)&gs.vertexregs.q = data[1]; +} + +void __fastcall GIFRegHandlerST(u32* data) +{ + FUNCLOG + *(u32*)&gs.vertexregs.s = data[0]&0xffffff00; + *(u32*)&gs.vertexregs.t = data[1]&0xffffff00; + //*(u32*)&gs.q = data[2]; +} + +void __fastcall GIFRegHandlerUV(u32* data) +{ + FUNCLOG + gs.vertexregs.u = (data[0]) & 0x3fff; + gs.vertexregs.v = (data[0] >> 16) & 0x3fff; +} + +void __fastcall GIFRegHandlerXYZF2(u32* data) +{ + FUNCLOG + gs.vertexregs.x = (data[0]) & 0xffff; + gs.vertexregs.y = (data[0] >> (16)) & 0xffff; + gs.vertexregs.z = data[1] & 0xffffff; + gs.vertexregs.f = data[1] >> 24; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + KICK_VERTEX2(); +} + +void __fastcall GIFRegHandlerXYZ2(u32* data) +{ + FUNCLOG + gs.vertexregs.x = (data[0]) & 0xffff; + gs.vertexregs.y = (data[0] >> (16)) & 0xffff; + gs.vertexregs.z = data[1]; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + KICK_VERTEX2(); +} + +void __fastcall GIFRegHandlerTEX0_1(u32* data) +{ + FUNCLOG + if( !NoHighlights(0)) { + return; + } + tex0Write(0, data); +} + +void __fastcall GIFRegHandlerTEX0_2(u32* data) +{ + FUNCLOG + if( !NoHighlights(1) ) { + return; + } + tex0Write(1, data); +} + +void __fastcall GIFRegHandlerCLAMP_1(u32* data) +{ + FUNCLOG + if( !NoHighlights(0) ) { + return; + } + clampWrite(0, data); +} + +void __fastcall GIFRegHandlerCLAMP_2(u32* data) +{ + FUNCLOG + if( !NoHighlights(1) ) { + return; + } + clampWrite(1, data); +} + +void __fastcall GIFRegHandlerFOG(u32* data) +{ + FUNCLOG + //gs.gsvertex[gs.primIndex].f = (data[1] >> 24); // shift to upper bits + gs.vertexregs.f = data[1]>>24; +} + +void __fastcall GIFRegHandlerXYZF3(u32* data) +{ + FUNCLOG + gs.vertexregs.x = (data[0]) & 0xffff; + gs.vertexregs.y = (data[0] >> (16)) & 0xffff; + gs.vertexregs.z = data[1] & 0xffffff; + gs.vertexregs.f = data[1] >> 24; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + KICK_VERTEX3(); +} + +void __fastcall GIFRegHandlerXYZ3(u32* data) +{ + FUNCLOG + gs.vertexregs.x = (data[0]) & 0xffff; + gs.vertexregs.y = (data[0] >> (16)) & 0xffff; + gs.vertexregs.z = data[1]; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + KICK_VERTEX3(); +} + +void __fastcall GIFRegHandlerNOP(u32* data) +{ + FUNCLOG +} + +void tex1Write(int i, u32* data) +{ + FUNCLOG + tex1Info& tex1 = ZeroGS::vb[i].tex1; + + if( conf.bilinear == 1 && (tex1.mmag != ((data[0] >> 5) & 0x1) || tex1.mmin != ((data[0] >> 6) & 0x7)) ) { + ZeroGS::Flush(i); + ZeroGS::vb[i].bVarsTexSync = FALSE; + } + tex1.lcm = (data[0] ) & 0x1; + tex1.mxl = (data[0] >> 2) & 0x7; + tex1.mmag = (data[0] >> 5) & 0x1; + tex1.mmin = (data[0] >> 6) & 0x7; + tex1.mtba = (data[0] >> 9) & 0x1; + tex1.l = (data[0] >> 19) & 0x3; + tex1.k = (data[1] >> 4) & 0xff; +} + +void __fastcall GIFRegHandlerTEX1_1(u32* data) +{ + FUNCLOG + + if( !NoHighlights(0)) { + return; + } + + tex1Write(0, data); +} + +void __fastcall GIFRegHandlerTEX1_2(u32* data) +{ + FUNCLOG + if( !NoHighlights(1) ) + return; + + tex1Write(1, data); +} + +void __fastcall GIFRegHandlerTEX2_1(u32* data) +{ + FUNCLOG + tex2Write(0, data); +} + +void __fastcall GIFRegHandlerTEX2_2(u32* data) +{ + FUNCLOG + tex2Write(1, data); +} + +void __fastcall GIFRegHandlerXYOFFSET_1(u32* data) +{ + FUNCLOG + // eliminator low 4 bits for now + ZeroGS::vb[0].offset.x = (data[0]) & 0xffff; + ZeroGS::vb[0].offset.y = (data[1]) & 0xffff; + +// if( !conf.interlace ) { +// ZeroGS::vb[0].offset.x &= ~15; +// ZeroGS::vb[0].offset.y &= ~15; +// } +} + +void __fastcall GIFRegHandlerXYOFFSET_2(u32* data) +{ + FUNCLOG + ZeroGS::vb[1].offset.x = (data[0]) & 0xffff; + ZeroGS::vb[1].offset.y = (data[1]) & 0xffff; + +// if( !conf.interlace ) { +// ZeroGS::vb[1].offset.x &= ~15; +// ZeroGS::vb[1].offset.y &= ~15; +// } +} + +void __fastcall GIFRegHandlerPRMODECONT(u32* data) +{ + FUNCLOG + gs.prac = data[0] & 0x1; + prim = &gs._prim[gs.prac]; + + ZeroGS::Prim(); +} + +void __fastcall GIFRegHandlerPRMODE(u32* data) +{ + FUNCLOG + gs._prim[0]._val = (data[0]>>3)&0xff; + + if (gs.prac == 0) + ZeroGS::Prim(); +} + +void __fastcall GIFRegHandlerTEXCLUT(u32* data) +{ + FUNCLOG + if( ZeroGS::vb[0].bNeedTexCheck ) + ZeroGS::vb[0].FlushTexData(); + if( ZeroGS::vb[1].bNeedTexCheck ) + ZeroGS::vb[1].FlushTexData(); + gs.clut.cbw = ((data[0] ) & 0x3f) * 64; + gs.clut.cou = ((data[0] >> 6) & 0x3f) * 16; + gs.clut.cov = (data[0] >> 12) & 0x3ff; +} + +void __fastcall GIFRegHandlerSCANMSK(u32* data) +{ + FUNCLOG +// ZeroGS::Flush(0); +// ZeroGS::Flush(1); +// ZeroGS::ResolveC(&ZeroGS::vb[0]); +// ZeroGS::ResolveZ(&ZeroGS::vb[0]); + + gs.smask = data[0] & 0x3; +} + +void __fastcall GIFRegHandlerMIPTBP1_1(u32* data) +{ + FUNCLOG + miptbpInfo& miptbp0 = ZeroGS::vb[0].miptbp0; + miptbp0.tbp[0] = (data[0] ) & 0x3fff; + miptbp0.tbw[0] = (data[0] >> 14) & 0x3f; + miptbp0.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + miptbp0.tbw[1] = (data[1] >> 2) & 0x3f; + miptbp0.tbp[2] = (data[1] >> 8) & 0x3fff; + miptbp0.tbw[2] = (data[1] >> 22) & 0x3f; +} + +void __fastcall GIFRegHandlerMIPTBP1_2(u32* data) +{ + FUNCLOG + miptbpInfo& miptbp0 = ZeroGS::vb[1].miptbp0; + miptbp0.tbp[0] = (data[0] ) & 0x3fff; + miptbp0.tbw[0] = (data[0] >> 14) & 0x3f; + miptbp0.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + miptbp0.tbw[1] = (data[1] >> 2) & 0x3f; + miptbp0.tbp[2] = (data[1] >> 8) & 0x3fff; + miptbp0.tbw[2] = (data[1] >> 22) & 0x3f; +} + +void __fastcall GIFRegHandlerMIPTBP2_1(u32* data) +{ + FUNCLOG + miptbpInfo& miptbp1 = ZeroGS::vb[0].miptbp1; + miptbp1.tbp[0] = (data[0] ) & 0x3fff; + miptbp1.tbw[0] = (data[0] >> 14) & 0x3f; + miptbp1.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + miptbp1.tbw[1] = (data[1] >> 2) & 0x3f; + miptbp1.tbp[2] = (data[1] >> 8) & 0x3fff; + miptbp1.tbw[2] = (data[1] >> 22) & 0x3f; +} + +void __fastcall GIFRegHandlerMIPTBP2_2(u32* data) +{ + FUNCLOG + miptbpInfo& miptbp1 = ZeroGS::vb[1].miptbp1; + miptbp1.tbp[0] = (data[0] ) & 0x3fff; + miptbp1.tbw[0] = (data[0] >> 14) & 0x3f; + miptbp1.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + miptbp1.tbw[1] = (data[1] >> 2) & 0x3f; + miptbp1.tbp[2] = (data[1] >> 8) & 0x3fff; + miptbp1.tbw[2] = (data[1] >> 22) & 0x3f; +} + +void __fastcall GIFRegHandlerTEXA(u32* data) +{ + FUNCLOG + texaInfo newinfo; + newinfo.aem = (data[0] >> 15) & 0x1; + newinfo.ta[0] = data[0] & 0xff; + newinfo.ta[1] = data[1] & 0xff; + + if( *(u32*)&newinfo != *(u32*)&gs.texa ) { + ZeroGS::Flush(0); + ZeroGS::Flush(1); + *(u32*)&gs.texa = *(u32*)&newinfo; + gs.texa.fta[0] = newinfo.ta[0]/255.0f; + gs.texa.fta[1] = newinfo.ta[1]/255.0f; + + ZeroGS::vb[0].bTexConstsSync = FALSE; + ZeroGS::vb[1].bTexConstsSync = FALSE; + } +} + +void __fastcall GIFRegHandlerFOGCOL(u32* data) +{ + FUNCLOG + ZeroGS::SetFogColor(data[0]&0xffffff); +} + +void __fastcall GIFRegHandlerTEXFLUSH(u32* data) +{ + FUNCLOG + ZeroGS::SetTexFlush(); +} + +void __fastcall GIFRegHandlerSCISSOR_1(u32* data) +{ + FUNCLOG + Rect2& scissor = ZeroGS::vb[0].scissor; + + Rect2 newscissor; + + newscissor.x0 = ((data[0] ) & 0x7ff) << 3; + newscissor.x1 = ((data[0] >> 16) & 0x7ff) << 3; + newscissor.y0 = ((data[1] ) & 0x7ff) << 3; + newscissor.y1 = ((data[1] >> 16) & 0x7ff) << 3; + + if( newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 || + newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0 ) { + + ZeroGS::Flush(0); + scissor = newscissor; + + ZeroGS::vb[0].bNeedFrameCheck = 1; + } +} + +void __fastcall GIFRegHandlerSCISSOR_2(u32* data) +{ + FUNCLOG + Rect2& scissor = ZeroGS::vb[1].scissor; + + Rect2 newscissor; + + newscissor.x0 = ((data[0] ) & 0x7ff) << 3; + newscissor.x1 = ((data[0] >> 16) & 0x7ff) << 3; + newscissor.y0 = ((data[1] ) & 0x7ff) << 3; + newscissor.y1 = ((data[1] >> 16) & 0x7ff) << 3; + + if( newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 || + newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0 ) { + + ZeroGS::Flush(1); + scissor = newscissor; + + // flush everything + ZeroGS::vb[1].bNeedFrameCheck = 1; + } +} + +void __fastcall GIFRegHandlerALPHA_1(u32* data) +{ + FUNCLOG + alphaInfo newalpha; + newalpha.abcd = *(u8*)data; + newalpha.fix = *(u8*)(data+1); + + if( *(u16*)&newalpha != *(u16*)&ZeroGS::vb[0].alpha ) { + ZeroGS::Flush(0); + + if( newalpha.a == 3 ) newalpha.a = 0; + if( newalpha.b == 3 ) newalpha.b = 0; + if( newalpha.c == 3 ) newalpha.c = 0; + if( newalpha.d == 3 ) newalpha.d = 0; + + *(u16*)&ZeroGS::vb[0].alpha = *(u16*)&newalpha; + } +} + +void __fastcall GIFRegHandlerALPHA_2(u32* data) +{ + FUNCLOG + alphaInfo newalpha; + newalpha.abcd = *(u8*)data; + newalpha.fix = *(u8*)(data+1); + + if( *(u16*)&newalpha != *(u16*)&ZeroGS::vb[1].alpha ) { + ZeroGS::Flush(1); + + if( newalpha.a == 3 ) newalpha.a = 0; + if( newalpha.b == 3 ) newalpha.b = 0; + if( newalpha.c == 3 ) newalpha.c = 0; + if( newalpha.d == 3 ) newalpha.d = 0; + + *(u16*)&ZeroGS::vb[1].alpha = *(u16*)&newalpha; + } +} + +void __fastcall GIFRegHandlerDIMX(u32* data) +{ + FUNCLOG +} + +void __fastcall GIFRegHandlerDTHE(u32* data) +{ + FUNCLOG + gs.dthe = data[0] & 0x1; +} + +void __fastcall GIFRegHandlerCOLCLAMP(u32* data) +{ + FUNCLOG + gs.colclamp = data[0] & 0x1; +} + +void __fastcall GIFRegHandlerTEST_1(u32* data) +{ + FUNCLOG + testWrite(0, data); +} + +void __fastcall GIFRegHandlerTEST_2(u32* data) +{ + FUNCLOG + testWrite(1, data); +} + +void __fastcall GIFRegHandlerPABE(u32* data) +{ + FUNCLOG + //ZeroGS::SetAlphaChanged(0, GPUREG_PABE); + //ZeroGS::SetAlphaChanged(1, GPUREG_PABE); + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + gs.pabe = *data & 0x1; +} + +void __fastcall GIFRegHandlerFBA_1(u32* data) +{ + FUNCLOG + ZeroGS::Flush(0); + ZeroGS::Flush(1); + ZeroGS::vb[0].fba.fba = *data & 0x1; +} + +void __fastcall GIFRegHandlerFBA_2(u32* data) +{ + FUNCLOG + ZeroGS::Flush(0); + ZeroGS::Flush(1); + ZeroGS::vb[1].fba.fba = *data & 0x1; +} + +void __fastcall GIFRegHandlerFRAME_1(u32* data) +{ + FUNCLOG + frameWrite(0, data); +} + +void __fastcall GIFRegHandlerFRAME_2(u32* data) +{ + FUNCLOG + frameWrite(1, data); +} + +void __fastcall GIFRegHandlerZBUF_1(u32* data) +{ + FUNCLOG + zbufInfo& zbuf = ZeroGS::vb[0].zbuf; + + int psm = (0x30|((data[0] >> 24) & 0xf)); + if( zbuf.zbp == (data[0] & 0x1ff) * 32 && + zbuf.psm == psm && + zbuf.zmsk == (data[1] & 0x1) ) { + return; + } + + // error detection + if( m_Blocks[psm].bpp == 0 ) + return; + + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + zbuf.zbp = (data[0] & 0x1ff) * 32; + zbuf.psm = 0x30|((data[0] >> 24) & 0xf); + zbuf.zmsk = data[1] & 0x1; + + ZeroGS::vb[0].zprimmask = 0xffffffff; + if( zbuf.psm > 0x31 ) ZeroGS::vb[0].zprimmask = 0xffff; + + ZeroGS::vb[0].bNeedZCheck = 1; +} + +void __fastcall GIFRegHandlerZBUF_2(u32* data) +{ + FUNCLOG + zbufInfo& zbuf = ZeroGS::vb[1].zbuf; + + int psm = (0x30|((data[0] >> 24) & 0xf)); + if( zbuf.zbp == (data[0] & 0x1ff) * 32 && + zbuf.psm == psm && + zbuf.zmsk == (data[1] & 0x1) ) { + return; + } + + // error detection + if( m_Blocks[psm].bpp == 0 ) + return; + + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + zbuf.zbp = (data[0] & 0x1ff) * 32; + zbuf.psm = 0x30|((data[0] >> 24) & 0xf); + zbuf.zmsk = data[1] & 0x1; + + ZeroGS::vb[1].bNeedZCheck = 1; + + ZeroGS::vb[1].zprimmask = 0xffffffff; + if( zbuf.psm > 0x31 ) ZeroGS::vb[1].zprimmask = 0xffff; +} + +void __fastcall GIFRegHandlerBITBLTBUF(u32* data) +{ + FUNCLOG + gs.srcbufnew.bp = ((data[0] ) & 0x3fff);// * 64; + gs.srcbufnew.bw = ((data[0] >> 16) & 0x3f) * 64; + gs.srcbufnew.psm = (data[0] >> 24) & 0x3f; + gs.dstbufnew.bp = ((data[1] ) & 0x3fff);// * 64; + gs.dstbufnew.bw = ((data[1] >> 16) & 0x3f) * 64; + gs.dstbufnew.psm = (data[1] >> 24) & 0x3f; + + if (gs.dstbufnew.bw == 0) gs.dstbufnew.bw = 64; +} + +void __fastcall GIFRegHandlerTRXPOS(u32* data) +{ + FUNCLOG + gs.trxposnew.sx = (data[0] ) & 0x7ff; + gs.trxposnew.sy = (data[0] >> 16) & 0x7ff; + gs.trxposnew.dx = (data[1] ) & 0x7ff; + gs.trxposnew.dy = (data[1] >> 16) & 0x7ff; + gs.trxposnew.dir = (data[1] >> 27) & 0x3; +} + +void __fastcall GIFRegHandlerTRXREG(u32* data) +{ + FUNCLOG + gs.imageWtemp = data[0]&0xfff; + gs.imageHtemp = data[1]&0xfff; +} + +void __fastcall GIFRegHandlerTRXDIR(u32* data) +{ + FUNCLOG + // terminate any previous transfers + switch( gs.imageTransfer ) { + case 0: // host->loc + gs.imageTransfer = -1; + break; + case 1: // loc->host + ZeroGS::TerminateLocalHost(); + break; + } + + gs.srcbuf = gs.srcbufnew; + gs.dstbuf = gs.dstbufnew; + gs.trxpos = gs.trxposnew; + gs.imageTransfer = data[0] & 0x3; + gs.imageWnew = gs.imageWtemp; + gs.imageHnew = gs.imageHtemp; + + if( gs.imageWnew > 0 && gs.imageHnew > 0 ) { + switch(gs.imageTransfer) { + case 0: // host->loc + ZeroGS::InitTransferHostLocal(); + break; + + case 1: // loc->host + + ZeroGS::InitTransferLocalHost(); + break; + case 2: + + ZeroGS::TransferLocalLocal(); + break; + + case 3: + gs.imageTransfer = -1; + break; + + default: assert(0); + } + } + else { +#ifndef RELEASE_TO_PUBLIC + WARN_LOG("ZeroGS: dummy transfer\n"); +#endif + gs.imageTransfer = -1; + } +} + +static u32 oldhw[4]; +void __fastcall GIFRegHandlerHWREG(u32* data) +{ + FUNCLOG + if( gs.imageTransfer == 0 ) { + ZeroGS::TransferHostLocal(data, 2); + } + else { +#ifndef RELEASE_TO_PUBLIC + ERROR_LOG("ZeroGS: HWREG!? %8.8x_%8.8x\n", data[0], data[1]); + //assert(0); +#endif + } +} + +extern int g_GSMultiThreaded; + +void __fastcall GIFRegHandlerSIGNAL(u32* data) +{ + FUNCLOG + if(!g_GSMultiThreaded) { + SIGLBLID->SIGID = (SIGLBLID->SIGID&~data[1])|(data[0]&data[1]); + +// if (gs.CSRw & 0x1) CSR->SIGNAL = 1; +// if (!IMR->SIGMSK && GSirq) +// GSirq(); + + if (gs.CSRw & 0x1) { + CSR->SIGNAL = 1; + //gs.CSRw &= ~1; + } + if (!IMR->SIGMSK && GSirq) + GSirq(); + } +} + +void __fastcall GIFRegHandlerFINISH(u32* data) +{ + FUNCLOG + if(!g_GSMultiThreaded) { + + if (gs.CSRw & 0x2) + CSR->FINISH = 1; + if (!IMR->FINISHMSK && GSirq) + GSirq(); + +// if( gs.CSRw & 2 ) { +// //gs.CSRw &= ~2; +// //CSR->FINISH = 0; +// +// +// } +// CSR->FINISH = 1; +// +// if( !IMR->FINISHMSK && GSirq ) +// GSirq(); + } +} + +void __fastcall GIFRegHandlerLABEL(u32* data) +{ + FUNCLOG + if(!g_GSMultiThreaded) { + SIGLBLID->LBLID = (SIGLBLID->LBLID&~data[1])|(data[0]&data[1]); + } +} diff --git a/plugins/zzogl-pg/opengl/Regs.h b/plugins/zzogl-pg/opengl/Regs.h new file mode 100644 index 0000000000..40a4b4b065 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Regs.h @@ -0,0 +1,101 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GSREGS_H__ +#define __GSREGS_H__ + +#ifdef _MSC_VER +typedef void (__fastcall *GIFRegHandler)(u32* data); +#else + +#ifdef __x86_64__ +typedef void (*GIFRegHandler)(u32* data); +#else +typedef void (__fastcall *GIFRegHandler)(u32* data); +#endif + +#endif + +void __fastcall GIFPackedRegHandlerNull(u32* data); +void __fastcall GIFPackedRegHandlerRGBA(u32* data); +void __fastcall GIFPackedRegHandlerSTQ(u32* data); +void __fastcall GIFPackedRegHandlerUV(u32* data); +void __fastcall GIFPackedRegHandlerXYZF2(u32* data); +void __fastcall GIFPackedRegHandlerXYZ2(u32* data); +void __fastcall GIFPackedRegHandlerFOG(u32* data); +void __fastcall GIFPackedRegHandlerA_D(u32* data); +void __fastcall GIFPackedRegHandlerNOP(u32* data); + +void __fastcall GIFRegHandlerNull(u32* data); +void __fastcall GIFRegHandlerPRIM(u32* data); +void __fastcall GIFRegHandlerRGBAQ(u32* data); +void __fastcall GIFRegHandlerST(u32* data); +void __fastcall GIFRegHandlerUV(u32* data); +void __fastcall GIFRegHandlerXYZF2(u32* data); +void __fastcall GIFRegHandlerXYZ2(u32* data); +void __fastcall GIFRegHandlerTEX0_1(u32* data); +void __fastcall GIFRegHandlerTEX0_2(u32* data); +void __fastcall GIFRegHandlerCLAMP_1(u32* data); +void __fastcall GIFRegHandlerCLAMP_2(u32* data); +void __fastcall GIFRegHandlerFOG(u32* data); +void __fastcall GIFRegHandlerXYZF3(u32* data); +void __fastcall GIFRegHandlerXYZ3(u32* data); +void __fastcall GIFRegHandlerNOP(u32* data); +void __fastcall GIFRegHandlerTEX1_1(u32* data); +void __fastcall GIFRegHandlerTEX1_2(u32* data); +void __fastcall GIFRegHandlerTEX2_1(u32* data); +void __fastcall GIFRegHandlerTEX2_2(u32* data); +void __fastcall GIFRegHandlerXYOFFSET_1(u32* data); +void __fastcall GIFRegHandlerXYOFFSET_2(u32* data); +void __fastcall GIFRegHandlerPRMODECONT(u32* data); +void __fastcall GIFRegHandlerPRMODE(u32* data); +void __fastcall GIFRegHandlerTEXCLUT(u32* data); +void __fastcall GIFRegHandlerSCANMSK(u32* data); +void __fastcall GIFRegHandlerMIPTBP1_1(u32* data); +void __fastcall GIFRegHandlerMIPTBP1_2(u32* data); +void __fastcall GIFRegHandlerMIPTBP2_1(u32* data); +void __fastcall GIFRegHandlerMIPTBP2_2(u32* data); +void __fastcall GIFRegHandlerTEXA(u32* data); +void __fastcall GIFRegHandlerFOGCOL(u32* data); +void __fastcall GIFRegHandlerTEXFLUSH(u32* data); +void __fastcall GIFRegHandlerSCISSOR_1(u32* data); +void __fastcall GIFRegHandlerSCISSOR_2(u32* data); +void __fastcall GIFRegHandlerALPHA_1(u32* data); +void __fastcall GIFRegHandlerALPHA_2(u32* data); +void __fastcall GIFRegHandlerDIMX(u32* data); +void __fastcall GIFRegHandlerDTHE(u32* data); +void __fastcall GIFRegHandlerCOLCLAMP(u32* data); +void __fastcall GIFRegHandlerTEST_1(u32* data); +void __fastcall GIFRegHandlerTEST_2(u32* data); +void __fastcall GIFRegHandlerPABE(u32* data); +void __fastcall GIFRegHandlerFBA_1(u32* data); +void __fastcall GIFRegHandlerFBA_2(u32* data); +void __fastcall GIFRegHandlerFRAME_1(u32* data); +void __fastcall GIFRegHandlerFRAME_2(u32* data); +void __fastcall GIFRegHandlerZBUF_1(u32* data); +void __fastcall GIFRegHandlerZBUF_2(u32* data); +void __fastcall GIFRegHandlerBITBLTBUF(u32* data); +void __fastcall GIFRegHandlerTRXPOS(u32* data); +void __fastcall GIFRegHandlerTRXREG(u32* data); +void __fastcall GIFRegHandlerTRXDIR(u32* data); +void __fastcall GIFRegHandlerHWREG(u32* data); +void __fastcall GIFRegHandlerSIGNAL(u32* data); +void __fastcall GIFRegHandlerFINISH(u32* data); +void __fastcall GIFRegHandlerLABEL(u32* data); + +#endif diff --git a/plugins/zzogl-pg/opengl/Win32/Conf.cpp b/plugins/zzogl-pg/opengl/Win32/Conf.cpp new file mode 100644 index 0000000000..298ff9535d --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/Conf.cpp @@ -0,0 +1,89 @@ +#include + +#include "GS.h" +#include "Win32.h" + +extern HINSTANCE hInst; + + +void SaveConfig() { + + char szValue[256]; + const std::string iniFile( s_strIniPath + "zerogs.ini" ); + + sprintf(szValue,"%u",conf.interlace); + WritePrivateProfileString("Settings", "Interlace",szValue,iniFile.c_str()); + sprintf(szValue,"%u",conf.aa); + WritePrivateProfileString("Settings", "Antialiasing",szValue,iniFile.c_str()); + sprintf(szValue,"%u",conf.bilinear); + WritePrivateProfileString("Settings", "Bilinear",szValue,iniFile.c_str()); + sprintf(szValue,"%u",conf.options); + WritePrivateProfileString("Settings", "Options",szValue,iniFile.c_str()); + sprintf(szValue,"%u",conf.gamesettings); + WritePrivateProfileString("Settings", "AdvancedOptions",szValue,iniFile.c_str()); +} + +void LoadConfig() { + char szValue[256]; + const std::string iniFile( s_strIniPath + "zerogs.ini" ); + + memset(&conf, 0, sizeof(conf)); + conf.interlace = 0; // on, mode 1 + conf.mrtdepth = 1; + conf.options = 0; + conf.bilinear = 1; + conf.width = 640; + conf.height = 480; + + FILE *fp=fopen(iniFile.c_str(),"rt"); + if (!fp) + { + CreateDirectory(s_strIniPath.c_str(),NULL); + SaveConfig();//save and return + return ; + } + fclose(fp); + + GetPrivateProfileString("Settings", "Interlace", NULL, szValue, 20, iniFile.c_str()); + conf.interlace = (u8)strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Antialiasing", NULL, szValue, 20, iniFile.c_str()); + conf.aa = (u8)strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Options", NULL, szValue, 20, iniFile.c_str()); + conf.options = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "AdvancedOptions", NULL, szValue, 20, iniFile.c_str()); + conf.gamesettings = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Bilinear", NULL, szValue, 20, iniFile.c_str()); + conf.bilinear = strtoul(szValue, NULL, 10); + + if( conf.aa < 0 || conf.aa > 4 ) conf.aa = 0; + + conf.isWideScreen = conf.options & GSOPTION_WIDESCREEN; + switch(conf.options & GSOPTION_WINDIMS) + { + case GSOPTION_WIN640: + conf.width = 640; + conf.height = conf.isWideScreen ? 360 : 480; + break; + case GSOPTION_WIN800: + conf.width = 800; + conf.height = conf.isWideScreen ? 450 : 600; + break; + case GSOPTION_WIN1024: + conf.width = 1024; + conf.height = conf.isWideScreen ? 576 : 768; + break; + case GSOPTION_WIN1280: + conf.width = 1280; + conf.height = conf.isWideScreen ? 720 : 960; + break; + } + + // turn off all hacks by defaultof + conf.options &= ~(GSOPTION_WIREFRAME|GSOPTION_CAPTUREAVI); + conf.options |= GSOPTION_LOADED; + + if( conf.width <= 0 || conf.height <= 0 ) { + conf.width = 640; + conf.height = 480; + } +} diff --git a/plugins/zzogl-pg/opengl/Win32/Win32.cpp b/plugins/zzogl-pg/opengl/Win32/Win32.cpp new file mode 100644 index 0000000000..2e5177c5d9 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/Win32.cpp @@ -0,0 +1,251 @@ +#include +#include +#include + +#include "resrc1.h" + +#include "GS.h" +#include "Win32.h" + +#include +using namespace std; + +extern int g_nPixelShaderVer; +static int prevbilinearfilter; +HINSTANCE hInst=NULL; + +void CALLBACK GSkeyEvent(keyEvent *ev) { +// switch (ev->event) { +// case KEYPRESS: +// switch (ev->key) { +// case VK_PRIOR: +// if (conf.fps) fpspos++; break; +// case VK_NEXT: +// if (conf.fps) fpspos--; break; +// case VK_END: +// if (conf.fps) fpspress = 1; break; +// case VK_DELETE: +// conf.fps = 1 - conf.fps; +// break; +// } +// break; +// } +} + +#include "Win32/resource.h" + +BOOL CALLBACK LoggingDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + if (conf.log) CheckDlgButton(hW, IDC_LOG, TRUE); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, FALSE); + return TRUE; + case IDOK: + if (IsDlgButtonChecked(hW, IDC_LOG)) + conf.log = 1; + else conf.log = 0; + + SaveConfig(); + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +map mapConfOpts; +#define PUT_CONF(id) mapConfOpts[IDC_CONFOPT_##id] = 0x##id; + +void OnInitDialog(HWND hW) +{ + if( !(conf.options & GSOPTION_LOADED) ) + LoadConfig(); + + CheckDlgButton(hW, IDC_CONFIG_INTERLACE, conf.interlace); + CheckDlgButton(hW, IDC_CONFIG_BILINEAR, conf.bilinear); + CheckDlgButton(hW, IDC_CONFIG_DEPTHWRITE, conf.mrtdepth); + CheckRadioButton(hW,IDC_CONFIG_AANONE,IDC_CONFIG_AA4, IDC_CONFIG_AANONE+conf.aa); + CheckDlgButton(hW, IDC_CONFIG_WIREFRAME, (conf.options&GSOPTION_WIREFRAME)?1:0); + CheckDlgButton(hW, IDC_CONFIG_CAPTUREAVI, (conf.options&GSOPTION_CAPTUREAVI)?1:0); + //CheckDlgButton(hW, IDC_CONFIG_CACHEFBP, (conf.options&GSOPTION_ALPHACLAMP)?1:0); + CheckDlgButton(hW, IDC_CONFIG_FULLSCREEN, (conf.options&GSOPTION_FULLSCREEN)?1:0); + CheckDlgButton(hW, IDC_CONFIG_WIDESCREEN, (conf.options&GSOPTION_WIDESCREEN)?1:0); + //CheckDlgButton(hW, IDC_CONFIG_FFX, (conf.options&GSOPTION_FFXHACK)?1:0); + CheckDlgButton(hW, IDC_CONFIG_BMPSS, (conf.options&GSOPTION_TGASNAP)?1:0); + CheckRadioButton(hW,IDC_CONF_WIN640, IDC_CONF_WIN1280, IDC_CONF_WIN640+((conf.options&GSOPTION_WINDIMS)>>4)); + + prevbilinearfilter = conf.bilinear; + + mapConfOpts.clear(); + PUT_CONF(00000001); + PUT_CONF(00000002); + PUT_CONF(00000004); + PUT_CONF(00000008); + PUT_CONF(00000010); + PUT_CONF(00000020); + PUT_CONF(00000040); + PUT_CONF(00000080); + PUT_CONF(00000100); + PUT_CONF(00000200); + PUT_CONF(00000400); + PUT_CONF(00000800); + PUT_CONF(00001000); + PUT_CONF(00002000); + PUT_CONF(00004000); + PUT_CONF(00008000); + PUT_CONF(00010000); + PUT_CONF(00020000); + PUT_CONF(00040000); + PUT_CONF(00080000); + PUT_CONF(00100000); + PUT_CONF(00200000); + PUT_CONF(00800000); + PUT_CONF(01000000); + PUT_CONF(02000000); + PUT_CONF(04000000); + PUT_CONF(10000000); + + for(map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) { + CheckDlgButton(hW, it->first, (conf.gamesettings&it->second)?1:0); + } +} + +void OnOK(HWND hW) { + + u32 newinterlace = IsDlgButtonChecked(hW, IDC_CONFIG_INTERLACE); + + if( !conf.interlace ) conf.interlace = newinterlace; + else if( !newinterlace ) conf.interlace = 2; // off + + conf.bilinear = IsDlgButtonChecked(hW, IDC_CONFIG_BILINEAR); + // restore + if( conf.bilinear && prevbilinearfilter ) + conf.bilinear = prevbilinearfilter; + + //conf.mrtdepth = 1;//IsDlgButtonChecked(hW, IDC_CONFIG_DEPTHWRITE); + + if( SendDlgItemMessage(hW,IDC_CONFIG_AANONE,BM_GETCHECK,0,0) ) { + conf.aa = 0; + } + else if( SendDlgItemMessage(hW,IDC_CONFIG_AA2,BM_GETCHECK,0,0) ) { + conf.aa = 1; + } + else if( SendDlgItemMessage(hW,IDC_CONFIG_AA4,BM_GETCHECK,0,0) ) { + conf.aa = 2; + } + else if( SendDlgItemMessage(hW,IDC_CONFIG_AA8,BM_GETCHECK,0,0) ) { + conf.aa = 3; + } + else if( SendDlgItemMessage(hW,IDC_CONFIG_AA16,BM_GETCHECK,0,0) ) { + conf.aa = 4; + } + else conf.aa = 0; + conf.negaa = 0; + + conf.options = 0; + conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_CAPTUREAVI) ? GSOPTION_CAPTUREAVI : 0; + conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_WIREFRAME) ? GSOPTION_WIREFRAME : 0; + conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_FULLSCREEN) ? GSOPTION_FULLSCREEN : 0; + conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_WIDESCREEN) ? GSOPTION_WIDESCREEN : 0; + //conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_FFX) ? GSOPTION_FFXHACK : 0; + conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_BMPSS) ? GSOPTION_TGASNAP : 0; + + conf.gamesettings = 0; + for(map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) { + if( IsDlgButtonChecked(hW, it->first) ) + conf.gamesettings |= it->second; + } + GSsetGameCRC(g_LastCRC, conf.gamesettings); + + if( SendDlgItemMessage(hW,IDC_CONF_WIN640,BM_GETCHECK,0,0) ) conf.options |= GSOPTION_WIN640; + else if( SendDlgItemMessage(hW,IDC_CONF_WIN800,BM_GETCHECK,0,0) ) conf.options |= GSOPTION_WIN800; + else if( SendDlgItemMessage(hW,IDC_CONF_WIN1024,BM_GETCHECK,0,0) ) conf.options |= GSOPTION_WIN1024; + else if( SendDlgItemMessage(hW,IDC_CONF_WIN1280,BM_GETCHECK,0,0) ) conf.options |= GSOPTION_WIN1280; + + SaveConfig(); + EndDialog(hW, FALSE); +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + OnInitDialog(hW); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, TRUE); + return TRUE; + case IDOK: + OnOK(hW); + return TRUE; + } + } + return FALSE; +} + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + + //ZeroGS uses floating point render targets because A8R8G8B8 format is not sufficient for ps2 blending and this requires alpha blending on floating point render targets + //There might be a problem with pixel shader precision with older geforce models (textures will look blocky). + + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +s32 CALLBACK GStest() { + return 0; +} + +void CALLBACK GSabout() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc); +} + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + +static char *err = "Error Loading Symbol"; +static int errval; + +void *SysLoadLibrary(char *lib) { + return LoadLibrary(lib); +} + +void *SysLoadSym(void *lib, char *sym) { + void *tmp = GetProcAddress((HINSTANCE)lib, sym); + if (tmp == NULL) errval = 1; + else errval = 0; + return tmp; +} + +char *SysLibError() { + if (errval) { errval = 0; return err; } + return NULL; +} + +void SysCloseLibrary(void *lib) { + FreeLibrary((HINSTANCE)lib); +} diff --git a/plugins/zzogl-pg/opengl/Win32/Win32.h b/plugins/zzogl-pg/opengl/Win32/Win32.h new file mode 100644 index 0000000000..acea999c8b --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/Win32.h @@ -0,0 +1,9 @@ +#ifndef __WIN32_H__ +#define __WIN32_H__ + +#include "resrc1.h" +#include "Win32/resource.h" + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif /* __WIN32_H__ */ diff --git a/plugins/zzogl-pg/opengl/Win32/aviUtil.h b/plugins/zzogl-pg/opengl/Win32/aviUtil.h new file mode 100644 index 0000000000..e4aea12340 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/aviUtil.h @@ -0,0 +1,488 @@ +#ifndef __AVIUTIL_H__ +#define __AVIUTIL_H__ + +#define AVIIF_KEYFRAME 0x00000010L // this frame is a key frame. + +#include +using namespace std; + +#include +#include +#include + +BOOL AVI_Init() +{ + /* first let's make sure we are running on 1.1 */ + WORD wVer = HIWORD(VideoForWindowsVersion()); + if (wVer < 0x010a){ + /* oops, we are too old, blow out of here */ + //MessageBeep(MB_ICONHAND); + MessageBox(NULL, "Cant't init AVI File - Video for Windows version is to old", "Error", MB_OK|MB_ICONSTOP); + return FALSE; + } + + AVIFileInit(); + + return TRUE; +} + +BOOL AVI_FileOpenWrite(PAVIFILE * pfile, const char *filename) +{ + HRESULT hr = AVIFileOpen(pfile, // returned file pointer + filename, // file name + OF_WRITE | OF_CREATE, // mode to open file with + NULL); // use handler determined + // from file extension.... + if (hr != AVIERR_OK) + return FALSE; + + return TRUE; +} + +DWORD getFOURCC(const char* value) +{ + if(_stricmp(value, "DIB") == 0) + { + return mmioFOURCC(value[0],value[1],value[2],' '); + } + else if((_stricmp(value, "CVID") == 0) + || (_stricmp(value, "IV32") == 0) + || (_stricmp(value, "MSVC") == 0) + || (_stricmp(value, "IV50") == 0)) + { + return mmioFOURCC(value[0],value[1],value[2],value[3]); + } + else + { + return NULL; + } +} + +// Fill in the header for the video stream.... +// The video stream will run in rate ths of a second.... +BOOL AVI_CreateStream(PAVIFILE pfile, PAVISTREAM * ps, int rate, // sample/second + unsigned long buffersize, int rectwidth, int rectheight, + const char* _compressor) +{ + AVISTREAMINFO strhdr; + memset(&strhdr, 0, sizeof(strhdr)); + strhdr.fccType = streamtypeVIDEO;// stream type + strhdr.fccHandler = getFOURCC(_compressor); + //strhdr.fccHandler = 0; // no compression! + //strhdr.fccHandler = mmioFOURCC('D','I','B',' '); // Uncompressed + //strhdr.fccHandler = mmioFOURCC('C','V','I','D'); // Cinpak + //strhdr.fccHandler = mmioFOURCC('I','V','3','2'); // Intel video 3.2 + //strhdr.fccHandler = mmioFOURCC('M','S','V','C'); // Microsoft video 1 + //strhdr.fccHandler = mmioFOURCC('I','V','5','0'); // Intel video 5.0 + //strhdr.dwFlags = AVISTREAMINFO_DISABLED; + //strhdr.dwCaps = + //strhdr.wPriority = + //strhdr.wLanguage = + strhdr.dwScale = 1; + strhdr.dwRate = rate; // rate fps + //strhdr.dwStart = + //strhdr.dwLength = + //strhdr.dwInitialFrames = + strhdr.dwSuggestedBufferSize = buffersize; + strhdr.dwQuality = -1; // use the default + //strhdr.dwSampleSize = + SetRect(&strhdr.rcFrame, 0, 0, // rectangle for stream + (int) rectwidth, + (int) rectheight); + //strhdr.dwEditCount = + //strhdr.dwFormatChangeCount = + //strcpy(strhdr.szName, "Full Frames (Uncompressed)"); + + // And create the stream; + HRESULT hr = AVIFileCreateStream(pfile, // file pointer + ps, // returned stream pointer + &strhdr); // stream header + if (hr != AVIERR_OK) { + return FALSE; + } + + return TRUE; +} + +string getFOURCCVAsString(DWORD value) +{ + string returnValue = ""; + if( value == 0 ) + return returnValue; + + DWORD ch0 = value & 0x000000FF; + returnValue.push_back((char) ch0); + DWORD ch1 = (value & 0x0000FF00)>>8; + returnValue.push_back((char) ch1); + DWORD ch2 = (value & 0x00FF0000)>>16; + returnValue.push_back((char) ch2); + DWORD ch3 = (value & 0xFF000000)>>24; + returnValue.push_back((char) ch3); + + return returnValue; +} + +string dumpAVICOMPRESSOPTIONS(AVICOMPRESSOPTIONS opts) +{ + char tmp[255]; + string returnValue = "Dump of AVICOMPRESSOPTIONS\n"; + + returnValue += "DWORD fccType = streamtype("; returnValue += getFOURCCVAsString(opts.fccType); returnValue += ")\n"; + returnValue += "DWORD fccHandler = "; returnValue += getFOURCCVAsString(opts.fccHandler); returnValue += "\n"; + + _snprintf(tmp, 255, "DWORD dwKeyFrameEvery = %d\n", opts.dwKeyFrameEvery); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD dwQuality = %d\n", opts.dwQuality); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD dwBytesPerSecond = %d\n", opts.dwBytesPerSecond); + returnValue += tmp; + + if((opts.dwFlags & AVICOMPRESSF_DATARATE) == AVICOMPRESSF_DATARATE){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_DATARATE\n");} + else if((opts.dwFlags & AVICOMPRESSF_INTERLEAVE) == AVICOMPRESSF_INTERLEAVE){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_INTERLEAVE\n");} + else if((opts.dwFlags & AVICOMPRESSF_KEYFRAMES) == AVICOMPRESSF_KEYFRAMES){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_KEYFRAMES\n");} + else if((opts.dwFlags & AVICOMPRESSF_VALID) == AVICOMPRESSF_VALID){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_VALID\n");} + else {_snprintf(tmp, 255, "DWORD dwFlags = Unknown(%d)\n", opts.dwFlags);} + returnValue += tmp; + + _snprintf(tmp, 255, "LPVOID lpFormat = %d\n", (int)opts.lpFormat); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD cbFormat = %d\n", opts.cbFormat); + returnValue += tmp; + + _snprintf(tmp, 255, "LPVOID lpParms = %d\n", (int)opts.lpParms); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD cbParms = %d\n", opts.cbParms); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD dwInterleaveEvery = %d\n", opts.dwInterleaveEvery); + returnValue += tmp; + + return returnValue; +} + +BOOL AVI_SetOptions(PAVISTREAM * ps, PAVISTREAM * psCompressed, LPBITMAPINFOHEADER lpbi, + const char* _compressor) +{ + + AVICOMPRESSOPTIONS opts; + AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts}; + + memset(&opts, 0, sizeof(opts)); + opts.fccType = streamtypeVIDEO; + opts.fccHandler = getFOURCC(_compressor); + //opts.fccHandler = 0; + //opts.fccHandler = mmioFOURCC('D','I','B',' '); // Uncompressed + //opts.fccHandler = mmioFOURCC('C','V','I','D'); // Cinpak + //opts.fccHandler = mmioFOURCC('I','V','3','2'); // Intel video 3.2 + //opts.fccHandler = mmioFOURCC('M','S','V','C'); // Microsoft video 1 + //opts.fccHandler = mmioFOURCC('I','V','5','0'); // Intel video 5.0 + //opts.dwKeyFrameEvery = 5; + //opts.dwQuality + //opts.dwBytesPerSecond + //opts.dwFlags = AVICOMPRESSF_KEYFRAMES; + //opts.lpFormat + //opts.cbFormat + //opts.lpParms + //opts.cbParms + //opts.dwInterleaveEvery + + /* display the compression options dialog box if specified compressor is unknown */ + if(getFOURCC(_compressor) == NULL) + { + if (!AVISaveOptions(NULL, 0, 1, ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts)) + { + return FALSE; + } + + //printf("%s", dumpAVICOMPRESSOPTIONS(opts)); + //MessageBox(NULL, dumpAVICOMPRESSOPTIONS(opts).c_str(), "AVICOMPRESSOPTIONS", MB_OK); + } + + HRESULT hr = AVIMakeCompressedStream(psCompressed, *ps, &opts, NULL); + if (hr != AVIERR_OK) { + return FALSE; + } + + hr = AVIStreamSetFormat(*psCompressed, 0, + lpbi, // stream format + lpbi->biSize // format size + + lpbi->biClrUsed * sizeof(RGBQUAD) + ); + if (hr != AVIERR_OK) { + return FALSE; + } + + return TRUE; +} + +BOOL AVI_SetText(PAVIFILE pfile, PAVISTREAM psText, char *szText, int width, int height, int TextHeight) +{ + // Fill in the stream header for the text stream.... + AVISTREAMINFO strhdr; + DWORD dwTextFormat; + // The text stream is in 60ths of a second.... + + memset(&strhdr, 0, sizeof(strhdr)); + strhdr.fccType = streamtypeTEXT; + strhdr.fccHandler = mmioFOURCC('D', 'R', 'A', 'W'); + strhdr.dwScale = 1; + strhdr.dwRate = 60; + strhdr.dwSuggestedBufferSize = sizeof(szText); + SetRect(&strhdr.rcFrame, 0, (int) height, + (int) width, (int) height + TextHeight); // #define TEXT_HEIGHT 20 + + // ....and create the stream. + HRESULT hr = AVIFileCreateStream(pfile, &psText, &strhdr); + if (hr != AVIERR_OK) { + return FALSE; + } + + dwTextFormat = sizeof(dwTextFormat); + hr = AVIStreamSetFormat(psText, 0, &dwTextFormat, sizeof(dwTextFormat)); + if (hr != AVIERR_OK) { + return FALSE; + } + + return TRUE; +} + +BOOL AVI_AddFrame(PAVISTREAM psCompressed, int time, LPBITMAPINFOHEADER lpbi) +{ + int ImageSize = lpbi->biSizeImage; + if (ImageSize == 0) + { + if (lpbi->biBitCount == 24) + { + ImageSize = lpbi->biWidth * lpbi->biHeight * 3; + } + } + HRESULT hr = AVIStreamWrite(psCompressed, // stream pointer + time, // time of this frame + 1, // number to write + (LPBYTE) lpbi + // pointer to data + lpbi->biSize + + lpbi->biClrUsed * sizeof(RGBQUAD), + ImageSize, // lpbi->biSizeImage, // size of this frame + AVIIF_KEYFRAME, // flags.... + NULL, + NULL); + if (hr != AVIERR_OK) + { + char strMsg[255]; + _snprintf(strMsg, 255, "Error: AVIStreamWrite, error %d",hr); + MessageBox(NULL, strMsg, "", MB_OK); + return FALSE; + } + + return TRUE; +} + +BOOL AVI_AddText(PAVISTREAM psText, int time, char *szText) +{ + int iLen = (int)strlen(szText); + + HRESULT hr = AVIStreamWrite(psText, + time, + 1, + szText, + iLen + 1, + AVIIF_KEYFRAME, + NULL, + NULL); + if (hr != AVIERR_OK) + return FALSE; + + return TRUE; +} + +BOOL AVI_CloseStream(PAVISTREAM ps, PAVISTREAM psCompressed, PAVISTREAM psText) +{ + if (ps) + AVIStreamClose(ps); + + if (psCompressed) + AVIStreamClose(psCompressed); + + if (psText) + AVIStreamClose(psText); + + + + return TRUE; +} + +BOOL AVI_CloseFile(PAVIFILE pfile) +{ + if (pfile) + AVIFileClose(pfile); + + return TRUE; +} + +BOOL AVI_Exit() +{ + AVIFileExit(); + + return TRUE; +} + + + + + + + + + + + + + + + + +/* Here are the additional functions we need! */ + + +static PAVIFILE pfile = NULL; +static PAVISTREAM ps = NULL; +static PAVISTREAM psCompressed = NULL; +static int count = 0; + + +// Initialization... +bool START_AVI(const char* file_name) +{ + if(! AVI_Init()) + { + //printf("Error - AVI_Init()\n"); + return false; + } + + if(! AVI_FileOpenWrite(&pfile, file_name)) + { + //printf("Error - AVI_FileOpenWrite()\n"); + return false; + } + + return true; +} + +bool ADD_FRAME_FROM_DIB_TO_AVI(const char* _compressor, int _frameRate, int width, int height, int bits, void* pdata) +{ + if(count == 0) + { + if(! AVI_CreateStream(pfile, &ps, _frameRate, + width*height/bits, + width, + height, _compressor)) + { + //printf("Error - AVI_CreateStream()\n"); + return false; + } + + BITMAPINFOHEADER bi; + memset(&bi, 0, sizeof(bi)); + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = width; + bi.biHeight = height; + bi.biPlanes = 1; + bi.biBitCount = bits; + bi.biCompression = BI_RGB; + bi.biSizeImage = width * height * bits /8; + if(! AVI_SetOptions(&ps, &psCompressed, &bi, _compressor)) + { + return false; + } + } + + HRESULT hr = AVIStreamWrite(psCompressed, // stream pointer + count, // time of this frame + 1, // number to write + pdata, + width*height/8, // lpbi->biSizeImage, // size of this frame + AVIIF_KEYFRAME, // flags.... + NULL, + NULL); + if (hr != AVIERR_OK) + { + char strMsg[255]; + _snprintf(strMsg, 255, "Error: AVIStreamWrite, error %d",hr); + MessageBox(NULL, strMsg, "", MB_OK); + return FALSE; + } + + count++; + return true; +} + +//Now we can add frames +// ie. ADD_FRAME_FROM_DIB_TO_AVI(yourDIB, "CVID", 25); +bool ADD_FRAME_FROM_DIB_TO_AVI(HANDLE dib, const char* _compressor, int _frameRate) +{ + LPBITMAPINFOHEADER lpbi; + if(count == 0) + { + lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib); + if(! AVI_CreateStream(pfile, &ps, _frameRate, + (unsigned long) lpbi->biSizeImage, + (int) lpbi->biWidth, + (int) lpbi->biHeight, _compressor)) + { + //printf("Error - AVI_CreateStream()\n"); + GlobalUnlock(lpbi); + return false; + } + + if(! AVI_SetOptions(&ps, &psCompressed, lpbi, _compressor)) + { + //printf("Error - AVI_SetOptions()\n"); + GlobalUnlock(lpbi); + return false; + } + + GlobalUnlock(lpbi); + } + + lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib); + if(! AVI_AddFrame(psCompressed, count * 1, lpbi)) + { + //printf("Error - AVI_AddFrame()\n"); + GlobalUnlock(lpbi); + return false; + } + + GlobalUnlock(lpbi); + count++; + return true; +} + +// The end... +bool STOP_AVI() +{ + if(! AVI_CloseStream(ps, psCompressed, NULL)) + { + //printf("Error - AVI_CloseStream()\n"); + return false; + } + + if(! AVI_CloseFile(pfile)) + { + //printf("Error - AVI_CloseFile()\n"); + return false; + } + + if(! AVI_Exit()) + { + //printf("Error - AVI_Exit()\n"); + return false; + } + + return true; +} + +#endif diff --git a/plugins/zzogl-pg/opengl/Win32/jconfig.h b/plugins/zzogl-pg/opengl/Win32/jconfig.h new file mode 100644 index 0000000000..cf6420d500 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/jconfig.h @@ -0,0 +1,52 @@ +/* jconfig.mc6 --- jconfig.h for Microsoft C on MS-DOS, version 6.00A & up. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +//#define NEED_FAR_POINTERS /* for small or medium memory model */ +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +//#define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ + +#define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ + +//#define USE_FMEM /* Microsoft has _fmemcpy() and _fmemset() */ + +#define NEED_FHEAPMIN /* far heap management routines are broken */ + +#define SHORTxLCONST_32 /* enable compiler-specific DCT optimization */ +/* Note: the above define is known to improve the code with Microsoft C 6.00A. + * I do not know whether it is good for later compiler versions. + * Please report any info on this point to jpeg-info@uunet.uu.net. + */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE +#define USE_SETMODE /* Microsoft has setmode() */ +#define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/plugins/zzogl-pg/opengl/Win32/jmorecfg.h b/plugins/zzogl-pg/opengl/Win32/jmorecfg.h new file mode 100644 index 0000000000..54a7d1c447 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/jmorecfg.h @@ -0,0 +1,363 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +typedef long INT32; +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/plugins/zzogl-pg/opengl/Win32/jpeglib.h b/plugins/zzogl-pg/opengl/Win32/jpeglib.h new file mode 100644 index 0000000000..c1d119199a --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/jpeglib.h @@ -0,0 +1,1099 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +#undef FAR +#define FAR + +typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples. Always DCTSIZE for compression. + * For decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values of 1,2,4,8 are likely to be supported. Note that different + * components may receive different IDCT scalings. + */ + int DCT_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, IDCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/plugins/zzogl-pg/opengl/Win32/libjpeg.lib b/plugins/zzogl-pg/opengl/Win32/libjpeg.lib new file mode 100644 index 0000000000000000000000000000000000000000..ae22f9c400f4473bd6e6e5038c4da14713f501f8 GIT binary patch literal 470518 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

H{y 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�*8S-ao#yR+JgG6&&XhH(aQ@%?wIb{vCe6Vovc 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 z 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%0A)B%-q?>`HWKQwJa@+6w$uH2Pp+2IS%z z4K@ZviFfHr#F$Z6B5kUFSG2|Wt!T0VK6XYPS|~+do!o%V{mYhoZidcB1D}SI0oz8G zZ_f_L%Ro?V6n%IIn|oWw=E)%q?5e>RijU1x4XLdQqClV_Tu-m9jc}GYLfAoUItMIk zo@E`J|17+s*T=ytXon{tD0ZM}a%np|rZfWsT&cY@>1IoXb^-n~Th=Q9@{iYEb`Bt6 zZh?&wI0;W*J>>_h`o`n1sS@J|c_Z5k92_>|)m(Wd6Ps&qh+CNtUpE*q+uLfR%|Fw? z>gx=w(ey_Q)mB#l`+~L>NLhRaI1z|;8a)p90&oWKMIgoS_rS}6uK=$F{sFiG_$rY8 zhvQLgnYIib;HPQVXj_I{W6w01W*jW4Eh`&am0CINuUSlFNm@M0mI+!2kJ=;4w425& zTr{jiTV~${?J@a}5&~KwDjVCf3Y$zOC+%KgD^6dx4%ktv&M06zR%uS&iOQbjzqu2Y z6aG$P-#^AC@AsK3joDfQOwuYfp0*>X|wNx%@CeX@ZT(-PKgqm0xC@>gzVgL$98Mw z>)f`f>nvZj;zzY@XTI1jti4aCUYq;2<%`e9(=Jsqhx1%l>rfO*SnOAW6yTC zM7^hx8KxWR-MP1?2dGy0?B2G0q~)ud_9Z-yy67psR0-g-Y*~D{yHqY`!4PYAKam3XJR4ZT4%y{Q8%U84ZB|MI}Wc1`S zTmQkGHoai^YSq4kM`B%}DTcvP;h@)l zlU>{+bsfa8+$0CJi0$DZU0yDBZ@32i`Yurq2jwG)-(3B7g<~H>x&|sbwfVVjx=L&^ zUB!&+O=VI$G2pSTJ$2C)znj}!O?NU27gj9Jm|I;LX{dya+Zec_KKyXCL@xh#w4y$I zL_XHlX}F@^OIFl3L#B(g#CWZ!o2vDi1?@iD(b1D$j5osDe2>~pAy(S#FGD&F#`7tRNy&=3l$ns^A3ODY@EooAm;|pCaK6+|(mdkP?F zs0H5(nwKrhD}9?le+@hjvtNg4FMaQV=VQ&6Dt&C~oW!>quNCGtFmM=ri{@o`Ug_g& zcMW*%)dTeQ(#MtjKWo1B(&xiFBS#PG6MP=^aVU63y7^oyxa=s82hVA4K9BG&0MFHK zK38~@gU2)vtYW;%uNp4vz=ytDOsewx9Ij))Go1ZBOnc>bGI(ZbzC^jW(#PsDSNkPE z{7bcBeT5Dy!S`QTv94+U58OBRJ<6lEUY0&UtypuJtMa%>r4=PVYGFEgSugd)a?ac1 zcwgNs5O?WOYtWC@&#j8oW8IUB#OC_rjD`ki#m$wqCd<9 z{38~Yf8r%%&-G$1wH|L3mRFVS;*v3!PnVeD&|F3YI#&L-`v0Wd+(? zfxatnbnlECiu{>xP5$QmtFQd@mlfzErtR`F=r1eKySRlQafR6~7yZw<0?pyb&$|L$ zI2lv;0Xet?E3~#1S*($5C`#wNOQ^L7M>P8}l^!@Tu~0o1eVzNptHGdgp6?($qtUl& zBOlzhA&AV42Ta!_H0Q?IJD2&?HXrLW;Q|{!B@ta?FERykfHd-#V za~h#(U|r(FD<9ffwT9=^HDP=S=c#y1!#G(LESj(;PC}8hz$OFnF=8AGM0FU)0mlN5 z2bKd*08R%^19D;FBp|Dk9|)?dXv^Rtq^2#`HdR%O+ce}^sOoRzdR884=6S3gAAlI}gGs0X(YWX;T{y6pdVpMt@9;X#%jQidVLD{N7(^{qdiMqDaHi3gA(vrzu+|eh(EI zxfr%-0tIb49>;=ZNAbn?2Gf4P(?@=hoC}8O_ie&|GZ)sOGh;xd+0g+vR0g(uvCE@j0XrA= zC`Zl(OUqXay}$^MF>@aD1#1P18hb|gI;zUY0c<%{w`!zpOz;;0O*e3DMMU4Q4~ zA1q(5(F=?ke%TKRl30Ab;l{l09a%Zo^7T2rz^Ihik3Pu()ymhvzGeGZzA{*JFv8=I zI(Bl(7u{Fiz3vXn7ms_c2dq4O+`)BX#UMT6&y%Tg}OqukqR!+nG}`drDj^H=3(99rl^!%REpC)tNiY?6cf{i+k1L{465lh-lU)J6EJaw8cRr*+dSb}vJuk@V-j_bhJhaO;%49_(`_Ivw*ryF`kn)cE+ z5!Zj5+MG0rSCe>TU>lz<;Tq*-SElTi$hMB_R@DWc*bkKRO#b5q+at# zfcWQ?zAr#O4SX~DDK3WRmA)v_7bOqcE=_ys%LC6a&DUP~CTSiOqE25;?TnUFaw|+) zIV>l*`Th%QevQ!VtNHO-s@GvG+Dotb^;Bzqql3kjlPiK)@-x*}`)G$LW5$#~HL~=C z5`5(=_0_YL`f5d4S>=Q&MWM>#U`0?g{cV_IjB>g)Jm0aps?MjJW zm2s|NQl*zVE3+gT+bWHF{gTUkFPTZBW@-IgEbB0dvvK-{Wb9eX*?nFvmx6wx)z2NT zbh0oWGSjB3g_{zQY>&k`X7nDDySia^Lz5KE+|z5DFg|dp=CZ=>a5A6PQZ+XMto-(F#0u_u&;`gjgFL-BEfmzMXW&|~rjSbjGU=t+9@2MKR6;bhZ$Dzdk z-n#78-%a`B#NO|q4P%vid?~4-W-04og#~rE zb>bp$K-DsS0a-_u&2OG07uP~fD;v7Hk)G7CikD@_$IfpJW(pP8V`4>ODK2I);@8tx zxNRu`SMEX=46fzrI<)5_GZ11E?$uUNi(5E;y`&?)F}S^(N}+a_1TAUe4Y&mj$KQvm zb1z-DXx)nly0t-WX$$GgaOG}X`;EB#!1)4C10J_}FDDgDcbj^z?btM&(H6m(UOTr? znxtU;CE{F($25#DfQJ)p4{G9cyreiKTm|HJSv7C~um;HG3e5IKhXOHYD9fc>ZJUnY zSPc~YE#ynod>etMgMJ$D93bq`>wxosw*%?#Zs1wK$AJrg8-Qm6-vurKegHfV*a2x= z3gi^%eBdC^nZ})2IcFYCqo%r9!pg>vSL?#(7y@r(kPv5NO-8<1vxcqWMjSU`WKUAuPZatid`xMEY5XG;VN#Jzk_lx(L$zJViQ2kq);N z=LU+Yy7(FwfAIss;==lL++Y%rV11GRSKtW=1M>*i;@PX9(VaDNB4>Ycud1|Q<6D-4@nYp6(oguffk`iFr+Vf6nm0U>gup8@&t&sf|7iya%`uNPm>b?s)7Q1lZFl+RNIe7U-B(({Lt5 zEzl_&B@(kWl*m0h8hb`M8$D_=jO<~ZjIdggo93>G9SNMI(mN7jaZa1*YY7S(N(ygvb z6qR?1X(32%F--_01SDaYHVR}{;5C~11O$cYeF``L_%x6Lxe`c$Tm`HGt_D&d-vCk| z*8`(KbdMsC&j2Zq&jML4=$)iXg#J}jzwm5tRqRA|1O4n_{DH&bsIP&@TlvGF&LgajIq zjz_X%YUvX_W2zD9W{&L2(>D~!^{`v^J(B%kq_6e548=Rei*n^{$?Z#gVKQkWVr((z zAmo@?G~*39wQz( zM5QBe3VwG6GB26HrNAuU`M_-8g}@vj-%VYB%ol&N)(h|`8K6z=T~f4V+EvK_(`cHb zVNo)mY?Ohcgl6t9RCSLx(Q_bk+fRSUByw~XDn83qBl!6|+)&R)64f={iJA=TC0=Es}n}%^x;Q9eS(ZmC^z~uqEf(BuW_5uzB?gcy; zmT zU&7WjH>=BpcdeAfv-_Gb*~kF3+Xy){uP{64(A6Zx|C zCH2>F?Pw3wnp-oDuzU^EzBo1GwFiolPs2TimamE07u%xbYY6&nG0cTCU+n$;KE5m1 zUtId@SHDlr7o`H%HrevkD^XwdI<8)ZTMqk(FSC8U+I>~N<%`FV(g=@34&}4gv3Jt) zb&d9=K8@*L_P^62vGWR&!SajC;F43@dVgO~ymouNf>4v^*7U|D4+p((M3OPbca#gn;s5MdBYCKM67&3Iozp;yKNdE8<>SzX@%y595%rNgjb-p6S$?If> zL3~x&jmOCh3n2U_y7&scPG*1vzK%|)qkgThSM=H?GaY<~g69Hu2QcJIwTtW#@T}2% zY}v9q$E6w1cKyEQfmMvxE*`$izXjjFG%u3jnZ5@>Pe-Toq#gt$(r0_`F%pLNA$UI0 ze5t~_4}4#N=O#90m{j3~FeC81=24v9>AM7c+y!+Thr}?6@N9dENoSw65j<~ezEtJM zx5~GghyG~1%8ze^P8eQy*<11OJ?d4zoHV-sG%@Eq>u^9XMWc&gldF8O0QpQCwH%--cU1&(nSpI7<40lrP(dvsqF zT6^`o2|S-@zEt_;+cjf96_)wmtA3fjt}Z^W^t}VVQ@~f0t3qopeW!wFp5|*WeV1yU z_R_Zzj@N>3_5j7@19+uxFdR+?&#n6_zBE88`FjaGZ)v{v(zi|Xs1UvD_ewhA)AUL_ zG-#%t>FbU3-3^{~dBWCi`~4I=-)g>8>0|rtg?`>{q<(Fq2D+8wIl#^LU)d!%r+)5_ z-zE6R8-DF}Wy+qw%vf_ijR;GwH}QN+D9ik2p{q6x>3PmnrjwxaRayVOzcB;bY{TuM+nIgFbaNF0fX5kYZj zMF{&6$4tf!IkhWs4{Il5xO8;ou_cq_@cxt=9Zi3|EPsXH%P+exv6&YY_tW3Y z^1rtGa=^&_n=)_x!_wHAZ)VQfe=25)e%XDw%SX2Szja#9FS{>y>2{!#?u zFD|7}7gun~1wS?v4x$5Wty94&7g?O#n}_Nv@=JQ7=TV!%4>tTposo)s}FDu~ZJ>0e_*rWj8DkL%-08d*0e6D_BSzJYTPa|w9s`yJ9 zdE!Le+?TmwOs>QwXZdrp(|HJiljUg!KTf$ofZZbqgo_YqTz?m}ZEHu#ji9?1efc@f zPiQ8ifk7xE)1XBd5k_i@p{S%Zh<0IDiFpu31i_a1sB40g6fy6uwkL6*J%1ah7qL{Ac!cw$qdXK$f7W22BJmyjW7CW7?=l~ z3mgh;0_FpM1v~^9lvF1%J7}r$v77~SbAfF(jM5L)Jbnp z`iNc`0#_HTifzF!9F4?!PnZq~8|G+OLdrg?OjY}D+qOsMfOzKe_`Bg#}O40V1=1731pG;+2uI zQM*M7%)PtVD#9j*pIHyb$CNQ@7ulxWX~otttH zdvV-|ho;9bTnSQ;yKuV3zTK_m;MjNmmb})Hu0Qc%uwam6Rj>^WWra5Z6v|ZNW)n-!dB~$%2 zH+!3g@v>Q^Vk3|7FmN#N5g__z_M6cH;0?ea@J1l|T)AS05`8Cr zbK(BCz;l5Q0G9%91G4f-zf{w&0^W?@2utX>5`#`5ik^c!zUkO}@-_HWi0lo~x zJ0kiz@H*f-z$pIy0$c?A2e1{mr_V6(PKmNTkUtMd{)2&dM@QLoNaqnFq*E?pK(;c{ zxfD+NWZ(tBlYkJC=yc#kz?r~{fu{p60iFS*KQ6`4-$Eer96cX+8Sql=evNj&4v0P^ zx(0}mLi9Q9{(J5I2jCf?zXd!K_&)Gy;9r0%fgb@^0Y3q*1%3{E5%>*oBk+45$||}Y z_ircU--`qAsIHzi)zvE+awx9qy+~Ox4c*myQQ6Y*d!W#K-8&fF@m}ntcXm29 z?8e{hPyj8L*tU$Ur6@MTJjUya_$7<*(+K&0zx@N-jy<`vEDxGRvM1sx$l!GcX0dP9tAXH5W%lSaKOziIf*UI@~Yw3n45Q@XR5Pt3tT zWn@4CCC28KIkoE6wjB&JyBL|4Z>mx7xJxmznaTP4FqeD2>-SI$DsyrM!+X-u=1UOS zW0;2N58&wv!Zn(R-%;i%7dRAn0Ptwwfk4*DLBL~x=n3S2#zTPh_>EDZoZmMTI3K@D zfQx}+fUWvBTD<&5%QXr?M-L~z?*SI!_e((fds)-j+J@j!t&O$}o+~I4(OGsEQ#LYW zr+G;D*pJedL5(Gmjn2HEPHY)G%uS@EvvIYyWw4i(n(oYgSZo=*?MlZ>SyS;c4=gX! zjE6(zC|f3IMR@!Mxfr%-yuv*aj{1f=^b|B^*o@T*QQ5LV zQ(@aVY4-|Sar!d--h0cRfwu*{jzr&QoCD3LMFDhbzbfpn_IbCnmt1!j304-u7kEy? z<5qi`0^06)_)>Il2{%s)pc*;OI^$3`05)%vQt;J_yxiuCaZ>a<0*f`h45G($Oak(2 zqym@=oB})uh?iNEodW4hE9n$bhO0!BHZ>?#wB_100|ce;tAcb^1?jAcX?Rps(5BwaiguxPO|FV+xTva7Hde(9p?OvXh6xF6 zi{aF^Xc-(2&L6Reomz92Y7$JEn!Jg}473=&5JeS(?P$wT(ZOlyv>}))zxS2q)vjuW zZcfy{Y1tb)_C+;=p=M*_{sA`E$e-1jpNJ20Lh21Km)zRaGoC;q0(h)X&dB7up z^MPZ57(zzb>dpkRO<^b*oen%3cnT1EA7yxbE|9_y19I5B6!-|R708$TuYjw7ao`5v zVj#tUYj z3Pmj@pdCdmv!>%O$3Di#XzV**OF`k{?Y47<4?_U>^rQBw5{gGTI(2GonL|FAqBDnq zqrt{EV494;0%9|Jkze80aF^I%G%jNzy3J=jDkEbe*=<>;4z&6Am8kdB>RbVYSmtZ0 zJ*}m_3FE6dRj1fz**Nwv4bwt#$^_2VM2K9J>Hiuy0Qe2?DB!oiF~IMElYj=Qn_}bx z)&qA3^5wM$Fbbp&&=UO{Uoi5U;=!h*#Dg}a_oZkzYgg3+F>R(f3l=3F%0}_PR|{xv zy)UNxfAOGLZn<T(3_@K ziFkJElnKA@LHsvM!%~2_2vnMm ziS*o|2>8#~?RC)!v>nAo33cB5Y2Cqy*$pwB5^=qtDamnlhKt{4eg|K={XPi2J6{wW zzmHo)&3su35U=Zyschj?h3O)`#4l{8J@dCYmaosXFX3@)a^FLIWo!4IS@ju~uWTj^ zMtF?MnX@A;&9ya(X1K~Q3uL8mK<*2sT!GHRoiE1X_i;XhJT#U9#1I|Vj+8BqE}#6K z<*Qix%0XC8d1g0j-37X!L*M%?U(>ZO;c>K`ZsN-^`a>$7|@-891ED8ufc;_g=d z$8+}fTf1AnuF$@etG%7}5MO3o7k(B_w|qUQeF={vuAT{Buoy#rms@4|dP(~d9=0#O zqpCuOLeGK4|%OHk?^h{<3bJMGfChYX_? zM#W`salJtG`^;V>t?Mxeir($5ySMN#4zm?l>KFgeaqURe?`8Swq`InqQ`I9^ z`(ocIDlBGqXexHtwv_jkG@JR#yP@&yYGquDb#WGHKdQSZD!s}e3{b1 zd|AG@wn-yA4r$pNROj*Emalo*m+(+F68T~-oW1cr63#~aXTdL9c-XAud7}nFDx100=p1$nbR?Yw`D@*wiFuJO_Ru!LFJ$ll}Ufpgd zd#Elq$(F~&hdnqiXM2zy?h@*`OQl=!B6!}^eC&TjC&8sV!|v)E@O1103rvE~_WB~7FRuaM z8RF*i2(Ju0m2N(d@XiKLtDDai9*17Hf#(S~pGSCag6A)8K3911LcnO?0R1)9UVcl! zbBvqM6&}m4LG!>W#!I(nGF;Aa@p;v6I_mco@V&+NI835`Z37k3ufnq%M6;9mO3l|^`p(uoDny+=+W?RBay)HrzFpS^n}^^=VRnr{;~?5G z-p7k#Gw!tc!-q|qREwLDn`@`d!U=d)bDMvhDwr&TZNrq0dHOrFzDg!dstn?S=uqXv zvWn6P<>7=97L>Z^I2y;vA{%G<4ZmNS&bc$jn1q~OHymBl5K zEAZ``p5r*O-gOlH|D|K+|E)WysjI;G=@;t4ZCr8SuAdy*Y zp*9c3|M?Hsr*hPE%ueDedAH#Agwx7I5jV6nRo6N$x=(Ry`YxQiPsJ^d3(pzSgKR6h z*Bl*|CUHMWA#~!E6`-_t<3T&&x(?BAM|CVk>HMTxWxQ)7Y^xQ@w8uIBl%uOyL#Nkc zC-aP|rlzVhIe4ws>_qs-f&Gp~Ei-4aPQ4FK-2OWj)U#ji3rwP+aZqFpk-wWt90QLROzHlsNk!T7PG z%xx|u@$0ynQQG$Kqi`v1Juwu_dicCqAcfk_n!YUNhwXR#h{ZXmv7?O0!J*jEMoVYY zd#JTzD2{s)vVxCB!6dBy21#_{6F5HiXAM)P?fej{}N>muX9 zf-QcAucgQOSPxoQJJ{T3EQ|HTfBveLU%lklBj;hGpE0vF#ySmVJ#yYm^^@ufVNoK) zrt|686*+ZHEh5G|1tus?!+*|dq)|gcG@jD9=U?{UTU+2bK~v<~%fv}$%0?ydY%ZWH zqdvHJ<5@K>;H}3XomwVUxNHi_fU-q(s>zy!)E=A;s@j{~+*HlsJ&uLR$-$dn_I;Q6 zYMLWL6?L>PK`uo0Ov5x$P&m&uOw)rHP%xb#Am>a=fvolMKrxOj0%YkR&H#IxX0^ST<0K5lyHt-YjKH z$8WCjV?VZLIYJ|Az~WK1Owcf!2X3aHVVg#|JN@(!PKL`csar$iUOJ^D(vq97cW7qripP z`71Y!?#B{o9o@Zkbni9sMVwTPZT5{Ajopun3h<*jD;~zX1k-p8;8jp92ek3^Qztwod#yv5?zwNvbc3@ zcI*jVYZog)#>9*% zr`1In-2R4OI#|n;h%gywu)UON!}ui1rK2<;YlGWR^MM_K(|}n2idO00m+If-8;(cS z8f_V}n_AIUXjjx4Y>eA9bXQ%SvN1iQgw|iPWNKu}EFNW}8$*O5iM9d6c!fI}E>4ve zGi=6cg{W+la}_oNG&yPa3R`j7Ra!zAnWTr}YeS1Z*#=L=@z$x7pNl9|q1LIrL#=gz zQ2Y*&#MZ`bK`1L@BXy{C{^$8$7sK!1){5L=BkrffhFhm^#^o6cPYcJVr-$06;o_i0 z8z_x4q2y*hp*V((Q!vb`K(y7Nv|@I=*)&*m$edAgy);4B6 zl1}!Str?}URq5ni@HPu7wgy446p^gur(+<>WEGl4sfrQzGqI}}6-3En;EI6Or5BHU z#43m7UEmQno@_#KgxV@NSmj-1R7kffgP|ZcTd|&d$G^63M@1E2P#lV_Oy5w##X(k) zR1It6?0$&=KC08)ttWLKy0Udb?=2Ovl5Ah>X{G}&v&$)r3p?o^amxYmrOqC3DJw|# zfZ85H=eJ?BM7m*gZ^nI}FAOQ7bcEwdV8U@NK=GS%H-XNg*(~^AF5VRQeOGR8<~x2( zZZ>hzTDF*kGWG-b;qFJdHq0RrCuUYz{iu1yhW$PdhUIP8k5b&-{U~KpT?3@H=gerC ziCwAc%Bo|!v3~_+Chm0M2^@_Gdx8-89@Y+tVRQgNnTBcR@BSck*K`bJqs#}sCZauo zeSsW^pW=HUf_TLL0>h z0v7{E0XZB#61W0*6z~CHDR3ol9B>VAJn&Uu7|0E%43ER!V}Km8GCeK88N;56WGfKbYgZUa);>IjraC2$b(H35%$chHt$P<|Bc1#RQUD@H%?V;Z`v zcZag2z4?fBj^icfsQ0vl1!5C`8PqOcxu$>$T zwT?*-$IH<1;|9TF(jQk|o(aX@pv1#B6jD>c+Q5t9pJrjkJ- zh(+nxIiBMxpjUZ9x+Sz zZ^*yM+*H_=%+aPk%@pk}{8ltr5;v;QPO6eQWuwfUEHvLf9gTgUD$Cojx(w@Rq>V<3 zLu>Gu7&pJpzeG#U2I5!qP~n1*ShXxKks zRu~4?ZRCc(eSvr2_dwupfJXxF1aj5_6(0=&F}e`NzTW~T;r9c;6M&BZYk`jeS$0nX z=L1&*mjl-T2LWsFDAA%#iI$=v260v08PjSSx+~FAHj36Pq51acVC>;KuOW7Zn$=8* z7QcJk7gJi-s`2tuQ%rCP5~U;nfk9^>=QdC-pWjgQ^T{QyR~6CR5Mx!*;7o{90M_@{ z2>dz|Pa5Zhw9K}_reyYV*k+6Cjrgx*7PaY;*$Y5%>m2`8e90wycA1qKHd%&~-fU)l zbv+i|clH>Uf3qvALmEuO^so>p5&XQO!K_0x4VVYq6L=sn9|)Nhc|9077QYVxQa%R* zp9c;F{t*aXnLQf@q&zm`QSwMz2G4WRwA-~!$s^NZ8qADoc~mya;~7Ge*$~KM7kz#R zQ~E!tA=m{8a~Qjh3`Y`vpE=(;W6bln@(Y;Th-+uGoRT}49+@-0j~fhWqp`I1EQ(u~ zgyRBB=i-AGmUpmxvG<`79*1ti?x0#4Rmb0Q!rhjyQt_i+cTTOej^Znm|M3(}e&#gG z7YC3u!sCdGb!o-bv+>FimM^v}8sTwhZ*>CI%GYlu#fDhEo)SN5M$@S&M#-|Yw{HDc z?F`G;U$igbam3Zx5!ZKDy%e>4aYG=D@Hp}%<>1SO8%twhR`D#$7lz7WR9V?I#V96L zz8)&;0#y*!56ubMm+&~^;`>FFA^G;5KYFa?i$iT1;St*{nu4~@ksQpENtBlz6lio- zH?qNrp)YE5vR9;G{+zlt{EYDXL~Lp6nTE#90PXUO!4-J;ePc?mrQP;{j-48Us6pFi zX1+Q7zN_$`=F|n39FrV!SGf3nTk+ovIVVwu=3H@(3fZ=8xSRMgrT6gqLzh{;e5#mI z>H|t%;QyxW+x~9(+Ee@DC#kcg^l-%W<|R$rEnobkp%ETOE%T$ylHMCTl#I80g|#o? zaY%13@nz<#tjE2_S-xtuFX3^-)jQz}7STPld@azvgvU`keZ-gfVRZeB1M%`;Rod&F z?+|A{)+bRr)PtqzlTSs(F+H{?=YnHbzwdMWH)U+EL@xfIL*6SX7yF1WGZ%*pKIc`- z*Js+7@HpxsAigL?G#kr)b+_fKE0YKlz@x0gHAS^jPOgSiVluzJ$k-FXHNP0Yp@?sL@eFw!}8Uql5-^Wn~-*zq6|M~aHrLn*8u#Y!uc|f8xw&{=u zpfsFX`4D=9Y?j7f2R&V4`O4M-36G;RD5X{({;$Rli!5J~~>+aa6uwz&m67upWlRA`6qTxdIF zQ=tvtxzKjVrb636;o6nas#C3}OBhwNu^G1Vw3e#5k;+KbjM-Yz52q~P17UVUQ*&cg zwT-4#9GeZ-s+@aiM_2FA+$0B6w=u~J1kiLAZ5>FrGf z>7d$W(ZROIGwaOSriRLyRZWJSD`{%MBerB7kLZ$^9J;l7Z>FNvVdl5e+=;D7jUF^^ z8E?kk42X&-?5Z~J@p-9}oa*b-p&9JqUHmn-G-4At)(%BXn~e-;RvtbqV3{3hRt_Cf zkUvD&sabi9XjXPVN-i9ip36(K@=5l!cH^O0xfSF3EiOJU%}Vy_?{Pe2GhUiN_rd)G z@co*jAQ<+?qFHGhtdhO}&*R`3&an{;-X)%zMO?Bk1kW^%k6;qvN&8VW{$~~zgXcoc z$MlLulWo{TKE77(0nbxzK9BI;0ncVPpGSDRV}#X{qb!(2ydL2V15crw&lMhv?PTzr z?&k9d?-KB=aPxVD_Y`A99sqYK`uTodBG}) zu?2j6IdX()uYQZbQ>OV+rH}PH2RvuH`8@J_HF$1w^SScN`d9~^Ke_ol!uuXP9XU>g zNtM0;+y-bK^3iyeUoQ-MOTag+zv4kLdA5%QaF_|64>&@FX|McvdtOgGG^x_Zq0}(V zBaHaxmA<<`p9a44T*bvvx>x=3L$)7yayhPqX)k?Y@J!WwsnW;#<*j(-LdY91A$cl{1Rz0CvPO_&d+Nmak2 z;BYs1J{qL>+N<9j%qj1Mho-&y7zv*7Za$Cv)`O?T&F9K5<>g}V+~nr-2yYd5UUc)h z!ejf`0-o(|K9BJB!rb|RcxY1Pm*I^C&xvk6kMPa_&k{GED}4ckca!FURg72r%|e3K zfbW$diYHb5Vx`k~2R!BZim$!;oe!SHnlDv;*=%prJSs$Q`THm0eGYu<4{JYtSAg$j z@YEf?z^R$<~j}h+&;Cn&OmU5!l>-}*T_>MRN{qx8jr*Dr@*rkDo zCRO?cwTbzxx(v*@IC=gI@dg568Z25 zZ-4L%b@REx3m}Yg@HD#lJimPr=XhdV&@@sr!XZyCkG;7VmYu2B4 zV_{jBvrYF%qr2V)hro@oy~Ygx;Aw3i@-EVnr5O^WWBXzC#T7rjNHkY4zhh~ zTw-6mo*)umj5C0Kn6rHRLZJzxcP35*a`K`R9<_muHgyAnqAl01N+Yaf;4@TQ#@@#F zOO`yl@MP}n9-RO7l2_CY-0JTZ2IX2*+2kFJe;$l~q|{CDzcilqPB^|U>*0#sw};v? zci)VVv4t1v9V6dcfGe*=tHZoTRCX^?{BlR5sP0QWvSLtvN;AIb$y(lM{#{rP{$@Sa~>7nNMybsH~}qRAKvyQUZ&> zvCKEOWe)WMn}xp+q!uBYM~=>JhI(X9PAK8f&=P5Ek;P5D=~}eL=x!ROpEb2R5TB7^ zjzcqG3ub9%ah}jWPS>rVN(7X}rSal8g$MVd@Fgl;LtR)-PPhU&45W8-Odq z%}6scutU59t|PUF&onAus8emDy9(dV38Hp)=2da_-y==73U|O&r!@3QlPY{wF61yd zY4=LM;uHUxKF) zk7<}UHe*aXAm7R$j3|2~G`r|@;6mUjz;l340v7=(0z>hr=1W@!Red#WtF~oGnK2I2 zkW)2ZWn=R#5L$oDf;l)b6lse`*(kcjc$989>%%l&;T{D?G_y?H+`P4ek@lf#24?sS zOZm!9*eLiad{`X%;9lV?PTzno#(-C$@Ub@C=!>1u-D)z7tcuP?XXuA_T#eTk)b9de zsNeMtL5(w8wUqhA@e}%mt1sg0y`$0S1|!V{Eh4@s4;2KWpv#^_;zSq1iu@wI{OT-N14r-vDb2 zBw~J}MpvA`EX2{v86orILi4SB^Kib|5l2BISuY|AS?|_1wON{8Kj!$WdvU{f zw-BLiH?|4;8v;*+n!^4UqBtB|voB}Ywe8>)_V386Pr^yc&B?HeYLH**AaO<#?O!DY zJ%cag-xT(L_@g6V<=1}d3$2PY1y)qys3l-f`I3-89$I80LxR2pF%XdgefhIZ{sQjL zgCgf+Cm?>0fwCLR$D_J2+ER=^#NBpiTM8(qTHvt^k*XV0wq*P+5;xylU5&T)Bpc^J z9mU9<9gK6J@?uDJN8{|WPDX#Ir06%Si_!froJ@Y4ZHAy*2uH#S%^hr~=Jl#OkQ&3$ zk<-^qjFo5`S!le!M>7R3xRxjI!2d>RPMRA7pRl{Eh=a61#p^t^F-rM!M#<4+~aZev(jYXVz3! z@=|(t)y)Rn+py~9!pmKCqi}0pbtk~pv+7QXdo-`QpTjRP0*pIrZW1VK2hFpnDg504 znhUxa6tz#T?j@!ekE%hmrSR%r?Y2|fQsg2S%C-!Vss3rV||e1-J&Z*TP9($46E z+TMxBfo5z3>e4QMDd zzbY_4M=hR`U$>xVwDd7n?fkkW!K|hzhK%g|y4k6Pb)`qc=I(rRFNd(G+36eC;DrPD zSfw3bx<^m=WSS@a@6z;&2*$yYS9Dr7u3!L$BWe~%It@1lqk%4sV!jc0Vw5lN z1kUw0V7zDy)qaM-XHy&h3$J3-_z0s$w5jI35Ep_Na3VQZbXxk1Yo5t2egeAq=;kV9 zm$Qq10xs_3>&M{M9?u>;35}&<=+#5q4TaU-+pwXq`nwwnYku>FG7YYt4W%OP;oVSH z!QV2BHya8U2-X7aO*D)Ee!mUc2NeCBTy}`G#n$8Z2cY+W{tc83=tEF+*Hmm4L$@sc zzXJUTzZ*dJgKh!+7!t2;=-ZyTd*o#6HZL9fJr%C?O1ck(QPr&>T#=6DTtVr;p~1x*xXTgFQ+X5^Hc zoMa?p)|rIaW}_BgU zrQ$Wcbq^A1{Lr7(ly829dEf;F=11sA(1jGBqj;;J^e!1v%}=3bZrLz&J1-QPd&4-l zZzk<8G`B**TXEZ_{Q82nO1EAVv&8(IkC*P|1a6UDJ7U=w8hLG}W#3nG=9z0FE1+Pm zdx7aMFvlf_o<<*w?8QWCz0z0nS&8gJr7s|P|)6#XiXOVp-IW*pU-Fh_w|NDImGl8Yn0o2*Y z40ZQ0>;k-v*AkZV$VGrR?_*+c_3UHVhqN@0`8k5@sO*Md82&VVW- z>``Gmid#{k#yx1>`^@~zhB*N;9LH5VmE&D5wlB{dv)q79xNg=QK^uV{S~&bd8dhY}MiY^sk! zC0apxM&OC4kJB3e3xOxbv?-{+rcL09No}wiE~u|+<8O>YX;4N%{em{qQ?<{p-GZK~ zA>@BO=}m#5Vs&g_&K@>YjaGnV2vEhuiXl3;0Zr8BWX8o zyDRIM~&Ij9M_TfEXxq=o1#Km>LG2C^Q&iUQ;}~$ckUgr>J?W z+A={_2A*iA^2;iJKejv@lbLbIKW-whQY7Rds>xcoFq(}R9Fo#=#zN~{7>dA@M_~1# zW7KkrL4kwR1P)hIIN!xC17^8#6{m}+M=1tL(4)kfznS*4@!0Psp2e?oUF$b~bI1w9 zd#HWx;bOs@s;cS=_ozYP-iD(F)8d|)-T}AfqsDr;dX5^*pq54rc{f2$%P{^NHoC&$ zR_%BOy7>&)sXgfe(4nBWgJQ=ZwgEH(%8q^v=uS{-KjN@45tPFPwHL9?LX(mx8O34n z*joIa4SEk~CFq&RFX9G)V#gu&dr*8gA8U{JECb~*^D8`Rn4wL*^H6SYY2Or3)CTZa zhW=`pQMP3Kep1|g*(Vs;hdLO;_M{k@J3AT~TRIu(n6d?-0JC>-!00(F6$4*aHKp>} zq}Th6R`(~}9=kx@_3aD~c$M8DdOmb^Sf4G6hRhZ04>6Hh(GV>?ij4;Ivyl0bbbs+? z-g-9}g&ML&A@irq&(PB`q$KM=c)+`je{F|t&JH85>J(UW3cYH#97l(c9L6@tJX^b+ zTDOfqnr{xzH*|08hE|F;JK9%h_CUXcW;q6vsjb)^Wb+HbzKwP?J70a$2?Ma3 zx5*bV_p;?;pEU5uX1n)_tk@G;HL9t4s+!M175YHg359e0Z|M(Oa`Fl zdT#_Cd0lrmA@dD{h1QG|q1PGJRPzW0hS6Z>VO%i=G;-bvU2y(QOmDLog;qg9bvS)d zPDQ7{YMUXXD-OE5PAx{tdH5Y4;5Y z!7~kP_b0(^qjvuR+FcO#deAJ;b)dI^{v32Y=mt=>d$eI`_xFLa-9HG5<*M-u&`yx~ zOHfQLq0`QYodo(ADBA%vrHR(Hji6!t{taj$=x;&M<_#Z z_Ozb@s!xEn@ok}uUa(_p1uy8DPT)2qhNcA&iq#a}4unUR76jIC`puW|6?~zPNyX!s zhnxpKjQLwTMeDEaSx|ote-_ktR)i&sU#F6=d4|o=-ig8r$_F5JBHQ_VopI7wlUDnpfY=$a%Hqgg87oG8Atp1N*Dt+ShF7Z^#irH9agb z9SZ7tP|W^`1$C!k<=BXqFGp9rR?}OF_|cK`@gtz~2Ew4YegBzpJzgAlM30weI?ySw zdy*HI;T+`4>N6ZoT!wTV5xu9SUnfkdJ|(jJK+Q>zElQoBZM|FvH6dAEdfJ;&%t!9~ zC86c37hg#-HWrK9-T2Qsl*HY0S+XZ_e_TeZBpGWs1y7=`KiMx&GUmfpDQ=5lHw|%R%5<=QxXNx+jwnx+252vwq+O|dxg{C z&|AB|idM%syba1l1Ow9JRFsNP4}lJWZ$aZBU(JLq+2y32p1LP+5{ z!A03pVfz~%zrnaszGaj@OGw!$o3k>t0H(|v@X$Chb_l!S=NA-ZTgFT7JAzCLU=s>G zW(s=DwwOUBhQW9$&TesAPuOIEeA?Y zINj17uD05djXz$KWplBO(Fn$&c7!$CR=;)L8~255t}()++Kw|U_T+Y0y;cusu(@Vv zF2Oj$VwT%s1uyDsQ7h@;f;6V#V+o&82E-VlTn37X3cH@h9ZuZyPUaUOMav(31dQm5#04 z>UAyo?X`S3S-*0naE+9rQj=ql5WWVoW{6|8J z4KLomsd*~+n$D>P&Q@*}AREl7M$lEqPJ^pm?rH6Yth2fLYA(SzQV|p`)jAC0#j)M* zwYhRNmtY*_p5_Rv?@d1}vbiqTT!L|gb-Hj_{m-sh8=kkhuF+hAafH>^5mvwTq24yv zI?W{*M_B2?#nwR+nfGp{&GjqIB^dF4MY}Zb6Z*m5?>mP7EYcN4y*_PTUS|k~r}eE` z*Dqe5cWcT040m~*DO^_Dxv}=KWSi@t<`Rq}T^Yhpr!)I0g zjZoz)XV_eGG?!o;VQ~+|4y)hVp@VF$m6}U1j<5zf!s=f$cYw|HbIm0fM_7X$VZ9K| zxX9*uQgaE$5mshAELe<}FaGT>ZLaN_OE8XJVu)~Yb-`NqhrJJe+q~9sZRGczn^5b9 z#B1G$TJn%)wJuAztXel{+SpY#*AdMn7)L6G371t9R;Jy1kaUxMU>so$cZAh7b=p9iYn0{^j3cZOj<9Y&`0*^8>oUzH7)Myy!llMgtTcmX zJZy7SYc9b!!W!ua>)6*LZnL?tbtpzKjSWk{;3_- zbDB#qj|C)nhmrV9L=`I z?oYJSdCh9w1;S<3x*^Fg?6tYtYIeamQjsfM?9FJB+s1H^-3qI(w&cPG<8s0*E<_jK zw}>JBj9Wf>>7M4P7$ulH0I*UKic21)C5MclYlO`cE-Mv}rTn^!&2_ov5{x4iVd1h; z@yw7n&$GF%(_Dgaq#`0*T-$RVU(&GlQ1eub7Rmto17)My+g)7Mac-H;yg*2P%`kD=rH@B5mI|FYZg>24 ze2$iw4Ni}QY;bxcWP{Vgs^cw$A*uD^@bFM!3}-fYad>#dv%!hCv%%pma+|+y)w$7< zZ=$f~%<+2I+)K-C4dJfL&4o07c@r-@4==0uJiM#|^zgEZ(8Eh{LC5f{xw8^a#>_Xg zYGh9@#Wk#DE>ADTT)155N=ls3l7AAOySe$8V7zo@VVY_&ukHks-aXxVZrgMEbrGw#&M07bN>~PVYv#@hDhQDdNbfVn=_X6Nv z(O67MJ#~6@g2!9H?BNz9Ol$G$gbl}@cxYOS-*8|?yKx@rEdyqr8|O+dqrV224Q`x= zyar(Y;KsS+aYy4LjbS=yyz=jU?D(|7R_TM>=7iw}kXQM3g2(TG`8_uzVOq<-&w)9v zaV_OvI%M?5^f#ANV3;`0BfVDubCnzCN-yinDq!w#<2>X&0n8>h&LxlW+YL+-H%?(% zi{I(M407XK@>sqF8Y2Sn&#OFm6~Z*&dIc4#rShnN$6#RAovv`LmB(|yyrgmQbhzTj z{M!f2S8kj~{`Kf<7=7{3v?P!9F9ggbZk&g_g}~Ihajy6UA@44YfmMuG{@sXn-UwW@ zpTe}%A8?UA5txZ*C|qm#cMUKrHO>#XgzJhQ^Y0#DHo9>h>3t2DKe=%(dCb3Wf$4Up zieEfj4|zj@Ip2+Q$qPcvRE<#*z3bl*crFEQf!;V^zIgQq{Lbdbz-;FBElg|qw;z}z z8W&H8D}Kzsld!4V4-ZWo=aJq#V2a#0mpta*9AH+saUSyS2Idhr&LxlWds$-`KN_hA z9y$o$cjNy3ItZcoeO_txch^CP_ttS8gt#IyGI3(bs8G0M)a22lBNIysi^36{6mBmX z1hF>)=aLDbNs~&7qZ22?1Nz~RZ&zJCYkqaf47s;a^mP5dp-1rlRfU27Vzq$(0`-5? zOgRVhQfPE!yO28gAC-W}loj~$KwTA4I(;s5gUqZF9epl+pe<+#q_(}Pgk05ET2$f! z6>w-Dz4E=_`m5bqd8ZW$v5?r3SaBfJ!#XF@e6A|ebbQpRa1R?X8rKqhZ>gk-+tqB!8ZaO z4~wD#$T|PXm8Ctltb6a0?a$;tm^Bt}7(Wv^4TnD8SryJ-IH$AkgA0zdEyWcV2sqVu zPfq3Yg&U3^e&LoOLq;!|Iz=wOh5MmrC%-Yi=dPN^r#{^0?LkG4$*0e7U)MBp)tdV% zo}N&fcEJ~UX}8Kpjc`BOuI7)Ytg3qN?3G=caz;F~66Y`4Q2yR)N-wUzsQa#sdpjN& zR5SN>DEtujU9aD0Zkm5*+NaaDzfm%F59YqD>k-`f<(z}hzWC*s>wG76-1kJ*y8q}A z{4NUdrdNJPm3miC$E`&RzN3%@3+K(pX6?*Dv*uP(!QaeTmE{Yj&RZ~aDtnx>htD{B z!TeIO1NB|Q`i~w#cfOYD8Q{NJk01^aWKgS~eYy2hkD@E$EyRJS>BCp)TqwZSlxpS; zs~a;dtD$a8S>2cl_3=EvQP1_msghs1M@5Go8Q9IOz~fe!z}+eO^IhJp7|gUuctON$ zkgvz}dd7kzP<}n0iQkFG(x{Is8*Us5i+rNta86ZOxsjmb2EA$AFdjjqGZ~a`?P&0B zEXKG^1m$J}F!Fu*MW93Q8~m~1pqGR4t$hh7-@;7?9SGV1kNOUqwiM$hakur_mIA7F z=){75M5^zwm5uQUh?_69t&xgDu^sj0ywo`p$!XLjCF)_IYeuxpK>1&twa*_uhhN#Qvq(1xLJf@H$819z{f28sRdsdM99uaei_F6y8>r7H7hd{A z;hgDLLidcN95D(H&NP&AL|o&hlp{`nQ?)oN<%ps+k@}BV^vXl)#t@(QiG##gF#gOK z)&!O+O(ja0zpFrVLB9`rE$9MJVlZCnlBZ3b3si1zY2Or?C{VU#=&wp%*;w-ORicrm zA^kOF$TmjVI>C(_5`JDOEwVwxc*zaI2VdXg;6U3lRR=BE4AqvXY+N}j*|3OwQW`JW z3hC?B!RWQ6ozcCzqtO*QYAhWxVW$E$r5IvSWMs0^2LUY)=3VS>sNDgzx1jEx^cVud zk;OnQFLQ+kut)hDnj;F#hvld(HAp0CmWX6Eg+@k<05rT{2g~eY-pJ3PLOA?1Ae>$n z!2#*A0dMDQj@EbkeSUpqdTL-4+R2SC0E5HcXbsfM)-)kG4vnn&^{d{x8wIjmyrA^9TTHV%= zxif0M62_q{uV(jdfvHj*!cjz?Bn;;)ELeK4m0qMz;;qtEU~ZJ-#UUIjFVjgK32RMO z$i%5G_^wAp3(R#pB!RC$J6qIzgULjD4>e6pj^LzLS*SK*`1U7T@KEj2^l3(5#T#JN zIj*wwC7tL3bK#W08g}S7b{TC`he+vGKn;JB&eLE&@}k7;VGdGe@k|} z_uLJfWtcDQJ^6BCr*=fOi7~HMgU$oRo3I#qPAZ0oT@QLI=!2lQf&K#YcFKN1XALOh&0e058sBM45oIFU4N{aF`IrZmp{wfUm5u%F zP;pCx1mjS9WD`byoGCJjJ41zF7hxPD|M5->RPk{>qHICf!g%~r_ZXgKl)p7@`DJdC zEyy$tvE({2imwweN-j~X*Ou{;D_{2+X}wd7-iUio#JwBho{ID&F+DI=Sgofa5lOpO zSSnV&f$fcfdynq%6gI5BF}?)T*!T(%=5N71*Sx2!5y z`m2aJ5!Y%)^~0%|D4f9GgW-F!3z*V1=HSw^(B zAvwfz|I+azh@~5>gt!tR1@TNeBUcwGQ*o^+rYaXb2CkMVMA(c}MC&KBV636A*6&j} z=!;a0tf^Sqep{phQjC!`Wwe*kt^oc>SzV+Om4qV*`%OzjNZ^LOqRa!@JG3$nQR^Xk z>snRj@hya$i6_bUJ#tvt*epN8!@KsNHoGRzweI_YrWbd2T& zblS`>%wS@DK~d9X@YxQ!6u(~sy$yW3;H+E2q?p&3IXCKfD*?8AH+=oCGK+2y`Wcu?gw1}`Z4HQ&`&^lxSGE) zU#DK?*omNrKzo561-$_DE6`D(-++z-MSY4*06hkJG3as7sh~}urJx256aN|%$NXdL zWb^T;!HhO2AVHYQZJ4$}V;1ntTg%X24Q9%gjNe7#mZl+BYRZ~yW0b8E+%Ci87j>kR zZ5c1QlLaYS^7h~`>=tq>MW&?urMOb#HZD$-d{`t5QW`J$3h68EViX_hV2pzLmGg0M z_LAol z?KMLMzXbvl@O{)vk`yZ_ZOEsB*QTz8X3dnW1EG;~3ZPa&?lXvDm9yq+pu_c@E{oPF z#l_U55REqe*`Ht9NQEL%aLYIstv`1NJKK!;i^DR_9c46pMqfmu4Hfmz+h4s}d2)1ps z@h?dQW<%8fO4R>)!GM=Ug^HT-Q$rS1-Zeto!6q!=l1`?Q1gO%?uifj5)`gDN><(kK z70jlCc zC(an{od^DM-+93=3EIPbI%tA!g3|fr)2qwn0&nz=C7Aur#2XJz%qsx)HtZzl!7H(o zjL&x$CGapzc0H_+mD;@%ni%78GH3y4Z_v9z`+>d)iXw`kdoj)eW!EwQ^fXXZEzu7^ zJoN$$0_CZl!Js#Q4gnnqzG-+=)1^(_p`qMXTl;+D&Nz-~k5B%?E$R&upk9$E4`!B=sy=_(tWu96Q+ zJSMbH!{e5(kiH?EjUnh7&PLNc9o<8pvQ*;~G~EE^p;X<@jm_nJMJ5W`%A2vnW&l>`xwc%Uv+wJ*5PPf zGonU=GlVCg2c+lnP{w!Y6q$7k~}#HRzEByM9$&zB^9;WTlZi~p=bc0;-q zzs_?h`QRrdtOf`0{KQ_|s*fW})hpSAmxpXh8Gw2lug%(1(Y&$&58}ZVUU_+02|r=A z+9q4t=kSW*u?*wHhK5Cw?BvlMjU&c*hCo@FMuDCNii6U!VH*V5gJKv^v@F3Z&>mx8Xx?-EdkPk-hX8@y_8w53pKxpsS4+frm3m2tF;35%+@%Ekt_ zOx)5mWTmD|fsIi%Hj*FU@f$?##bX&Sxy#{+2FEK&syje21v?*G4=rUWF6NQ4vB4?% zut*rBG+y!*(zmd!v9K%|8`ACM+7QP3f1`2=ekkiSiJ!>&;pO*D(tvj!-i9d)sue!V zEuT?yWx9AUWq#iw{HKkkMdcI;A1AdX&d1zl82t`C@UG3p{H76%TGxT>T3^j~<< z@J5?!0G(h2<2dxi688IUz<mto17)L6Y<+cKXn{Sz0Vso*(rV)%Itd4NC!}{vdbI00TYlMgG4j4yR zlEXgcDDye#^&OjRt_L-jDuu*!vEQ)6x_0r%zu8<{HJ4xqHCzu*xeCFR#ulT$n(!@?!UFr|WmG zC2g>|xL%Lw7DuZmnzM~@;b>8R=>BO{>2#ec{cDl|xmT|kywO(@x#*wZb zj<62BG^MZ2B?B@11>*>dwZbp;5EkRbNQYH6*K0Z~!8lqj*Q9SD{ij`v3?n$P z|2ai46$v%LRv58gOa6PxDehcmZn3$bN=i&GN_M28w}fSt&iK5=r8ZY@MiE9ZjvPA` zu6C_E{mg^+*<2$vmtY)W^${+WCx%g8|KQJTE^ffm2*wc>M|3-^4G#=@$L6xODFx#Q zD=1w2Pjk-M1>I~eZtBtm@i>nJr_sg7i8C|os_@ImFxnDJ=XAl)*=nb0@pk&4mYik; zDLG+u=qp@S+u5<`V7<-Npt%I&NQJb}c-!$^^yV;|YnSFytvE5PevYu#l^*`9&2?OJ z3C0oD8Ny|i&P@XbRoh&rvYUVrj3ZrV!qqOF1J7KakgjtzmtY)WWe8Ug|7kj3v~h;|MD=o-SC7)fXSTz~&mNxdg*Q z!b64<1jEvC9ugh`7q3IY6CuO>4TwI3*34NS)pEOgd|;p@#83Ywete+MmU;V0JxGtA z|MlSW_EUUbG0~Cs@M?adwAo9<_;I}EKGtcx<~}Me+3C%Fth0E{eH71#7J0mU6i;(m zI>pUA5*@4^Yn?!6WaFM*@r`?WMLF)NIGwSMdp3`F+{+{GmY?@-Qak}Icw0$m!P`ni z3*J^TTJTofEqLmrc>A`rqSwi>j!-sV^6S>q3P43FOP|kdQ9>&KC85PA>V&oA&vTnY zvxBzzd*?Q@vNF#ZA#k4CTrB4{|8}`yOvAuI<8^NHTh5UajmNpof z{^oj|+vJA#W{n|^#_Jr<4!HNkd}lA`JTUBiTROLy8pPxc4-H3zmd-(aFGz%Kyv}J= zARopCZ47N*@#Bu=uhQ@$<8*~>Eq>kmLgx$~n%3f%3(N#JPU?r^<$q4C<^pq#8|OL~ z!~ydTU>2>M zX}r=)ZH=RlIiopSfQifVD37_oT%&O4+~)z8$yp{0!}ZEP1Nk=|nDLxf!nBruR|9i{ z#>La&iXZcDJur{DaUSV?1(_WhwCBlEMSJaaV~kCAfs4gL?Hfo z<=>0QmubND=WG^+`Qnv-c-vxJ2+SPLUtwCyzuSPhOXK3{aK(@L_Z%?W-8hf*9suSm zH_j!G{Z$Xln+J353=aW#>La&iXZFCwZPo$#(AXo5n!Hn<6QEX-nW6-=f-)+Yd;*fp5mct zDSq4x83Ih98|NW!HZTj_I9L4AA@4R|o^s7 z<45CFzG*18kAUkKQW!K-&+_F*DJKClXOzOVR=&3ZbC<@&^TicEmdA6zYm#}*gwAu%olE)hrF&~ z9L~l=x+V8wJ_y`G@;zET>5_!-Y;}O55 zz^u}^mg2{7?gQotH_k)ePGEMsajx`I-f>{Mj92lChwCA4ATZf(oJ$_t??u2|<;Ho) zTLsLmZk$UV+wZS{dB=_OkarZAq#{>3T=H1Hr)!KtdY3O>-V6e+V1h!i+`P*7J-Al` zGvPuT*V1}$5irX&E}qY>_^~`T0P`z1&Lh1$fO*f2bID_Qd<{&Oi7I~aa6RM=1SZ>! z^N@Fu#wdy2`B#tpy9&4?lN1Wg#WVk=0@uG7r`0AaTx;#)7r;EFaq)Dx;>Y~^BQPJj zaUSVydl6pF;h||s9{ZQUz>IO@Jmi%F^L;nY6+g~jZqgWrOXJnQ97Vo71l-+I6o&H( zullzWxG#XiTFbvrf%!(`T1qeT@8ru+CU|J#IFIy>0cMgL=aJs;15@wDdB}SR znBTZ@9`fGM7!^bB{F?>O&w#shszM=~JoE1@xR(KQ?&S*CTK<&*Gf(5<`QnNn%V~|q zD2Y0L9(qr1cjNwfy(bG1*0}~gnS{aN;n6J~9-g{r_^_!H%PY&LFDRdSRq4D6e2@3t z)Sk#U)6b)QpJsIK+6h~2%7~tXxznp_=1;FIshVGgkN!?E+IM{j6|B9j7$uxnT#{E5 z86EdKMfv50#ut}NnmlPjWPBKc72jFPFA8NUC58EuCgqPG17@gH>7@a~6kvQ&iC~ID zqY5Hk8X8*Ev_j1nHzS5)M->$1jSEej7`ntrh1+9vQ!+;t;9N*@*G_P$tSX&eSxz+& zB@3$O*OXRc7c99e%V4aei7FOe!%xYIvhoGhvydONs^*r=xpF=()ky9d1awAK6$)c6 z-ts1QU54C~5-BO4TRp#O-eS;F9HX6&YuS>!Vt3P+S6zYcDa+=}C>8A!)E$CrBUA{b z_{g$+rhI8Rzp9dYCCIfMToQru`SYvhOVIz(v{HU$N%KAN0CFqX4uv-^{{@;>{!Lm{x*;JqqHdLzpf1h28sGa>(=e92wYPy;9Dk1xiO zn(9M%Xh4#mUl{v`bY}lCwxlpJX%Zr+TEBPdT5nJPgvJ%N?Gun0$gQlQl3O+S zm7r{;RgEex9ZoFxn3Z$3E?(7S`PuVTXvcH#vJNL1=ixvgo9s2sdI$P2B}*(xbEeOq zT|U2L;rvx7*Vv-G;z+TST{1FL_b8~{(xU)y2+tiDFF9oXM;FWA z)5S9Q%zESFS1$<{t~)UQr8}QTrhSDaU#f4|h^C5Ljuy3v-123QGq3%25MBjg&XDTs z-S7FN&ZBofIC|yGygOewge`&##JzjT?QI*@k3I0p&*t2A+3!BaHy5Sio;~WxfrC$* z+3uoi_O&_T;DxVax`%SP5q_;`3Bl{qnX|6^?pi{i*W^12DV<;auTYNi9~~{z=LAJ1 zOfX|n_VE5w=gcadU$vlWW_9rDSqo~WR|XeU*Obkw3T98ex^(KSxuumgW#v;BRF_rG znxRUt1${CyEBKCOTsdpbtm^Nq|E3!1Z*-MyA+Dt|S*>WT-mCfSzgLONt!Rpy@N_ip z(6$sg{-AV)m~ThT{A^y;ic>d>Gny{$xxAsK2hKm>=s@bWQ5mOz2Zt5#OYVwoAFay^ zM$Iue=0J|RybMbNNXBNaO+Ldj8_y8eiFht|>Cf%F7zPS$%4+7!v%c$Z<)8poE!}V^ zAQN01Wr}=y{%OQd-Au3~f-)?ArpnKt!`gj2g5}=I4p4q%`5I^t6#Z3<+u?73a@+Jx zP|Erv=s?g8c+|)Jw8;(g+HJY^O#xM5iUt3OR3G;%8`oR`ar2$j);I|t;de;X+Jd{b zm3|#)S7ABG^}HEjbJnnsdDQ$I$5U#0;v(Pd0y8;;%Xjh84+VlEV}Zn$^u#G#z9bF% zKQ*^M2aECghfnncsr}R!8t`)8UYH4=%7a-qK^Vt&A*C(-=IkNqKY z%aOMt^_9;XGuN8iaFcc5iGwKqVD2g$VaW^Pa7kW9Q_XNy2WDk7O-`sF$%v1uff4m7{)}U(T1-ByJw!m|g!0%@?UDUe3c1qr8k=OVkj*ETl3#^zZN5zm7 zDtd_4Ey)bm%^pTA52%k+>p)dCR?Wi6}2@A*BU%UKCY24BkS6gHLF^jIAyhKFB_(17$4T&R5+~Gj(cw8t)77gdJOQNvMu8!HwaICrmVPw(H5F!Xe{}ZrMQ@<%EtdnJ}hx0?OyT~ zQnc9YY^$``l%>SA*yK*aX|mvNuLCn0D~^k;+Dk!^tarn8m!V=_HVkLMf|qS(<)U=^ zc-2+-mFcRF8E|9#PsfwcQ_ifcSx{kD$RK<@3^KWuj#7?Iydeh$;_I1&j8?pi(`F21E7o(&Lm3D$PW)xouEzijLK~}ek(Uvz8EdtRGk_%S2wcu=9liMO}g2)IcgR(&dV=t2nT+*JQ=xYnBA_= zH(z8$me@P<_BOb>MV~~ z!`iiEZk0jDo^eMlUB)Zi1r7HJcr3$sxks#1kk9n*1^WZX%CKuE#+Fc-{O~gDJSb;-wMr1`p zVEK8lSSOmJb&G;>su{0ah!vVbwXOtP|fuQUw2ZQE;W`a`f0naAqgAN5<0tzJpQde_;QFWEJ6k{X) zE4L@LEk*KyVOoa%st-{%Hph^-rD@1uO*yXE7-i#Fz*mlb%mY*&gNX5xI|e=&SGuJb z-EgOOD(?601T_H3&}oxY+)=o!uzKQ`lEAj9Y(dymSg=TVq%>Y(DWtDQd!q;LDnD@# z?kvYW-|cVUtm)$nGgPeS=wGo_{v1MN)|mC~t4FK*LP6iFM{B;S{ie$@Ox;768**l* zW{O2>rWh?9Gr@cvr}tym^)#xxqHo={mO@HjW8b>JH#*mC^U&=kcCOF}u$R$Y@ose& z^Wx&Li7r^Vgv~LSV_l3IzJ1%6Vqyd+Gp=o8Si#W8aDjkB(3`KtFV#2S6t~?68*{-P z3uoh(yT5J_1l}ftCX9vBUzb&{(qh%a*8Ysc=)W6Opug$yP{TC+HEt$|z}6LVf3{bu3e`I_1&% z16(MfPRSq@SY8i#uO2mzq4sZ6wZF-u_FD_r(!2@gA5r^rvuF2|+P~Rd`!_eQ{V(lh zq*pYd_D@3X--g5Y;u1FVQ2QsL_P2B$z>0^!p{Ih>9H6FxT>jL}&cqUB ztI^ba5#(BSd#tMLWw)%ju{w)=lIdKb=>^q4E(`sGEdG(lBky007Em*E8XDz*!?&sJBPD`->@&Q@kax{?_s^N2>Q?^H8Qw{%>xEm`d zHx5?f8S0u2^FvMg^Q7fXuHg{d&(+iCE0snWz<3+)K7e{Zv%$coUgXn~O6JzgQLD0M z8U`2-clUsg1EhPPMu6Wy&UDa5&>5hwfno_23xcle(+MV44mvX9mpiQZcRc`CGZ;C;=jH6}fuet|iOUCaiaZA$>Y|4va?%Eh- zWB0HGj~~lcd=&h5dqQZqTI1WxTe{=^TSzuyRq~b?(81tg$W4q~wJ_8kXUqRjIAmIh( z*9B%S=DedbYM<)FlvQ`FT~=Y#bTlu5n&MZaIdhj}LL_TXc;vm)012!)0$c&NOajkA zJI~VeMFsW0K(WFN&4yY`XRa+QjTmFi<F911+xm3>+JO~+;3qN1_$W$0Mu)QZ2b-?I!e zc2U+-n%k|q3r6v+?8j=8p7QO7zMX=t^EiG7*ka6XPg$wq_>I9kMD@NZeN@B~s@(zw zn$IUGouVq8t4GMb3eqGRGubmNikgMkR2d!QL>8M+qB#>e9ZSd9ZZeIt>=!&LC!NtO<-7;k}hbxwMl5qxjRsX=;Q#RHC_6n=; zxb>ZF0*d}mg8tm9XgD-1ucJ%ml-87l^GasUn!iAG4l*GDyt%O^zKN=QI7hAklyBOL ze1&>m8S4fFxfJ3!f6{s{DO(4T-l3Hnpe--7-O^cm2*KpQ~s1>FLAALtIy z{{sCZ=>4GYg8l+@H|Q@x4}m@g3ME6vW-fo=wc3}Y)Oc#LhJ?7d=mRPRNb>b;cPdig=sRFmzIgaqIxf7 zV~@hofs>my=uo@BuGDi|GzN=OMWk#fJL6~K#xzmBWn!?nWv>>uH2h~s-^W9fgeQha zDLYa&_GWj88&Q;PnHVf?xjz)Qw3FKzC+|r%I#)vnz)mPVf~yq<;~5haYrV4dgiVE! zh=il|Pm0^(T=kmOh-m8bY!TFrbWroKK?cfCD!zLd}TQb1zGE z%WKD$Cfy%+?%dFdrkZ5zO6 zhM8B)#THjBS%+nvwN=eDkIPJxuSo25R^m+aO|G-BHUE#!G!N^U=2k1=)=U$6qcGQ8 zpy!$krqmt_EE``RIoP;23B9X%@W@+@yOaET8Dl^SY*0;YG61JIx!}SMI zd(4~ZY6TL-U{tf^)h0A>42D5$YrNWo#pLmnW!>`4r1X6A4|)vZFKEI-0F56c`9E=| z@QwINl5^?johwOe<_vAu7=^52MP_Fmz#!za$}I;w_<=Qf*icz zzU!A1H(`%8uwpICqv^?}3*hdU`nOylocg6 z2jkHHvB5Zo)LDk{;9z_<9ICbZs~ChBw|79#1BLQTQTFvG&?)%63zVx{bX_s#>t8{y z2Hgj`9`qy7he7v)a^?Op=tj^lK%WHt67)IHBcRWN9tGV7`W5IOK)(jv4tfmqb29e3kVgFJ0&kXLT&wQq_+`79&L&|eKO%ErNr6CV!p%2>M$ zEI}KiY#iDe@%Rm(N{GB{3J0+Jg@6=Ey#+LiEpoyYv%XrD<#0+w|GlBs=Q8rU! zOH?)v_DXgllJdP|D`Z+pC!++DhD$M^_rl=b9fN#VP9*ds$jT!Q=}Jm4ZcB$vx$D;Wu1jJ78X=$gy)tFG?}NCt-AX;^x3ROe5% zyvoZ6)jrD(&Zs`6mR(ynGjTvKPOm_hIgRV5%t+SZ$jHa10UKCz3I21eU&O&(-iJrI z7|Z4KA%k6bU_}#TLe*&4Trw>1975UVd;OSt`|ttYJZyjcgO0QD!n+ACyt%~?F+WUr z^KkAqYq>>gJ}>XPkFw*=U6tK@XXYP#J$-!>VX%(mNY+JBRuzHOZ_B#~dF6myi*M~r;L2=KzAWW9Nbz+<9R?&W?eGl; z7H}c8f|K_c|Bc~Dt>7jjxoS9KQ{n(ohv$2)J)AT&q7HEH0qQ+KV6`^CeCDjV<+7j4 zj@jG%gUdAt;fjqNwPhF=4iX#)*|F1LIE-;caUSTYpt+!ZLGwU|f`&oQ2OR?%1&xA^ z2h9h)60`u6ladQTcR+SACdRg4kG~^^rS#mZ;+1R;$ zfX8nzJ(O)3FS#7pROd>W3pKPQxw`~S6lGh+OYYn7gxr%;jFa(7q}!HcBY^#-6uf$G z3stU(Vf6%3NnkgqY(dymScynDYJX?^6fzB}h9=_GOIy6|p|SFa`Jtq;3s*MQAeBe3 z#F4Zsf2Vwf^mXwYU7&)t!v^+p1?gD*Y>8g~@gigdUc~m)JuKe02BW19sP)slqj>Fl z&{{XmdrPgG&;fp4V1AakkZOGiRapA7)eOaK7s-0DAm{ypx`)%JNU*ZO4*k!C=Ie## z<^uD;brTBAw+iadVNz6YDKBfsl_sqW1)l4cx8k+MZH~Ny71Y(7G z3y}~ui3@U`U$&F?(8M4;VoIpyk|~9yUlc%xb(BH+mrTnqeKG3*ZVSk2$U0n@^Cg#w zL1sv1;HJxwalGk=<3VC)J=!eWm>XHKCk($;@T=*>bptxUeT9AqtvwzHtVx5r+)#zi zy)frc;HG3a=w%#-^QrT%PeXxnI>7wJdvCY-1I4ig)lA>V#bAPzx6Ha9*XVZ>ucm-gDVJ#HKv*} zbU?DXw8v+4vxh;=y1nAW9>JqCM-B|h1R^)^)93N+LhT1WJ&E8~bB)N-W}h$ElZS(9 z@{rkl^6(E1_J8+VxqnceWAb2q9+!;?1Sb+fsX5j%T-O)wsGurl9pkwJd6j;tpM=r?GuEM@0Q_kb6yt?!COQt-4b{JU6cRk!TxefIHV0*(B6iT|= z^;SW*{F*MyU6XLN6FVmsTmdxAOP^$p#k_T6`UJT1!YSz*;a4HJjp_4*KAe6BDR;j4 z;pw{g0lR^XVFXkSb# zw3`nZu2%FX#%&p}DUKO&w;NznVXQ!=Dc^BzE#AxHw)wCrU%+HK$Jn{2bH{)R!2JNI z_jC^H{e!f#qTCJ{!}i6Y;wev=8WfQ0^5#O{jbWybzSrJM1IIib1hnj$IDA6toodTF|+m zD?uLx#qCP5r$ASOJ_}k8`W)yQ(9NK0LAl1i1N0NnJ3)_u-UXV8IQ`3ury)^PoQj-3od?=!>Awg8m+K3+PLrFM#dSwP~6fq4UD&6Nlkd zzHcxlW*?)gWyKlIq1@S(?; zU|m&aUDdFtIUdQDBxAIoeGDG!Lkljrv7ei<`5`1w_2BG5lx+uWsu$iDcViXe^12Go z2-otu4>FPd9YGUrHo4J&`=<$-D9W~smt4jbZIt_b`22vzlFd+U ziOR+{s$?f3Y4?(?kiJve8>e7-dqNpr6yh_7q)})ZwI4@W`LPeiJHyauD)#rnX0?gK7A|PjGBpNwA+5a8SNP@{VKNf+@MjD z3ruxNw0`3^F#vE)DQxRui`Jfxk2tL9V6?7Xp}G8+q{{4Wxo!=g8}woF&wGb*9%5XU z*6WXU5x8uN$p#o(Y6Y7w7H8H+yEh{Y)j;ow+qko&n(7G1Vk(l1Lj32iBx#h^OOx|m zjkaD8XwaZ7G}dF~Y*{m{|E3q**;IRzj z!FZnphmDq_--vNX1=CBpF{J}&1AgPhfxOH}1$`C2PXML7ZlK?Qo&<_l!$uF#_MkmM zx$-(0lyl@>pxr@n(lmz8+Kp2|`-1iX?FV`q=-Hq_&@9k2(DOl02gN6oMqf})4bK2& zr;!f3>NIFmFCCQIdhMGc`O7p~hW@J4P&PJSeg&ZhcB1~Qq3kqljIy!Q7%pg{Saz22 zlFLaRY4!+|HhuIZ)U%j!Ff z(DI^z2yPkAOWr?{&9JlOPnR>JwM(X1Z{UfkISJ#sx<@JW*cv0Kh<4H?V2^`) znv%jfDs8Jn`UG1pzlWM8eT{uoKsupqdBu#$wmcbpx8-H3UyL*^o@9fPZVGRVx8+sR z(eA6l_;oj)Bx4-@$HZ2K|J<2OGWdd%leZ*Zk}E?}lCc3c*0CghoyZTAVY>nUCx{J6 zl<5ciZ1-iyM+G6@6(!yWm8gN82V-US@sIUjyoQ)*58^5E>FyA6t7k!1NvXB=V-LiZ zW*NqZ^`tKxm?E0l26`e;WK)bi-S4JdCJc@p$( z(5FE^1bqe+udWSDHYL61!LE8x+SI{5<%SUX`8(Y3y%=9>#|>Ro52|d*@W~UmG>zG; zX%eW7QMOKSD-twOlx-O=xm*^b2knllMu&FR8+d|Ur z6^26k9_eU2f*v#*ZyGYto1TQ8)apgm0l$R4>`{oqvY$1n((w`p<4-~5Cc!(^js4;t3eu(uFnJk9~-T66^H0MH!JA)vV6 zBUS=>J}Bb~MG{i!E`l6Y>1b0o6e_pXKq)s^WPgm5=5ioarBgOmx~bx3og8Fk``>us z7&W}NVG`md@rn{ZT>ZYu+HdNdmvt5F4P1M@R%?$gB zk`2eUVzxy$8a5gl!8oq+V0qdXj@^962y7=>Tz!Q{)jj9MIIIp<26B z!4mWP*qK>zwlB*XA$+V|L02l+Y1^r&{^cDLZLW~!5{x4iDZ<56GJk)*bk&b-u42t4 z7)Oqwpc2B`d;Plso9jx=B^XCo?9lu^b~y~|_h%ja)aJr4B1SNdusXxtPS=9lcb#r? z)oU)nIKt{8Tnvk5O4o*~Z7vKUVg%#328VmKeqRRuvrKNiID2#R(viIKHNf909s9bf zN8w5nXjVGxmh4pgb@44{*<2WM#0bWbiW7v3^?~N@``6|89Rw}ZduKBag^{D0&j3X66;j;RcKfTs}yUq2y<`Rq}$I={OO?vm_ z3Y!bxCW;Y^BdpVfOKLT2JAXCpJe%uN%_SH|Sbc@dO4rcrWmnr=NqQ&}j3X?m13q%m z9O$*+6Pt@4?$D@ulGrNy!PW135piM8-*WQ9bDEdV8G_-SwpBX);-xb{OYUd5OXp1C zvQp7w@yBayu58UE7)L7D%h^{=Uh?kf4mQ_#%_SH|j`eqh70cKew7JSOmtY)Woh4kV zC1UQ;ZSYMt*EO0;FpjV|L$cfH<3qYWYIE`J4UJ$NVGV?mJP|7)RSV zTevnM=h=4d{A4JaGJZJv%t3Jv z9hyrpj#@WTxcH?n>&N<=pPt^l)_qSfy;0^?ts5DybsuZVBb(K_9O1HRoo~&JlWZtf9%7)Mwa zIKnz}+tdj*SGDF6j3caE;j&s&zo89&b~==xv;4O;=!d zUjG<@i{HnOB7Ly^;nY7*Z(a{a3x-=OIyy!qUJr+A$q^&ynmLRSE~_4H42(V9<{G29 z1mj3oRJg2qc=sEf>TRxa%_SH|9_Bm3`swcLZ?U;*HJ4xp9IO7)MwI!j;bdc-~*U`g5D>ea$5pM_7f9u*%yE8ftTWqqzj* z2y47>Sz~VCi~Bd&TsUPXMlg=BiX34TU2xejn`?yT5{x6P32`opJ+Swg!#39>%_SH| z?{}ea@f!t}^w6d@KWbjv0^0@_+gx{RF2Oi*j5`u`Si6dbylQhbYA(Sz!n(*2)?E#~UbDG&X)eJy!n)WI z))%!^b8W6;noBT_u%-x?)%%_NNbm-mt5 z%j*4hthxEH&2_Qn5{x6P%N$|-_3R}FY_1y3B^XCoQ{!B)7~h^+*umzyS#t@-QR^-j zF6&Exv-_>av<{t`W2Se7VBW)jtFOB}Uh96TC12jG)|CjC)z>vlI0&`yx_KH6noBT_ zR7?{ttJeKxaHNmT^{(a;j3dXUJHndOuBf}sby#x=#u3&G;j(H%#VPB~w7I$_!xKg@ zj<8DMYS)A=&!6yLHrGJSB^XCoWx~aA)D(% z%_SH|Sk>{cU@62xWT3(Dy!hAxRESOZtTZx;Tu+$u7Y zUT9u|R}1DX{I^Q5CSHP>I;SCxxc2FLw%c4`%_SH|N*4*2ZUC|iYIBun zF2Oi1&1Nc`mu4>(ITP^TX_i1nqIz9@Yp=se-;$f?X6rrG48zkCoYY;z4kx)NB^@_q z#}%g9muK5f3YCD-LEA0~3NCfXi7pzR;3S+{t)h~Gm(1n!E#-JxMz)TZ)6cqaxn;f) zt?+sKC8p3Bnj@(WF9}~OGSd+rssgqgRZLxuDySh|NS9+mq%4VvvC(c44NIAljt8zV zXX(XVRYcsbN`96n*6o@Qm$=l#$XJeEN?dfLMy7jus<^e_se(m4@X!sTYibLgiW8;X zGG_~(iW8aDGG_~(I+MKkti1B@O9&@^)ZQ!0Y)_9Yvpqes%=T2Ajx4i1J+jR9RGf}1 zvpp3jdKNo*wx{B3!LwPG*?i5jEbixV|4%~D_IXsVY)tU=$j1ac1YgCAUc=7J1YgD5l5ex@OyF#upSEX0Sjc33{KG5v5_~;!FTvL%_Y!SMj=Qo0THP+mdgy+)I$#JojwR<{xY8tQ(f@;icl>>7^o&)iRf-m*VmW zNyoXlPoj(CLscE`5snx*5mxs9JsHFQu8h_Y&C}$Jg-6mH0O=vFET3CaHLrTs9NZFC zJ$*)Hxw@=sdL=HTDdA^r+O^r&ZaN#X)0_LKnpEYU%7fd$6D4Zk)F3Q{siF`0=JJZ&0)BC<`usvaQ*r~ z;pAxolQnHi@p~4S7d5V>_yr;6Lyb`qbvhEhvY>k=p7uf7Y~vNbgYX^^#1|833dhx$ z#Lp#fEZmEL`H{vkeqQo|Nbhfe`Qz!W%ljPOO~8ECSK+uT;3bb=C$~+DL(8-+1js_+ku7|t`Fc-RUE_rOaRlt~ToQJ#zfO*`FbID_R zUkBzxH_k&|TQoX3*OizKmpsbWL(^-t%l`|!-uKuyN*;L^V;G3Nd>s$wKp7j zr)Y}0I(SqloOpMzb@OmX+c$qaZXGQsnmB1fC@*64(d?aUz}Q6p9@@XV?LVnFR2;$G zvMSu($|J9+a6-}e2yRQwE1EpM7^>uycbf7JUx@gQ4@agTUCCXq>Wa)O88sQVAoKR) z7H>0l-8ssiLFT)<0Q7(GuH*mQW~?q}3+CSBfP%T}Q)Pl>8syis-o3R~UZ?79+~ zw-euKdH%n2n=$Kg8tU=?HTM>K7w(Bj2D_uNP^Dgs8;y&jMe0Unk1LMVi;EOhbzy%d8NG9Qx)w;c022*f7J)IQ@1C5>=La)4eku%CUI4f{x(H#zTM13NWLF{s%midoi8~ zc=%y7w+iUT9WLUrIy2_r;YUnZxrofZpbRS)&xLr<9m{>we^WXL=%m#jX$YvyY|T)Qdm7;{0fHu>bL&i4A;iz_qR#%w{1&B3BLc2y*Gi6 zsyg4t?=TYx0ZalYsHg)*jfw~aFf5h~2{Msj!lIyJLkK~lNMbTkkZoXyX1*heTh(eS zt!u5;eMM~$OrUi^w5@xob%CN*tqZv2|2*$GckVJb5zudc{r&zupSkm%d(QK|XJ78Q z=e}pD0}O{w_^dZOt!Musq0YS~S9BS0e(#|xuJ~2@;p6UGzyFjMKhDXUUAMAp#sPi$ z9(d3ZM;?`X^fAMRk2oQJzSi4jRAU!i9@2 zimhtA_>!jh|6F<1)z|#&+Uu_W`LA!j<<{G7zvDM|-v7XZ4?X5 z7n;sUKz1Ol|B%i-LzBByoZoA}&=u*u$6fKO`_^|oJa5X!`_Ha>G2?)oVShW~6DC1Y zuxANaxlbubCLkGqDiMk;%9$hQ1tzs{4W=rP+)!dixbmyw1e9358o>cVJ}AXt>q~@k zN)p+j_&6xWfV!Z@HfYXh6U`ZZsL}zbKS1GxKfVwEKfZ&HE%|zu!Q(TuO38T9*R!BO zq$H5&Al3k2n=`=9Hh` zP_ZDQU;6RvLG~veCY`-Vs!kqiF`NN-1Xro=!g`w=SQa1WqIjso&c=UeU z4+C8XIvlhW6#aDc@1R)Cj8gH}7|?;ZXCJDR0MM2pO8b=CXWEw|kb31N7W{F%P)Y!l z4VjEgpqsB>SEFAf&FC|yv(XdEvwHA=^_4965Aq##AL_KARzC3$)OV<9`8cJ{cMZiu zs?Litn}+UIjV_$UCWF)2aq4(p8}-%XmaI-g@J8qf*6)(U3!x`j#YT4AMOoJa#j*9BCXIfY_1yQ}lKbdf(DY~&fy5T) z%!%Ms7r$>L<4_#!F@M8JNQG*T9EZE$3dks}Y-xz1^38&c zB^@yOByFs*pWyl$*NLtc%$K0_uLJ!Vrzpxu3&#G?ayE~OIyU6_)saOAq-PcfYY&4^ z*@z3^Wml}lCK-lXJ590-UO`-?K39`G(&(OjbuvPj@|IW5tE)M$dO^hkv|Qb>pfkux z!Od?-MI}}9*(1-i2X*?{%4jB_#W6oHvxvS1idj(fT43ga5;FjoYKgREP&bU^cQ-jY zf;pcddd^uc-HaXhr!50dYbGyWrzl={@SL)wLGPhktg=yBuDJQid*E1$G-Jlb&c@V8 zH?-UgwA`+$<)T6~ZeG6MqfN-I$0+XlFL!Tvl-;4@*UqysFie&N zd$F0?y#_f>>-nIJ?_y9!CyF2Em35%(*_ML#*Y3>Mi*SDwDDg}~6hD?6`eI#jv?)a@ z%I#9^n_)C=ElT`h`2mtoA(fY*FLx)lupAAQrCXL|79}=?n5o)5_SMj(|5RCPfe!=& zV-t`$wz9DeD;v|p7Wpe&BU~-=WVq3c$K}-`&3t526kzHfGM!D4d2eruEDy3c%Yy@B zU$_QwrL;n6H)?#hmlxycF0cQQtj0DHP|k`j2c_IKpe!f4Gr#H1@}@h+J#pt4N_VE2 z?kul7T&ktfrWD*Nwz~A5G2rnGc6> zBJKKs{}tH2De`Xu`L@X44Dy|SOL6QUzJ@o(tqybw`PchjiGA%`lD^_=1NC}Y&!iSL zR&k|2EwNuo<%Z(K%Mh3?(JM(D%CR75(|pP!V?!;mY{=leEO!I;0f?5efbj>|N^n^- zwA*nv%%wT;Q$ax4CFu3&AhhA+%(fw`<8z@|msn!%y2QTpAjmBB&BL^;Hd2S@K{Wt0 zWy#E}I#Q2ETh;$7C+MM;$(GC*7n-pFWjtAjKj=VE#$VMi+A^r`OS?5|TZTOG zGH#|JQq8KAEgkoK5~oH)*f%1+P)lk+EvcbZpAtdS8<*ngo3!S78xh#)@{YuoRLyT(oLcw6n*eL`&1b zjIg2mc6A%0b2xF85NAW=%nud1Wc3k*KFL~~__7#hx$zb%QHv5UgyWs)!1#m{&xO$v zG1Xj^g9>D@5&lJHUgO}@pFGm|K9<{Wp%M@+Q0zFb0rqCG!`kNG5{~W8TDA#oF(c$} z_J2J3b2P>8%%-Rx%Q7TPK9D66QQ9#Tg(<0Qu{FsX=o4yM$0isaxo$1)8gQV3`Q#R( z1NceIgeATV^Ryt9C>%J!^McGYA<<1C1o#}1u6h;DEPp`yq_6q@^hq>5(?=gGeNDJ? zq>m0rAIX1m`Xrj3=~D^7;fPiu?{FuQ4oDRVMDRG71$Nd6OSDvZxyQ(>+Uz*j!4>u zC2a*s+r*^pO4!)11&m+9rqaRjjWfaXk)GkMvAY>4`tziaaoMma!)GCD?5>wdc&_Q0 zLcIp>L-5S>i{xYgV{&;#WqI&3vHRkJP)EQy2EY0c7M!J^N=q=PlemJpwEEv zz6-FsK}Unq{Z@TX{h@f?jvkEqLia{c-ao7F*CCwma6b@oCgW1`5ZW^ML?iXRo3TRM zl(uHp?QX_e`6uov*w{k48Bc3lhVd3`Y|Gt@x3w*U;YhvfW>AYNYhZ>bTxX5$W>BXz zZ5c)gHn!z%#&~VZFlNEVyy#}k(Kb9e!KUKOHmc&h0O?`gnTD=vo}_H)xSuX=awawB zNH9msznYCG9K%vJ#OpGRgGly4d@*=Gr|zk&9m=U|jQNV7PlDt^w#s)dUvhG7~n z`IYd*+$+1Ykq!A7h<_U9c=j+DUrVyGaUQ0^up=3cR~QN@YV-Acj$Aa%J;mWniOL@$ zOeF1IvK7*o?KiS9cQog8w$(n483@dCBV7i&w4FD`3|v4b~SV*N-mFQG;x zJ#|W4`ZyyH_Wz*`PhN#H6x7#RSVCyt=2nBWwSa4@Al!*(#KT$faPK&D)~f>_u<#{M zI*OlRke|ihYD`Jt&f9F`FPza@Fl&Nf=BW_os}O4A;Rw~sB1)~%W&p+!6y1b>!O7{f z0&Us?w|LXb^8X6{J!8cTuwo@53UDHcq=_UoR?5>JtJVT;lteCY@B>*$V#QDr>=DCO zIj&wEH5kU^w ztk zn$9YU7j;_OTGZ(d$&R8Z zpbvvy1NsQ)U$y@`pikg_f7D<+y+=;~eF_wZgBiaE<*b=_ zO}2v8fNlbffc^pWLQrU4kFElJ4wN(8=Ruo6UjY3UlyW;Ep)Y|R3d;L|h<^hvHCv)B zL-sqY6u0y7Pg{n(8CfB2tdX>3$XUBlaa)al+A`#5Yu3tcTw{{@nZeZ~sh`kru5B4| z3^i+NH{rKax_g07FFYwjbr;_ar5;|GkRiX zA@AeHVW|Y?jJC>#f%xP=Jk$^OIL|oLJ01##SBG+n;>CTFEBVckfEsJoXxyn?cch2o zx+ytTHs)5($Aq72_zU)M0sjz)E%lLsi+q`=!Kl1?8M(4r95~a7;41Y^trv%&BQEbryWa(t(LUaiXIA0yjk z?RB0lHcSKaozDU@wfl$2S6V*?Wxjt3+7A@xBSeFspMkQxJ_pSO{Q{J&^-EBe-EL6k z$yeH)ZBUgDZ5akjMY+A9Z5hV+ysfdX0-?my%kvwz#MJb`QCZp6sD6wK`A{$V^$69SG}zC%JGK!`>|(E@&+%Vk%k-!pglw-OW^Y zv&IT)PHVwDsdQ^Ni>HAiBU?Put98u_(wQo^kb8GY!-1u=VJ1D$*4cqkGHAV3ZOjrY< z*m`8pc3;Ck<4w%&c+&^?Z;gJ2e-#*Wy*2uczHg1vSp|^=8!@d>4zMZ$oG{TX-o(cP z^_;=`)+jSu+4x+cY|M7WH%7a~n+jlSjTR;ESp=vvUvypmrTOcTK#EbxA!lt4HK`*sMv!j(%y$8-g9G z`!^fDwSXCf>eN@&FY+-9HQ&p^H_#peIHWoh^kq_2NGTkHT^u?L$(#ZzC`O1uI_hw? zFi%d@4dyWBh@=0u+6$_~$0|Qs3s{VZ0LEPAhr~3OZ1%8KemJpKet@$#@gFn)3ON z`Rsi(Xc_1+pr?XDqkMEa=s?h)f{p;K1sw%?9cTgQ-Jpe_PwM*?eb2TFE%8wd@#1fw z_<4UEXc=e~=wwj#&Qn2gvaK--bQ|b&&}rx%W`JG_dOGM+pl5=928t7VqjQk3pMu^7 zN~rPl6EiI3h6r_%{V|F64a@e`naXa z&={=U#df7-Uc!$<^ifNRt5;B3*#BbN+uy$jj;mvZWhhN^ZEx?E?_xZZX-`8z98*J~ zV{(ZQwFI3>caqcvD&^@l7XG-)X?v9>Rv*XWD3=K7_*qjHmG|n!WRFE zhWU|l+Zq%1`2+#?Hm(IS=W5ppuGOs(uKQuG`#jhEP|wvcbJ45G79*yK;~Zc4F4692 z=~1S$8uVz;b3x;v_`olEIp_k=v%tgqO3(->KhEPl#vbEB&_c*v2pR^xi2k7TpANbd zlzGT|jx${PQR5748S=pl%e0%6Cv6!LH8P9+~C|Sk(BYY#eDG5;ya-H*S+N zAG`|qil^P@E$ri-VellCcrSHq@hro!nOgROhp`z* z?EuH#@8qs;Jepe@tMOoP?&fyBa@c>xSKK$gJRKAyfQYaA82<%L>kL$O5Uvt}@cr(xE-f)q9Hfo_*7;$LuM5aOXOr=DTu6?u zVvT@XyU>0ppsa?I^G* z-{G*a!UPOHZ7JJY*d~h`W{Xm%1MpXUTn*?6t_`u&>p}mqpzc17Thw(ww=WwZWTwq! z$0l5+VR%8r(cb^`K)=8^U>BHdKJE#64DOLr(IKEXX)JmYXn)XazW)m!` zA5gY*+_#FG@8UG$V%x$pQ}Um9`Xe>aIgMTS9J@TfkJ{&GZi;P~p=|tTif9BQHZESF z?%G@~q6_lN!rTUjz7Cfc;X-{(7KXh{fx~4Wq~iI;hM57ET8B#vE;!KJhPe+egOe_H zU3rW<&JBV;en$Tp-{Ap|Hv3t9?2Y_#>Yka>fGmr{*}#&x7|uMP#oMOEh9jn>wcnR@ zWrM|qgA+YgT7863}wuK`&TbSoRYm7_s5WQ5%NNH)+H5J!1;(+cqsxtdV}- zjR={cF1+_&c%)=B>?!Rkm@u4)ror}BW#Ln%m~_LP(hRs;Db2WZ29)KSTzIAwBN#_Y zS>61;p!nj&)7Y#n7MFP@nP8Z%JhpQh#><(m?r`z@2GbMfoof&NM{2ryz{l@nuWgnf z4ml?r=I1(w-Br45ImSN7?>m|QxSB5+{d}tAOu+<^W2R)x+~7uYkCwb&ie!#6ejocj zLMrE%A`pmhlts2+xOQer&Pqyd){?Uz*{P$yr*KK0z_#Ja!1Wf_3z|zXjgI5mq1JGVAh-BcI8%xW;QP!3h6M?P5rIK}UaO?II;vx!7A%UyPF4#hhx3tFLZOf^me^ zU%1RXysXpe$1JWPnoBT_um(87TDoZDdluKpnoBT_untdh!D3u^{->{6Tosy2F!VMS zX&2g^XGP?|1!on*pS8Tp#!8Q#b!mYIubamy!y{R?nsO4 zdd(#mN4ky@F7|IU-_^cTXmLHLxdg*r{RCq8Or8VUnJ)Qs;f98!%SgJs`I*XcU*db?3s>@1r}-qUTSoN^RY2_h@m5 z2ZV~rP3Gzr?UajLb)F4;jBrUZVJrXrgYTtEK2|UVHp#~%CBLC1ACn@PGgrTFA^vH8 zU322gsgjR_55`KH4bohKakNvGwiVWuW$!<1ag}N= z!8pR=dcM`K4jOjE#THks<`Rq}tYMC@zB=RAg%;NpnoBT_usCh zp@knYS}xMJu#F}$Lk7c*Yk_o;9$?5|>0L~Wy$2XYjE_%v>{ss`df~gNc{o}ye4^JC z9G~;*OfZhp=^B-ihhr2M|8ZUU?u~fmZ*q;)T!L}r;fca!mQ}`vTkf*Brf4p~Fb{|8 zs)6`O-LUDxq842j{8%C4xpx3TeLbrYr%U47SZ-^F1|WTb;%Dm2_wrQI()q zp5u0}oL5o30B1nC-Q~eOXIP56!l$|`yjzM+ip$xSU)HBXhO2@bI?5w(q=NGkBYpIb zhlh&9@b)-7Jj`Ua6UMMqQHo^Rw@>6ua6SCf4LuF;$CFcMa$;^K#k+sKj>wP?<3F`y_M#P!igWfg|my zNf17dmr(ZX^zycg_3&5Gv9J5u1+wUp3&J^eQ4SxRxsg9OXqoRjb7S~$6V5X?ddZm^ zf5lKJLp+8tuQNCJfuO^9oVl?J3u&WWxB{NJVOs;DjPbbgT&ttOtg>15l{4brz_k## zXnMI_0aLAU9mVewjd8@!HeaKA8LrFSxPQOy@|yE1YO8+)-R1R|RD0;u z-Bab;Kd!dz{h(7fi2R*hQ!~E`d-B^+s7>b=Pz2KdRn^ti)Rmuib{*F9(z7?3&gQ-| z@nHgwh0n=TLzBuvQ=o<&4_fKjYv?qtq_lA26sSyR;QbN!g&0oi$|I614-zr?)DRSy zPa9W)ZN%x>mU8P%+yyaH7pas$)zz1RBQme9s$vdKdVIHLa>LYaxl@STj5ASm2 zgCM9Y`4G6AgE98J^J*59^P>XBgNJ!vPyv-w^%2p7ehonvRM$ny>nrN&Di$Sy%qaot3 zB20(K+GM6MN3csCh$tS`@PkIE|LRG;674X{*Pfo_Bh&LH#6B7suYI-VtpV>nRQ+E) z$)jdU3$HjYh*@M+eK2=n{)nSzo>yI2S5sdzHxj&{x*m$!g3#&-4Z*?unHN;ftX@z# zzhO?*%=(J?KTu`xfAu6Y&u7-w51q+A__z_XkE^e%oOzD)#Xm4_=U3zW*!mwR1U)X4 zvMC`_KT_k09+xBNzgthT-lUocrDOL|xUo5M+~e#5+seYx#X%#|x3w^56Yj&UF)jzv z$WFWsaG#UB;aukvT=Q@ZcI^@2{FqBnV{sjZj#nEQD=TK#)J5b=x1i~sLd|X19GCD_ zru5e4-n3aZG{XrZid@y4rrj}ji!$s1pglpc;wK+wVx>D8#Qh*pzHh+FuBflV+Fz6_ zlvqNHGQPYY2uhi1&j)R4f0=TNYTpb{^(-J3{4uF&&xf*crI6D|DEY*fJ)MVk8k~~# zz1zyl#^=3W5FtWn*Gk?hHQ(8OHF7L7Cxr-xTHR+KHfiO;-XM1f2wWq;^MPh&$se-GMphPy_Eq^t*`~>bMdh2av7)M%a1I?~I^VFpO7acctz7w5 z4~Nkm-?GEEo3+y)@!{-35(}j?XTwu(-@8Y{58QZm>Ubz96!=Shr~eBQL(pmm5rl z^Tihv?f02IM%U;U<5JVbGW7el;onR}mt?wF$~0XJce*$fSm~N`M*8IzS4eo&5Q3Mz zwnZGaL}$7zu2VIaVC1EZc90F7&UA6@$?r2;^oU#T-JF^($#Y*bkY>8NCDVmAAf{VN zx_ZFfO4osh52?1eR%kB4IMT)S87p1fR%3D9q`3scbg{vRVJe*IlEE^Wu7v}h{W3LO zGPF9<1yvDR;!~PtrlczyKF)MmTrX=b!8p>ze#4nAi|Z53B^XD#mu1lWFVHQ$^Z6 z?Qu&viTd~%$FOFbvl#|8Bv;#Bg9Bf1;+y8J(0ddi^mtL0dSYW2RaUSv-fLYaLI%*&DfQe|FA6T#U!6E%hjiEdmuln~7 zg!^;gR^=*8ClIgr@iF*1VA79KxQ^mC7??2{*IxYCKF$E<95>FRJeq*H+KqFS2j$%l z%+qe1hrDgTeBj2pM ztwm!PKN_#{eHrDp6}a0tn}_L)%d32!1@3KNes{dUI;?+x2Ig&zOXiC!ek>23GGaGg z@#Dlb%Z2lbUo&ta;Cy6&>8So44UDGeN5G|L?HgW;K0#~5t>FtfbY`=BDygmH;lq$SmtFM}QPUU$O^^vN&ANC^g z6NLFswC{rqb-Hh+bt>?r!c)tq7N0R5=j|xJY|F1~%J{}B^Xolrit za7uC6w4~hLmN#GIl@y;cA<4SG&95+Yipgq9Zs$DW19iXy6!-W^Wz$YCFP;>dU`6;? zd|G(QshDLd4;(m6kHRUTQzn)djh{MA3Wh8=c$z*_L#K@| z51mpZy#GCexxF{aJi_?*$TfKklbud@g}dN_syZ|#d2{S~-OTstkDGX$?{i^A-5jWC zRxgG3`aLvXfZvJ2KW`CV9M_hsMlA22A20){gexi$Vue-c`STGi=i6)V(|iAWG&7GY z=B@@dE*w9NHdr26R9hvl<%4Wk()FagZRgwc1;~5xRz1k~y?|#aHk!r79dYIIvSp9n z%O3>ZyD?Pj`gdM!&4MbNFDC*zkn1{Pok)*knZ1(VPLaA>MV5(iQ zqf-NOyr_86_)}z{VD&uA%raJesun8O`z!w4M?L>{55r!a^}KXPOTqOE^Oh{lIB8>i z!--L7fyXmnmM`_J=R+~~^E&H!oVa_R^*opJMNE9!ecQWWZnb_Pyzd(aB6F~z@&~?} zuB?kd$Pa$O{og$d`?U2VGUxxPv!34nGdWiCEs`oGztDv`s zBMzwyCsl&CWyKbk?5WOhIS?)HL(!c%@?2BV=HeNxv0OZv;%BtR25MX4^JTMeG-db1 zgl`&~mu1Cv1(tV9bb%E*$^$&POlv~oGpIx~QTk0n3X!m+Y0V}$fF~Xs zjF5N??qGROe-7@rC>k(UCT-UyZFePYTaq>|L41PiTwHFgv0S#NKbMDWDom;uR7a|D zatXGkH`F4yo>{p7c^mVEzFn7iQhmu58xO+@;^G^EjoN*%q25gAgXX|(BxoKeKG%|y z)P4e5f%^%dXM=`8xfC-Iv4EmLEi+$V|?^)pr?ZF0zC~h17Xep?F)JaC{&#A z-0)}_C}c(#fSv<-G3Wx&8$izoy%)3|bOY#O&>f&lKnFrD--y_^#6**BtF$e{mYod(L5j(ffz;|XmTdZ7k|=0W*apVlcHmoStKGfX@nl7lG9H;wXVNh%vA71~r&j0#tN&K#yDA+?!GJA_g{+1EV zytF4KG+}t%E0KCIXQ9w1a%w?~D+lH@eu!S_+rY8`$zF+#6gTmCND;bIo-@FE9K-!# zIPqOc;#=tomrV;LB2NSwzgU>Y{s@P6>rPE&h`&hj<0!bswq=KfMh|;pc?XzSt1mqI z+a-5J*D<|DC{dErySNhhG#;9R`;F%rj`5P5VCE{;_1NyQ7alZv_mTr*Z3RoSL$U8N zF6=hG@tuX8L$Pl%mK~Ce2_6m@@nlROG}ySg;qb<`NT@^5&H=G+eUXj@O=@flSH2id z{4*S%mQ#><+1ZE~&H=~4-#nK%4#o1KLYA6p)fKKZ!t1xCH*OBEjs(gghsSzVVC5xOUlg9#u5@XEACn6xLFGc)0R}=o78CvByv9Wn_l)M+0 z`@A#0oMm%9hiJ}#l)+b~)pIH$RZy;8S6!=iaxx?jgIb+ojLK#wSnBg(MI$?VE$sF& zlgHh%7~jDz3ZB1VE+W)pB>@YD>J<80PytJQ^RY@?jxS8I&rnUIuLd{S)X_+I=nPUvPgr=&PW2 zfxZU%4Cw2it)Q4SM0v*6Tc96-ZUa3Mo&7tYREzZ1om4@xCCJ3#rN{7%rNpdWz# z67)mRJ3yIV_koiCVSWE0DDp7cIe;$(K(j%=20Z}u8_*L#G1-oe1V!FPCxD`sM5&_{ z8uOwnLDN77!n;2%`yR)QNjH`jeKQP(!#ZFZx~iFnvZdqxC~@OG%_)i)WU?^I)*WtR zarq6VgR)Jd{GB|<36egPiCh-r#8`4!L;ZrHY}0tj%@bt*zMYM}pPk~%dZ*NvKJ7H0 zJ&Y_M6es5~%GMV)6^0!NNA2&7mqPZxC}3Rla+xoE<76L^X5KI#lvHO(DsSva+7;3% zUm*`XCEYkBGR2oOXSy#q>{MTdZ>ogD&Vey6z~wj8_UMwt3eI~lQJU1)oVjYX*jKCt zK3rKguw-@jt$AAu6M?4qieYdo9ND{R*{G7$SLEZSboI<8OR4#q;!3~h|9?6?yt;b< z&!)h9CoSxsIHNdz@~*K%_=N>Q-(jmOq#YrlAm`b+2NV!8OKpJO=k);GLLp9H^}eug9CWN_@t} z<=)zgx{C9v@WwzXYzzYJZQ6U{`4sSG8w;^JWZpmwLeM#cjhh-C|IZ_r%aL&2r! zKR*zZ@u%L#<)BbGAN?QDLqM+qJrr~;=wQ&>KrzpY-UWIj=!>97fxZli$JXfI_5H`7 z)bGem%g2IJnI;}zqy0gVA5riagFu-#l*?`=j7xPhw5ct@%I#9^i`ojqG@6F~s+&=^ zblkJ?SbP4tRFROXst#-B2^u(e4Ar}#234K40lU)^1^wbHX21?xFur1@*uvd;_vI&{ z)&f=_1C(&1aVu=p;YpVQ2ANs(BCJJp%KIV|FT=+hvv9-v_yco5b{vmCa~UDmS$U;) zde>iB3P{*i0%Q$9J+#MTjPG^?fiOotz!=73jClM3hMjrY6Yx=o!LR-;<1HtQtSL!M zk^~p0k57cUuMS|)W2$$B;>E*4@lZi15$ZQS9?H+WXE#!w2n9p&MPnMbGKKNUMaZfz zKSug9i?-l4oRDO$?%pM~JHxg*lF5+exuXrsJe2~%j5PjWjCm1LdDGao{2f^wc_w|d z#6I)VS$rf?3RbZUkw|1Q);xfuar3f1nfD}^U_44;9c5Ey$@+M#yZD>S6d2z1GR3x} z&1|3Z;o?3Ho(f2^-f-(p3d?P1> zECA&~#QC6*Y1Dz94q6X-7U%__=Yn1cx)gLF=nBw9puYg6JbtPKHk-gt?_8Izv%;LU|^VcCWZAq%YHNWZI5IWsg~)4<>qSEwUB8W}*~N z;+d=7hM?FEU!-4bw=Xg&`LH?^&eHOCu&qMtvh+_TjjiK&YBVg5t>ZvyL@tPmwq~Q@ zyx4>sU+aV*X2V8QR5u$9I2qo_j_!tSRkYK$WtAjucocV!lLg37Td&yifks0Qpqk+h zr?xVDVrSiCwM^)1>}VFa2)dtYp}hnN5Kk#735bf0X`=x>cx;mngb`sgP;tP`y||G$ zB1*u$V&Y(D^fMp63KMLJpP2@n?X^7D_b8{Mkdj%t1)LCchfR>ql+3G}nv4~PjD^3HNrL1c^N4BKLcv-N$aXG!Ko_8ZU?nxWgk~{1U0eHio`&__TG#2Ixq zng;rF&>o;z`i<@ndLt-iS_XRB=rN$b1jPtp+yr_O=&wMhfc_e^3iMXcDCljVmxJC8 z3K@L(j@}LW7f__pK=nf-!^0@(3!txq4n%w|z@>U=+LTsp<<_Kq)ohD-Z5sNkURv4G zalb^|eEX#t`=QtCIxJldR5rh~T(K7H=rvjj`hu)z#vNKE>Naht>oTP;ZmY~PtJgUY zhvP@HL6T+&Y@KoC;<8sS?#!rnBl)hfSqV4#*WT&jjW9 zf3rcc1{CFB%k%%(MG&_XlsK02rMOf%)25n^a$`)D8!QInY8tw#a#l8$^OfS}>z8Kq zL(|F9O~?FZmW7S=Tg-klAO2M49x@UatsZwg8WdLN(RvcQ!tt2YhSloDN4!f|*;*zX zi0U!{54PH4Le_T1B^;A86O2d(_{C*swt7{8=UmQMS#k6lYs5S~A#ZEJsxM?B9_f|& zu$-vy#VZGIj;-$$FAeVW$EOG5(+9?<=j6-C7C9&(lKjo_2^c7KjZ??MDIdOC%ujmq zQ{a4r%049^OQS2qHW~lStN>r3$?Kqi9O2ks+{{XO1@7D*4}UHQSuith%*Kr}=kOh4 zIk&}e$E&$9ZXez?a@~|M4&o~HMe1;rX=Tlvs`8oz^A{QNB2slMn^d^+&o~8x0lEkjM-R(bH42nDG#Zp+)lWcg z0xbZ&7qkfUe$bOZ9|8@7J_?G{6)=;*zADfSpc6s=2#Ql;ErSb>+U+iF%P<%|(`uSKVNn%d+0t?U3vsi*g6yH;^i{a-Nm~|dzrp2)ejAL3 zxJ=_E`(}9J6=ctV93O1Hf;8njr7C`Q=}JE3nn>Ec~O4)JzxEJ%Dom>Pm!X+ zbbg%60p8N=+wZ!@42$b%%_SH|SX~@pUH!~v%_SJeho!7#>Qo0#xlfHh59R98 zP2z64<`Rq}tggbvOeNP@uRJlu;^M5BMlg=BGT>@y5&p}|ndKH&OnBImluX08Uc0bw zacUOtCUUsM&d^64H~qlW@{+juZs}x|m-Qj=?OJj-NOqPNYrIun;WKvbZ*e`Mxdh`# z7YATV>vP_yf<}vLi{=uHBM&njVO>?cYpKPxLvsnn5f*y@E3EK4b)zjVnd!h^FpjX; z@muM7VO_6)#dR?1G>u>!VX=n#ef{{4>ztSREwH$TX)eJy!s;blX5F}Dzav&!T$41H zU>sqw=dtQxbi!+4iwmnQVg%y|Ykx;rf8Ek&jK#HFa|y-~7RMcxE<$Dv=yjIG^)t;S z7zy=v+C|kvI{iNB!cPup@MNV8>nhG?z=E0G#opWWfrsChr#a4=dwDRm_VTIC@8ffx z*|+pbw#prvvyTyU)m}6MaG5!OO!@G;EiN5VQ6l2(Z4MGHws9Kjz_z#!RmsC=9FXid zvxTd7ejnGZ2+0`r)2~xgAvH%dd7G&?IGKtQwd8|SQgMh#Hd8S(^PNX6t`f~97)P1% zA;fAI1-mYsWpT~XT!L}bpTitseK>OSjTYAu%_SH|SV2cv@753KZ*g6%xdh_~tG^?x z7r*(o#Ny(sQ5wNG!WsZqt6gLtKlRTR*GA1H7)Mx#3zwOPU9WGr&f)Qb)LNG-7_3Po+s;wRS~pTlKFSEX+78E6tL;pw59U~0Cu=UjI8t$p zaIwFo*}DDM7c8#XnoBT_R2&Pe-~5Eq`1*tqZ>OeWpkSKuZ?>Idlc`v&B_ErTisOXK zEcd@pJ-gWAGS3DSj3X6;gv;IoSX?*iums~s#qq+m68|(UXJ6Hnnu@{jL9W`$;`n4L z_?n*P_>@!(fvZ&(x34@j+v3`&xdh`##Zcig%cAC{zH2S6w=|bv9I40?F3!?9>#6T+XK6 zbeFSy;hK}@jZSe^XqO1BQpD+c&YbEC%Ij(x7R)KfW?uKEB^}9;IVm10njRi1==}CL zJUkS~3GH!scqoox?QwW`D2|j==qz!&mzPhN8m?F{2Vde9&a0|C*C@wk=gNk<>IgsL zt2wv2%HcwY>E6zs0iBWU`RaJIxSdA)pe*dAW( ztYm3f(1XwBn7Y!Xk1lB6U*#dR;CIO1zQ5vck6Wjw9q$b2AIi%MTIT!o59N(GVdzkS zQ~%JlqJOA#uDt1CHwqO{b=YWgL6zL#k7M^;d=Rl45B)=PFnqlZ+}Ioi(I;=nZh`7vP-bX^jy^ z6X(*C&soYJTsW`zZ33^^@fcW#uzXiy!A{Wjp|B8@*_v6vv3r_T5I?BI8F}XZOPc++$ zAM-B^%nUcqBfS>@v(k-o!(3UOFC{`tiXDrla(Z0_G$)&O_cD zjZqT4>mS2e=)!r`zgvJ?4BTOSM1x7zKi7D~b1F-+_=%@EJ~6VLB?`UBCp26%OJ(=g%zP z0l*A(<2=$^2Fy%1&Xr!4$3?(g=Eix*y9<~{-8h##=HH(+239d%`8NUyeA|Wd%D;ig zzrK?&mpDbq>L~x_1G7-$+RMLmi20euD2d+fw->_wr3>d3zg-Y=Un$r0)+D2d+n zF0;bdHN?sD@k=`IM1Kl`}{5u(#pSp1#@|FP8CFeG$c=N!WBJb37!im+ul9@Ae#Qde&O1|~_%_h1eQ-YX z8(^NBsc;>Y@8`hy&QiE!I$ZH%`#21k292dybFQ3#EtWicPlXWxp6Le zEZ-M^dEbrmkeBvT?D@b&(_VU6zQ+So=*D@-s{rOaH_jD5=3hc%7%q)h`7VI_4KAEl z`926-*K+8w#zoUn`MwLxCmPpYdf7i`&Y~pCc*T$XMxR;O>RX|3l;;({0B~0TbIojp z>nMIt0<&4;+KV6a?|optbmKhAWB*F*C%{G1o;=oXw0JFl4bCqvD$h!%c zb#9!8yjOvF*Nt<@V}IbEgFl<`DvyQm&jjugjqQSaukv^W?#}^pYn2ih0BLXi`8i-- z)i}T41{c_m(4Yj?moGJj_cRhe5B;`nZruL~{kC=I{uugg-$Z{){j4XTK0;M$;nece z3uhPBVGEgZOVe(J6OF@+9@*V{shrUo8W&VV8tS0lsHScX6me1+E7dOcP+DNeg^J2c z#-B1_S~#gY_8{d0MYhw*r=B{sZ2T!j_;^rpc`BqeJ%^b}XUo+Qj-hcl7}C@_J0j_+ zkF*qDQ)}-e9Afo3`sgXtsL<2 zhGyBU97bZVzLK#K4n^T<$@^CXP@KGf75C#yt^3!+e`?bIb@ETP_}}FHl;UK7+i)K$ zE5mtcI>3*V!;oR3kkzGJ^51p9DRpTw2Tv{=KcRe5Xv)O#Q$!JKHtNU8g{9+9Lb;}A zZ^f;s^5l^r)u=7iI1H3$n(pC=s62UeqbZ{j?~SYGnj74y`IX8$_v*mZ|Fi0CnVSFq z>9M^JwFC-%&#PdERem8h2B73vO)pOttWDSN9-k7+GiFDkvpKoEsBl{Or18_J;MS~G z|JN$B_10e8fj(Pz8)U|M=J-BnwEfW()iPE0IH~~;1ZJwJw?|G1RvK^V%!n>FtA?}I zIFI0^9^xRoo6^E*IydnWHCd!^5|?}vBZa`Cm{pFRHf6W)5K*Qvk$uRh!V zp2@pc#}G$wGVu>oCS3pjoIYEbt^b?#*{(z9$kn=T#_zQ)BdHB3gl`yMElwCsS;aBK zR~#!yZ)-Rx)K=DaRkKZ9+(F!L^I5S-yJOuU%J|fP z@;jgNK@R|}13d(^9`p!M2#+$(7k~}~?TSl%4MP{3FLj^D}F<6wC!05B&MRsIu$hGlhaO6csnj#DV1q}#^FD(b*4rPN0;Qhc96 zc)l3|D8pviF?{Af4dNK({Zi0zpvypEHEj!$OaKZS5-#J z#xi2{rqWntSW9RavV~DLu3j98OMR_L*{1Q58-yq1rgbvX@Ch`HDVw2M5|s^;SS{O* zq}@xliiP@8Q)wmOr`08iVpX@G53D%h3$5RkuD+{oGKyn9wC_-Qn^ZS8^2zO1mLI2z zv8dctEDkqjEQ&Ctdl<_8LFo$1g|~-kr;4%DU|ovfk`AJw%HBoTs~N+0SF=V`C&uYw z&|=U_Kv#h_fwG$M;|^8LXv;9JPP$#EZ5akvy(rr>@i&iBV`) zvl9hPlwMI2yq8>dTh3}`%4VpRL}g<&Q?e=0MAGghTOnQ53?J@`>YNC){Z@WTwWfoi z^z@Ti=*A{BzSE#J5RZUJhX&#$IWzLw9zz?4bE{HP$N$iZF-2`g=7im0|N3xjSHY4G zL(wO4qJSBhjZXj`R$U%?$gnR%dc5!J?4G?elss!=P4X+-~Y${oOoPm5& zSxWuCokN+A3@nNaXU-*_gYfk`e#As{YYpY9838l^{jsfQIMxy<9{u@}#*zf%guig8 zWmQfTG4oLw?qDicD5F}0fJ1*%z z2=so}=rreir7hOp)B&{__7MfRw`+){TNrMt->6|OXa9;%aASk=3akx}BMVlH8l^Z)O<;J{YT1-P% zH5w`#I}GNC)lL0HLz(jyM%ma+O%pUxlx-U2@8scT3CMjYU_A748Z?M?6|gCvvJ@9P zC}ryno03nciKN|2zC!v=>}s4C>1G_Tv9qz?oD8M2XEst5`yhY(s%G7Dp^9=`#4!c0 zhAY2{K&{qYyVpW)tTk(AI&Y%52{(Rd_GQC(3vKEPl{WS0lT;mr?g`b!-aYMkqeq); zF*fdLF9AI%WqDsnlV5#WpeXTCQKF?N@qAI@&*9aRI*Hoq%!fm5;n?~>k$*d^-xT?` zfP7oz-vshqk-s?%1v(9{u|p_a9Y~ixJLG>FXvAdv>Z)F$#IyU*(-k!ZlWCBq{{7t@ z!n03aJ7$pYvXxqH#60ui0JOtoG-2AiXT2*GiO1TqmOWiu`K{`lp!B`aCa-7^)Qatm zKq%QB{pFIUrAKRNWGxW2L#RlsQhJu1zkxNM{n%x=-2E7LKGXjU(4X~!MH!i8&zbjQ z^<(VY${;z2tJGIrUtUpZ>)Y1C)ijI``!+rbT&*1+N1wttJ_ULxC>|W6oN+dT9u2x4 zl+%T$LGwVL0cGFY0y+tF6X+SBn?ZpUWz^4u{t5TZ2n+pQ6bg;x9*T@a>GV|4SKwX^ z`Wh(vG|EtY8f_WuE43SXNwH-}J~9oaAyV~e%EmrzmbmrDKg|=07*Yzb`{k{lLbD%Q zC2out%g8ida_0(?aw&6zhPEdc&o2n88tJBN(|F09FG$Lz%>BSY)1KUg@be3bvQ6V9 zm*b9}Dx!b1%VsWFIiPIpiIr?SlJdP|E2KQ_pntdLM|-kWe%O)i$yP{_jXs^mEW`F> zt1`4BY4?h^Li!HqVjO^RBOBvVcPguzEw!6j&W6l_b~j`{+)QKB4yGD1nj3Y3nf@+{ zShImL^7aXdTG!y@BiF{jaM(auXZmUPx6wdog|aq$TmfJ`7;? zp-8lObvz!KJ-oG!;#Dy?n`6Z(1WlG9ZFsE6)qyQ7nA6|Jo4h-j$QM0t1PezO9`DFA^tGqJT zD#UzdFQ!J|Nh}`rzn>I&rd^C@%Kz;=V?db?vy}EG7jX0$wHiWcd3{OdWe=gI@t_?g ztIOVq%6zyK6+^mFEDdxj?Y_rL11hiyS$h+j=qhiWg>zssFDP~ zSjf+J*yyuC-Al*yHFNi&%X6+9Qv;!%zly@#CWK`ghRtqpKR7JWj(yP0F+Na*6|Dz7 z1auo{e^8FE13)>g!gkW=IM5?Ne+zmfXm1R(xu8%eDC+%ZfeyqyPeC~j^f}N$ph1K? z7?cy$TXCuGls5J7t=!l_DmSV+Vq8r_SJj;=8#^{U^qbw@9NuGb2V69~Q#f{{%EoT* zK3qzuiG+jpXAW4h71Gx;O_T?k3jXY~0<@}qnH9XYhhug^4g-)%%`SHJ5~K6Ks~PK% z_o5~1R;-lwU-k#&r2V)7b$XVZ7bR_UDKua2RrA(bNE4;K6BGJI`kTtb56EjCDJO$O z_REiP&wE4Xyv;j1gDzM9DYOI(l8~afu+m57sFWCy&|Mq}!JNjtz z)t;FrOur>n*?PlG0Um$W$i7) z$$QIi(%v!@?=8b#hp;!f1m)7yg}*l)rtYW@*f%yzg7!KzdHBhEWF5at{WlHHkE}cB zM+$6@p5XU&Wn#~Z+P&9eJ{r3Fd>(!u%x>;(Q1>8p&fMy`+41Yc-2dV|2&w zlgD5dJsWf(=&PWMKqn&Hi$IrvE(X0HbP4D{$bS`=8klHP#|bF6RoXYhI39S$-8A%9 z1Cz3`EB~vw_1BPd5i$)^W?__#9rI3HeuF5=HjS6ucLgZ}h+cm%WiwPuqOvh(m2Ap1 zk+gfsR!IB$gL$F^7U%Y|pWj3>WExz|^Z@11r(jF%DOO&I7#$ zln;{Ef_@E(XP+n*7L4mb&jS59=w+Zcfbz}fjiCL}SMk)G7${H8c^C91(Cwgj5Qu&Q zdI#utptpef5Dz>kME#(6fRH0s?*wI^`!O!n=hCK*_E2t3+E=|>VOmT>f7RzI8+*Sm z#Ld2^F|=aWw_H6;p6Vgfh{UJp&2akO1)1thK<<8njfYYd=3;@>vF8!TTH~0jb~m2N zQ#Rfl?6qj+Z^9y0v!tG3GIQG_~NFCiYF1d@3C2+Qve~5geYnf;MEsqKteH zV}2boud0F{((V1BGQIHbARhuFxYTA#i0KW-0yyxwqtu53mMi90Es(`Du7rhgnTBy= zC1#}^qa7bbq zv@JIUCy~zh^iZ-h0!9X8o5ypQ@)=J{sV+A-=-0Xc@IAOjr<)URc@mMn; z=u*(P?d|K+SCXAq$Ng681U6zEW78W!AuNO&!OH-3q)~Jo7m^Ii!FnmV2JW1228>_f z|6{SS263ef8{kt4nMz6M&oyG(AgKy@ZuR`C@_p`!Mcnb0_RYH@@X*v3%b$f5A{} zDQKP*#`&2I+Z#WO3@BLD7Qx`|ms2Bgto0-$2DiZBu)Lk5$-uBQ9qID;W&n2fPaf0t z_|v@4rkE~|H`AW>_<9gTTrXbhMd2NA6iw>mKm*3N_-DlqNFlNb)Z%g<@y20>h5Qk& z)F!|KtbbS=U=w%+muVOtn?PSUJgXi5iK@IG>|cVi0_+CO)%SxzzruYOv=dIMssiN^ zZhWbQ4-2Hp@F=&HxbF(usQoVo?S}j7K=%W^AJh-}5Gap|+W?9eUC~XT`-5^`dI0E4 zpgaohHPF7Ge7?pauAIGl5a@fjKNxfu=pmqNf}@Zg)dXo%O;EWtY2OUlYs9phhW@Gv zDqA`{3dGHRa#mLjr?0}X@hKZ~YKCx}1{>338ZX%=Ib>6AFAZ-`HqWE<3yShh<0Tu5 z_H5#|Vc#y_8DquIVPDC&BN>L5e1$X@vx(ZXe6b^G_mZu0(AU+EowC+qbM!GOE6(Q! zbFXNyB=M_eq!PVHX5-BeCH+ZW+sMa;!8P-;ggEhS@#_2XiNo&neA$maca3hy;lv=E z;;7HaJy4&K+b||^YVYxR&1NUGb711szM*@0bnSM=cxOMSztdN?cebRDUdKo*xmG$W zZp6gekNgK!6%LK=n8rSiyj;028?gU&20HpD-1BI?H$hJUWu{IB^VQwjj&QMgIP@ajT-7D@2 z>Dxce*neXH&mXF@_@N7zukPWD7?0Jq1)o~P(LIo}zVg9f9qJA?DGeH@Tvvhrr0;lRbZK}R2wUC?8fN*U2HY3slJw85N&|PvkHWp6k^erbf7fp|S7g&O?m$(8g zPhPSc$+>5B&o-6raV<;kFJSMcrjcyZs_*}E(#BTT-ZRxqB%1ylv{UL~q+<5`s(N*l z>fW#JB%i6GkZ&4>7sSP9g@|^<7JBLDu_GYLRUd4RmkDAGC~I6T=r2L*LGJ>MfIa}) z0QxxS1)!~<7lJ+qx)78Tza^m45!O=Bfw)h=uIe>ys$MHMhN9fk;KMkYhOVk!D;w)I zUo2T`J?CmDbJ4;m8+)&t1vLm}Ru=k2x8RO&*Ig zlUK|0A`VS%hI=@U-I8FDoci_=6h^EEVm-!hO@5Ieqgkn4RPdtKmPIvW9f|(NR zinJ-k=eX$iaS4y6YWjB^M(ecQAR1UZpL0z*FoB>yPTF*+#kHUCs4el%Lor#NexK?A(Ee~Jrp0xb<`Rq}6|5D0A0Mu1?)`mTUTP{R z)9>4ae>2XQ+Yt^kL=n`kpeq&Vk8G(p=9-#Zi_6S4!8i_GWBsuX#XPZX$^eUNiVjOK zjvVXe2vPiZuQafEdUT&=LumcP>7;<`k03C0oDp~A(mXwEPE$*(Lf&VXnHBQ}mlrg0v^ z&0f&&Ge4yaoF1N=T3$iH6hVerUWZ9*N`Acx|HBM-dG!}Av%I?B@zxuP3(m$m9Us9s z(ltQ1%<>8xyO7F)###u3($j^v0AF{ZP(p-XZ zgq15?W*^??z3XRMTv+uHBN#_moa4<`Rq}tYaKuO*?o^gT;j>VKIVn zgmtVVtox=t*JyF!c}0w19AOO`;<{OL3C7X;9WPuQIcWxsJNC-d)-)JCe%~$lH(S&3w$_ACNMVjQ zg6#clGb_$1{66du7c+PH)n%!YhYIEi{F{=8*d*f{M3^B;vQ3dQCO5WnA3J2zV~UID z2X#sX!UNyD(&BnWa|y-~)(GJ;%e`jqS%0>; z{-L=9;|Pl{imm#*@`6YHU~zq;xdh_~D?iBvi_A$ZF7p^{!8l51q;Q$v`Sfjg{F&6! z86_C?JVe=i65@$_(|1CAg3IvmbI&aqJvGyFRhqo~{r9Ov*%j`36UHkeeii_ykIzEDNq+*K5xWI>(9b+P6Wj3cZfM_2=@m;ce?x=wQm#u3(dM_6Zl`_@Mm z*PWV6FpjWJ5-zhQoVe@8<1DTxG?!o;VNGy^^?WSXmagYDmtY)Wg@wzU{}_kwe%A_X zo8}UXBdlUaSfAZ=?>iRPrww+#D^2C%{H%Yk6TKC)cZ#>lE8lbrZ<4DCR!e!RF+zG`uTU?_wmtY(@ zR_X|A?ZG{>EUqb-K(X=}Z$0H&ALZ#?)l#+@qbQrj*X9!ey4u*##%# z^d7T6Y}QvEK4y@nDU0XD}cl5m{H5D`96Sb?lt;|3CKL1wN|kTp!*;0)%jx1OcO>Omx&J2!TWh1|^eBUt9?=RGDB*ak`g?Y zur3i&y0$s#lI;G5)GbO%@L0m)=%n$E8$SB+W<%;BB_(()Va<(8!J@6c^4ejB)C)>V z@K|a>nULZelg4>8Y#v;!<49%kn(%@0xvW!7C>K(CP2gylA@#MA59 z_ktsg;IX8l64V42DzW&YA3El)_dC~Tc3u)(Z{ojRpDW|37^Qr!?39Z6LP}4C?@w!o z7*akZC3q~Us1{OsedcJGAvH%y2_8$iv-4||`xQUVy~B`NqND_mC9F$@lwO}X8fHk{ zprizkB`gd`nZn{|m?8CRB_(()Vb#W^U=cdgklLoC1dpY3778g&y0J^U{> zmP@kmbz|z~UIwaBIyoEbPB)~6D=EQa39CU!>0zaX?j2`HO;%EZ#}XF1jYe2STVLE~ zNR=xo!D9(4ETnX8Q(HdpBtz;dB_(()VKrI8x~Shz>kKIjkqRStEMYAcQhK^}&;2UT zka|=}2_8#WODtgxKcRS-A@z!q5fiog2$4IW+A2PgtxBVlw?Sq zt)v8xCC9F`gf(y0vg-_~5+x;gEMYCTg!SBjgLQ_~0wpDQEMZ+`32UU*?>$56Y9%Fj zEMY~2lwRw8bV{#t4XL}8l;E+1wZamXXYU_gGo+qSQi8`4){lggUhCd&ZvM3)^(Q4I zcr0PHSi%}pd&_SPsZW%Y;IV|&Dx_FmG&@gw;?IUu-#(Hmcr3MUB^)qTDV?>lEpMS3 z+H2j_g6CoU*WW}ddJFZ!;WgAj=C@H~XDfc!@Si!Fs+-OMsUP%caOIX(lDZM^VJa6FyL+T|ZC3q}h zU2h3%>p3UiYe?-^Qi8`4)*2x-l>hN$T|4_6L#kIYNHBuO64sAFHQo*fpIFgmNTn+& z!D9*QhPV`c<=3bob&iq}JeHbpqmZI@rJ~(@%R9Gqt_e2@p56Gb*MuA6HDQMG`9{

&xTZsk`g?cH#9X1%)&4gz4ZRZ43cie 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%0Dlh&j3%6ozKC)1>jj? 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 literal 0 HcmV?d00001 diff --git a/plugins/zzogl-pg/opengl/Win32/ps2hw.dat b/plugins/zzogl-pg/opengl/Win32/ps2hw.dat new file mode 100644 index 0000000000000000000000000000000000000000..970b7b17e9906e67a7678211bd4e1e1177a01fbb GIT binary patch literal 108445 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 svnrev.h +// +// This file acts as a template for the automatic SVN revision/version tag. +// It is used by the utility SubWCrev.exe to create an "svnrev.h" file for +// whichever project is being compiled (as indicated by command line options +// passed to SubWCRev.exe during the project's pre-build step). +// +// The SubWCRev.exe utility is part of TortoiseSVN and requires several DLLs +// installed by TortoiseSVN, so it will only be available if you have TortoiseSVN +// installed on your system. If you do not have it installed, a generic template +// is used instead (see svnrev_generic.h). Having TortoiseSVN is handy but not +// necessary. If you do not have it installed, everything will still compile +// fine except without the SVN revision tagged to the application/dll version. +// +// TortoiseSVN can be downloaded from http://tortoisesvn.tigris.org + +#define SVN_REV $WCREV$ +#define SVN_MODS $WCMODS?1:0$ \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/Win32/tsvnrev/svnrev_unknown.h b/plugins/zzogl-pg/opengl/Win32/tsvnrev/svnrev_unknown.h new file mode 100644 index 0000000000..a2a3703186 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/tsvnrev/svnrev_unknown.h @@ -0,0 +1,23 @@ +// svnrev_genric.h --> svnrev.h +// +// This file acts as a placebo for people who do not have TortoiseSVN installed. +// It provides "empty" revision information to the Pcsx2 Playground projects in +// the absence of real revisions derived from the repository being built. +// +// This file does not affect application/dll builds in any significant manner, +// other than the lack of automatic revision tags inserted into the app (which +// is very convenient but hardly necessary). +// +// See svn_template.h for more information on how the process of revision +// templating works. +// +// If you would like to enable automatic revisin tagging, TortoiseSVN can be +// downloaded from http://tortoisesvn.tigris.org + +#define SVN_REV_UNKNOWN + +// The following defines are included so that code will still compile even if it +// doesn't check for the SVN_REV_UNKNOWN define. + +#define SVN_REV 0 +#define SVN_MODS "" \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/Win32/tsvnrev/updateRevision.cmd b/plugins/zzogl-pg/opengl/Win32/tsvnrev/updateRevision.cmd new file mode 100644 index 0000000000..0e192e7a9b --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/tsvnrev/updateRevision.cmd @@ -0,0 +1,8 @@ +@echo off +SubWCRev.exe %1 %2\svnrev_template.h %1\svnrev.h +if not ERRORLEVEL 0 ( + echo Automatic revision update unavailable, using generic template instead. + echo You can safely ignore this message - see svnrev.h for details. + copy /Y %3\svnrev_unknown.h %2\svnrev.h +) +set ERRORLEVEL=0 diff --git a/plugins/zzogl-pg/opengl/Win32/vsprops/pcsx2_plugin_common.vsprops b/plugins/zzogl-pg/opengl/Win32/vsprops/pcsx2_plugin_common.vsprops new file mode 100644 index 0000000000..086133a60a --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/vsprops/pcsx2_plugin_common.vsprops @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/plugins/zzogl-pg/opengl/Win32/vsprops/postBuild.tmpl b/plugins/zzogl-pg/opengl/Win32/vsprops/postBuild.tmpl new file mode 100644 index 0000000000..e5581989b0 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/vsprops/postBuild.tmpl @@ -0,0 +1,24 @@ +@echo off +rem +rem Usage: postBuild.cmd SourcePath DestDir DestFile DestExt +rem +rem SourcePath - $(TargetPath) - Fully qualified path of the generated target file. +rem DestDir - $(SolutionDir) - Directory of the destination, usually the same as the solution. +rem DestFile - Base filename of the target/dest, without extension! +rem DestExt - Extension of the target/dest! + +set pcsxoutdir=%2\bin\plugins +set pcsxoutname=%pcsxoutdir%\%3%4 +set pcsxnewname=%pcsxoutdir%\%3-r$WCREV$$WCMODS?m:$%4 + +IF NOT EXIST %pcsxoutdir% ( + md %pcsxoutdir% +) + +copy /Y %1 %pcsxoutname% +copy /Y %1 %pcsxnewname% + +if ERRORLEVEL 0 ( + echo Target copied to %pcsxnewname% +) +exit 0 diff --git a/plugins/zzogl-pg/opengl/Win32/vsprops/postBuild.unknown b/plugins/zzogl-pg/opengl/Win32/vsprops/postBuild.unknown new file mode 100644 index 0000000000..360b05cad5 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/vsprops/postBuild.unknown @@ -0,0 +1,21 @@ +@echo off +rem +rem Usage: postBuild.cmd SourcePath DestDir DestFile DestExt +rem +rem SourcePath - $(TargetPath) - Fully qualified path of the generated target file. +rem DestDir - $(SolutionDir) - Directory of the destination, usually the same as the solution. +rem DestFile - Base filename of the target/dest, without extension! +rem DestExt - Extension of the target/dest! + +set pcsxoutdir=%2\bin\plugins +set pcsxoutname=%pcsxoutdir%%3%4 + +IF NOT EXIST %pcsxoutdir% ( + md %pcsxoutdir% +) + +copy /Y %1 %pcsxoutname% +if ERRORLEVEL 0 ( + echo Target copied to %pcsxoutname% +) +set ERRORLEVEL=0 diff --git a/plugins/zzogl-pg/opengl/Win32/vsprops/preBuild.cmd b/plugins/zzogl-pg/opengl/Win32/vsprops/preBuild.cmd new file mode 100644 index 0000000000..9047b6e29a --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/vsprops/preBuild.cmd @@ -0,0 +1,20 @@ +@echo off + +rem Usage: preBuild.cmd ProjectSrcDir VspropsDir +rem +rem ProjectSrcDir - $(ProjectDir)\.. - Directory of project source code. +rem VspropsDir - $(PrjectDir)\vsprops - Directory of this script and its counterparts. + +SubWCRev.exe %1 %2\svnrev_template.h %1\svnrev.h +if %ERRORLEVEL% NEQ 0 ( + echo Automatic revision update unavailable, using generic template instead. + echo You can safely ignore this message - see svnrev.h for details. + copy /Y %2\svnrev_unknown.h %1\svnrev.h + copy /Y %2\postBuild.unknown %2\postBuild.cmd +) else ( + SubWCRev.exe %1 %2\postBuild.tmpl %2\postBuild.cmd +) + +rem Always return an errorlevel of 0 -- this allows compilation to continue if SubWCRev failed. + +exit 0 diff --git a/plugins/zzogl-pg/opengl/Win32/vsprops/svnrev_template.h b/plugins/zzogl-pg/opengl/Win32/vsprops/svnrev_template.h new file mode 100644 index 0000000000..f2656ef1e8 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/vsprops/svnrev_template.h @@ -0,0 +1,18 @@ +// svnrev_template.h --> svnrev.h +// +// This file acts as a template for the automatic SVN revision/version tag. +// It is used by the utility SubWCrev.exe to create an "svnrev.h" file for +// whichever project is being compiled (as indicated by command line options +// passed to SubWCRev.exe during the project's pre-build step). +// +// The SubWCRev.exe utility is part of TortoiseSVN and requires several DLLs +// installed by TortoiseSVN, so it will only be available if you have TortoiseSVN +// installed on your system. If you do not have it installed, a generic template +// is used instead (see svnrev_generic.h). Having TortoiseSVN is handy but not +// necessary. If you do not have it installed, everything will still compile +// fine except without the SVN revision tagged to the application/dll version. +// +// TortoiseSVN can be downloaded from http://tortoisesvn.tigris.org + +#define SVN_REV $WCREV$ +#define SVN_MODS $WCMODS?1:0$ \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/Win32/vsprops/svnrev_unknown.h b/plugins/zzogl-pg/opengl/Win32/vsprops/svnrev_unknown.h new file mode 100644 index 0000000000..4872e23b20 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/vsprops/svnrev_unknown.h @@ -0,0 +1,23 @@ +// svnrev_genric.h --> svnrev.h +// +// This file acts as a placebo for people who do not have TortoiseSVN installed. +// It provides "empty" revision information to the Pcsx2 Playground projects in +// the absence of real revisions derived from the repository being built. +// +// This file does not affect application/dll builds in any significant manner, +// other than the lack of automatic revision tags inserted into the app (which +// is very convenient but hardly necessary). +// +// See svn_template.h for more information on how the process of revision +// templating works. +// +// If you would like to enable automatic revisin tagging, TortoiseSVN can be +// downloaded from http://tortoisesvn.tigris.org + +#define SVN_REV_UNKNOWN + +// The following defines are included so that code will still compile even if it +// doesn't check for the SVN_REV_UNKNOWN define. + +#define SVN_REV 0 +#define SVN_MODS "" \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/Win32/wglext.h b/plugins/zzogl-pg/opengl/Win32/wglext.h new file mode 100644 index 0000000000..d54e0a4d50 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/wglext.h @@ -0,0 +1,813 @@ +#ifndef __wglext_h_ +#define __wglext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are 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 Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/*************************************************************/ + +/* Header file version number */ +/* wglext.h last updated 2009/03/03 */ +/* Current version at http://www.opengl.org/registry/ */ +#define WGL_WGLEXT_VERSION 12 + +#ifndef WGL_ARB_buffer_region +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 +#endif + +#ifndef WGL_ARB_multisample +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif + +#ifndef WGL_ARB_extensions_string +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 +#endif + +#ifndef WGL_ARB_render_texture +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 +#endif + +#ifndef WGL_ARB_pixel_format_float +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 +#endif + +#ifndef WGL_ARB_create_context +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define ERROR_INVALID_VERSION_ARB 0x2095 +#endif + +#ifndef WGL_EXT_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 +#endif + +#ifndef WGL_EXT_depth_float +#define WGL_DEPTH_FLOAT_EXT 0x2040 +#endif + +#ifndef WGL_3DFX_multisample +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 +#endif + +#ifndef WGL_EXT_multisample +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 +#endif + +#ifndef WGL_I3D_digital_video_control +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 +#endif + +#ifndef WGL_I3D_gamma +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F +#endif + +#ifndef WGL_I3D_genlock +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C +#endif + +#ifndef WGL_I3D_image_buffer +#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 +#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 +#endif + +#ifndef WGL_I3D_swap_frame_lock +#endif + +#ifndef WGL_NV_render_depth_texture +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 +#endif + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 +#endif + +#ifndef WGL_ATI_pixel_format_float +#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 +#endif + +#ifndef WGL_NV_float_buffer +#define WGL_FLOAT_COMPONENTS_NV 0x20B0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 +#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 +#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 +#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 +#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 +#endif + +#ifndef WGL_3DL_stereo_control +#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 +#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 +#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 +#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 +#endif + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 +#endif + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 +#endif + +#ifndef WGL_NV_present_video +#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 +#endif + +#ifndef WGL_NV_video_out +#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 +#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 +#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 +#define WGL_VIDEO_OUT_COLOR_NV 0x20C3 +#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 +#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 +#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define WGL_VIDEO_OUT_FRAME 0x20C8 +#define WGL_VIDEO_OUT_FIELD_1 0x20C9 +#define WGL_VIDEO_OUT_FIELD_2 0x20CA +#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB +#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC +#endif + +#ifndef WGL_NV_swap_group +#endif + +#ifndef WGL_NV_gpu_affinity +#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 +#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 +#endif + +#ifndef WGL_AMD_gpu_association +#define WGL_GPU_VENDOR_AMD 0x1F00 +#define WGL_GPU_RENDERER_STRING_AMD 0x1F01 +#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define WGL_GPU_RAM_AMD 0x21A3 +#define WGL_GPU_CLOCK_AMD 0x21A4 +#define WGL_GPU_NUM_PIPES_AMD 0x21A5 +#define WGL_GPU_NUM_SIMD_AMD 0x21A6 +#define WGL_GPU_NUM_RB_AMD 0x21A7 +#define WGL_GPU_NUM_SPI_AMD 0x21A8 +#endif + + +/*************************************************************/ + +#ifndef WGL_ARB_pbuffer +DECLARE_HANDLE(HPBUFFERARB); +#endif +#ifndef WGL_EXT_pbuffer +DECLARE_HANDLE(HPBUFFEREXT); +#endif +#ifndef WGL_NV_present_video +DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); +#endif +#ifndef WGL_NV_video_out +DECLARE_HANDLE(HPVIDEODEV); +#endif +#ifndef WGL_NV_gpu_affinity +DECLARE_HANDLE(HPGPUNV); +DECLARE_HANDLE(HGPUNV); + +typedef struct _GPU_DEVICE { + DWORD cb; + CHAR DeviceName[32]; + CHAR DeviceString[128]; + DWORD Flags; + RECT rcVirtualScreen; +} GPU_DEVICE, *PGPU_DEVICE; +#endif + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT); +extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE); +extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int); +extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +#endif + +#ifndef WGL_ARB_multisample +#define WGL_ARB_multisample 1 +#endif + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringARB (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCARB (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB); +extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC); +extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB); +extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglBindTexImageARB (HPBUFFERARB, int); +extern BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB, int); +extern BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB, const int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList); +#endif + +#ifndef WGL_ARB_pixel_format_float +#define WGL_ARB_pixel_format_float 1 +#endif + +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList); +#endif + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort); +extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint); +extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort); +extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +#endif + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); +#endif + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT); +extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC); +extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT); +extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglSwapIntervalEXT (int); +extern int WINAPI wglGetSwapIntervalEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +#endif + +#ifndef WGL_EXT_depth_float +#define WGL_EXT_depth_float 1 +#endif + +#ifndef WGL_NV_vertex_array_range +#define WGL_NV_vertex_array_range 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern void* WINAPI wglAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat); +extern void WINAPI wglFreeMemoryNV (void *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef void* (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); +typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); +#endif + +#ifndef WGL_3DFX_multisample +#define WGL_3DFX_multisample 1 +#endif + +#ifndef WGL_EXT_multisample +#define WGL_EXT_multisample 1 +#endif + +#ifndef WGL_OML_sync_control +#define WGL_OML_sync_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetSyncValuesOML (HDC, INT64 *, INT64 *, INT64 *); +extern BOOL WINAPI wglGetMscRateOML (HDC, INT32 *, INT32 *); +extern INT64 WINAPI wglSwapBuffersMscOML (HDC, INT64, INT64, INT64); +extern INT64 WINAPI wglSwapLayerBuffersMscOML (HDC, int, INT64, INT64, INT64); +extern BOOL WINAPI wglWaitForMscOML (HDC, INT64, INT64, INT64, INT64 *, INT64 *, INT64 *); +extern BOOL WINAPI wglWaitForSbcOML (HDC, INT64, INT64 *, INT64 *, INT64 *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator); +typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); +#endif + +#ifndef WGL_I3D_digital_video_control +#define WGL_I3D_digital_video_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC, int, int *); +extern BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC, int, const int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); +typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); +#endif + +#ifndef WGL_I3D_gamma +#define WGL_I3D_gamma 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetGammaTableParametersI3D (HDC, int, int *); +extern BOOL WINAPI wglSetGammaTableParametersI3D (HDC, int, const int *); +extern BOOL WINAPI wglGetGammaTableI3D (HDC, int, USHORT *, USHORT *, USHORT *); +extern BOOL WINAPI wglSetGammaTableI3D (HDC, int, const USHORT *, const USHORT *, const USHORT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); +#endif + +#ifndef WGL_I3D_genlock +#define WGL_I3D_genlock 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglEnableGenlockI3D (HDC); +extern BOOL WINAPI wglDisableGenlockI3D (HDC); +extern BOOL WINAPI wglIsEnabledGenlockI3D (HDC, BOOL *); +extern BOOL WINAPI wglGenlockSourceI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSourceI3D (HDC, UINT *); +extern BOOL WINAPI wglGenlockSourceEdgeI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC, UINT *); +extern BOOL WINAPI wglGenlockSampleRateI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSampleRateI3D (HDC, UINT *); +extern BOOL WINAPI wglGenlockSourceDelayI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC, UINT *); +extern BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC, UINT *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge); +typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay); +typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); +#endif + +#ifndef WGL_I3D_image_buffer +#define WGL_I3D_image_buffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern LPVOID WINAPI wglCreateImageBufferI3D (HDC, DWORD, UINT); +extern BOOL WINAPI wglDestroyImageBufferI3D (HDC, LPVOID); +extern BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC, const HANDLE *, const LPVOID *, const DWORD *, UINT); +extern BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC, const LPVOID *, UINT); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); +typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); +typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); +typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count); +#endif + +#ifndef WGL_I3D_swap_frame_lock +#define WGL_I3D_swap_frame_lock 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglEnableFrameLockI3D (void); +extern BOOL WINAPI wglDisableFrameLockI3D (void); +extern BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *); +extern BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag); +#endif + +#ifndef WGL_I3D_swap_frame_usage +#define WGL_I3D_swap_frame_usage 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetFrameUsageI3D (float *); +extern BOOL WINAPI wglBeginFrameTrackingI3D (void); +extern BOOL WINAPI wglEndFrameTrackingI3D (void); +extern BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *, DWORD *, float *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage); +typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); +#endif + +#ifndef WGL_ATI_pixel_format_float +#define WGL_ATI_pixel_format_float 1 +#endif + +#ifndef WGL_NV_float_buffer +#define WGL_NV_float_buffer 1 +#endif + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_EXT_pixel_format_packed_float 1 +#endif + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_EXT_framebuffer_sRGB 1 +#endif + +#ifndef WGL_NV_present_video +#define WGL_NV_present_video 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern int WINAPI wglEnumerateVideoDevicesNV (HDC, HVIDEOOUTPUTDEVICENV *); +extern BOOL WINAPI wglBindVideoDeviceNV (HDC, unsigned int, HVIDEOOUTPUTDEVICENV, const int *); +extern BOOL WINAPI wglQueryCurrentContextNV (int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList); +typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList); +typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue); +#endif + +#ifndef WGL_NV_video_out +#define WGL_NV_video_out 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetVideoDeviceNV (HDC, int, HPVIDEODEV *); +extern BOOL WINAPI wglReleaseVideoDeviceNV (HPVIDEODEV); +extern BOOL WINAPI wglBindVideoImageNV (HPVIDEODEV, HPBUFFERARB, int); +extern BOOL WINAPI wglReleaseVideoImageNV (HPBUFFERARB, int); +extern BOOL WINAPI wglSendPbufferToVideoNV (HPBUFFERARB, int, unsigned long *, BOOL); +extern BOOL WINAPI wglGetVideoInfoNV (HPVIDEODEV, unsigned long *, unsigned long *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); +typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock); +typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +#endif + +#ifndef WGL_NV_swap_group +#define WGL_NV_swap_group 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglJoinSwapGroupNV (HDC, GLuint); +extern BOOL WINAPI wglBindSwapBarrierNV (GLuint, GLuint); +extern BOOL WINAPI wglQuerySwapGroupNV (HDC, GLuint *, GLuint *); +extern BOOL WINAPI wglQueryMaxSwapGroupsNV (HDC, GLuint *, GLuint *); +extern BOOL WINAPI wglQueryFrameCountNV (HDC, GLuint *); +extern BOOL WINAPI wglResetFrameCountNV (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); +typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); +typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier); +typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count); +typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); +#endif + +#ifndef WGL_NV_gpu_affinity +#define WGL_NV_gpu_affinity 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglEnumGpusNV (UINT, HGPUNV *); +extern BOOL WINAPI wglEnumGpuDevicesNV (HGPUNV, UINT, PGPU_DEVICE); +extern HDC WINAPI wglCreateAffinityDCNV (const HGPUNV *); +extern BOOL WINAPI wglEnumGpusFromAffinityDCNV (HDC, UINT, HGPUNV *); +extern BOOL WINAPI wglDeleteDCNV (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); +typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); +typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); +typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); +typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); +#endif + +#ifndef WGL_AMD_gpu_association +#define WGL_AMD_gpu_association 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern UINT WINAPI wglGetGPUIDsAMD (UINT, UINT *); +extern INT WINAPI wglGetGPUInfoAMD (UINT, int, GLenum, UINT, void *); +extern UINT WINAPI wglGetContextGPUIDAMD (HGLRC); +extern HGLRC WINAPI wglCreateAssociatedContextAMD (UINT); +extern HGLRC WINAPI wglCreateAssociatedContextAttribsAMD (UINT, HGLRC, const int *); +extern BOOL WINAPI wglDeleteAssociatedContextAMD (HGLRC); +extern BOOL WINAPI wglMakeAssociatedContextCurrentAMD (HGLRC); +extern HGLRC WINAPI wglGetCurrentAssociatedContextAMD (void); +extern VOID WINAPI wglBlitContextFramebufferAMD (HGLRC, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT *ids); +typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, int property, GLenum dataType, UINT size, void *data); +typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int *attribList); +typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc); +typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc); +typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); +typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/zzogl-pg/opengl/Win32/zerogs.bmp b/plugins/zzogl-pg/opengl/Win32/zerogs.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5cf24cf9e09d94de6bb9bc1c0099f1d3d6946632 GIT binary patch literal 921654 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 z z*T$v4S*pV9%fcS~pWypTgbfc)ddM$+=#`P}FAHm%nB4iM+lSn6``{aH9d^rIBd>2U zp-Qun%vTv0HzlF+gjQW<_v$yd_rPcWmCcgDKg8Gi$$-B0kIY1!P;+nVd%l@Dd-d$O zAI^Va?ZQQ$qI_RjVir~)?5w$+nPfxoCF~4*rF_5NVq(s~mj>V6&N!n32EIo2vYwGM z&WKr^%^+Vdd~KVr#`&Up{|@2n1w0dRP#1wwX6l8^i(-DPRIpfS435 zX^95lFu_i;R4EV?3Vi?yd@X-{c8RL`pwF(0Z|Z}#j6DsVl~PWUd`jYQ^5&$SUe;WT zHC`|cb8EOM|?;8xjqsY@rwi=muD7b(4^32E)K>5=P@HRf2JdJek-t@5exqM zbcFWhuM>hc>k@V`(_!&vR%B2V+L?|+5*YXz{xT`F(+XU^#eY~A*oL5;URVWlL2Dqe z=>-jcnGV|Yg3hHQH2jTha7z4*u6G>xYQZB?yWpT%b1=){Z_Qsd?PUJQqwOK-+vxlp zTzzX$wXbRa4RQ2uNY&3nQa%f+ye_cHD%LZKX!LW^9l0p?#5+9|TYD8Xg!WmnhT9+S2vw9+f35}v*yWX$DJ6IhEdr2JI> z*eCoF=8##s?BtR$11hBTy6)BoZoH%aovns9Z$0{^=8q<(kGw2#ihsgG!R5x@)NV%a z0W*3Io^ySxZ=xG)iLd`%Xv59n4ZjVozd51q5BCiHeBQj(FFwBp_%2@Z*=w(E1io5W zLCSaC>K~mpU(?%JGi(_6erLKm+um0Dov<_TJ?bnb=q#xq_!i79Y1(|Xm@mpVAHIa3 z|7sDeC^t1B^rWAa_>17Z|Ni?SZ_l1RyLa#2qeqWky?Q}opiDj#mK-K14TX`z(!!!J zU8Xq{MguV{hQb85p)j3Z5XFEP3X`HiR1H!GN}*7TQd?rGX{mA@!DN~Xaj1}~iro~p zAf|e!p2yH%7@JaO5CPSO8DZ=gKFGkpF?<0i#9$!~=y8;>xBHf)A~*(K5E*7cE_~32 zD8`^0u(K?dPl{Pk{&7br_c^THw2r<=Uk#2qJwaLL$(h^JCI_D!E=pI#rE!_Oe(3V8 zBT>x#5vg%>(?G3r|4brZ5e9s445o3MTW;<-u?QXq4k^!q2V|8p&xoHKIS^J_SUGyv zB9jNrb7vD@#_s{z@+p1^{2o9m6vpS*g3m5CF@8V%kgTZ~ha!hv9E2A?d_Dz;aZFUy z={jY(12X;~HSEWIj%>f;Z*ZK8D3I`f!#BFW!d|#N4ePjz{SLov`|PfrJ9lZH%{qlG z?)mq%qrcB23O&}lD3VdZu0CNa^&#vK^uAbd>IaNM>E6eEvGaflVtg z9ihD{IDcJWw*s=*WqupfiKFJ z)du$$z*loVJHw7b%(RnU_!|DEeG{0vDX{8BGx#X=3qsH=zTj7RZ9wLiy9V>GpGFRo=VL()&a7KouRYM7K_h-JzXwMGlmM++^CA|@yeh1Ec89~6{unjC1R6LHk)Z=u4Kl=H zK#WNp109G=3Y$>J;26gZVp!}*Ow$5uVTWVIsT+>+jWBlX61kjT-2BT&v|0GGHlMG? z=euwyCI_GM)EScE3(ELnF*xR0L}5~VK+Gj$x(Qr3`S^NEA*FzJiO51TcT$mmQtq=- zh>XJ>=7y8Wv#>1YiSUfb)T804VR~w$JWZu~tUOs9v6zPrb7lNC^s5lH$rPRSYhf=q zR_c)1pqcUlG>(XD==*2$*J8!z$Tt7~%K2|QpWkyII<)WJv2|+(Cw1u3rDMC>dp*`< z{I7K;s^$gr!ym#vo0YB){M~N?*$Ur z&0mybOY>*fC8P=1PRC&uCA_c|Sfh~OuMix6gPDku<&azmHvEk;{5|94FB3l3J?w@r zveziztUX~he=S&W(3$fYzTd52oi;)(-xnYX2BnZ(CC4FA2Sjr_sN9Lu9r0{VKlcSAKE% zj3;lnbA0o5fD5f9=bqZ+-L5JDcBs*ICu*!|f&KHc`0~fxRu_yja^TBKzTSzQPk8cd%vm#R{Pj}zB2pT-z()iu7)8|* zf0q6QxLv#QzS+4;mo88kW0Opbpfp{xC`s=unuht*`0?Wb@uW$UpfFMzniG`9U@<+l z1Y*7gEsP?D#a0vx#0pIVVo{jtQ8lDktSXf1RJAK0mWjejseYxEKrm)&bye(C^;Gy` z0geQkLaCqx2NN$KGSt9;i=;6;LK`Yzs}%i+ao?maA(zl5E(>|!4-IrOX+ zTYb{v%5!|nVq1nxe0u_%jBrej_^Y$!WGs33zhvhFaX=5FiebGP+4q>IVK@OgGTG9D!gmH@$a$0A%Z`+|`=T0VV-o8_t4%v6~o|-lKP^}AR zq||gAbi{J_o9m1Pb`b1zgieFMnvSv%e?hRJu%_bx!QDNn4uavY`a;_fv?MUSpewN` zQho^9hrb0YGTh;D&&A==zh*Azi}05yG`+CkZ@Bbt-DAMlhrhr#JfFXWooV)E-V6iZ z^licE-vQrXXWGe-luf{wKg2KajjFvh_4dOR5%L{8@wc9iXm}vD&H?6j4zGVOq{-3f z>rVt{?F!HMA*v>SJ0ffSK=7H=1fo;d{%_Lo!1##)u_J;K9xN5{pnv>`k_jV9mYZIp z>;nI?^Ge503#_^*Bx6NTwT~mKt|*cECQZhbYrJyDT~BrHF*>{Rgl^qubnE?0?K{4y z-0VQ&H77%^J<;^89g`k@YuMDK!$+;{K6+KxKAZ3C@?D$W-@owY>cy{o`r51CzVZ53 zZ!b0Q{b1R53^jthTQ?v1`Nwnn_j(TP_Z&XpIk?Yr;MbfzKcCsX^VFVSP7`x>+I-I+ zbJ~3A>I{5Y$=8na^_=!F)ClFv^j4l+BYgFD5la3=yHMHG%rFuD(!H5@GE_z35`TuX zFcePv}W5Jm1%OSNu#Ibm_(3GQ*P58C|j-adp zZrbA8OdJlY4=Ph%r!qPR^7V#*Lyq7}vHWv4y}>EKrD5zv0+Vu?z?Z8Qf~`^(h%KOj zFRv@yLv9_$Jyc);A0oqCcEMTlx#yVfGrP!VuZ#jbGkj3X1429V$Z&X|IHWvZ`($xM zWUG`#WUGq-F25N;na}c@A-cjQT=uEnEgg!?{~ehE&2Rmn51s@ypG=NP&Tl<(apmp7 z3p@5Bc9%QH`Z$+(KK3{&uTA%HW-kjA zRv+c5HOkX;Tu$9lIWddQbW$&htYMcD4 zeHC8ii@0hVY4$CZvOc)(mU4F-txR(^^NO&p)15h?_4Y>AJ7kVu|8QuX17Qsg8UEJ( zIU@7B=sH`&Yi^FHwKJ&3&e)V?rnNVIMCr1F%ft^2jC(LBZfI~q{}Ryy{mMNSSblD3 z+2=ya&A+n33oLjPS?Se?a?3+gR`?}<6q5XI^(HUel|8*nuW4QGed3;evl_P89M$Ax z!gU83X;u67-48vw?D6RzOrNpp*=N^0H-GJdMW4R-@`lAPfAPwzU%j<-%iC{$|G|6P zncI28`X6^}JA828*%Qa|PM$D*m;vjlL!M&?JV*BCf#7|+&Ozb*zn(k1H^+8$HZkYp zrp*`GtHlI0$k%Y!A@5(r)=N1o{AD6&sE1Z1hD_fo^sLpt02lZ|UJQrdyc{WF8i)x~ z17aG51!9_p>7#|In=}D!Ks?nk6fwQ5F+$Tc5JO>sn9f?#!UUypXeI{4lEaElqlnSP zG!vs))W-$~981?gVJcXea7@(-d@+im*!E3{?&# zF?X55zRDDt+JorGIt`f1CMl=KIg`o}g6*Y&V?;42#wFu(6EJQ9FC>`m436#?fYwc8 zlU*>En~9;0b(29e_niCe0C^+%JP3SJW%7h@;4jaGOr<AK}1X z3gGbc@k#lq=qJH1gnWEkw-@J#0>$n9i}LlQr0(Mv&h#nZF8o`4dvG7e=Qw}LH@d&V z=lJeTTg+yXBmM&4P93tTj@WF`t_uim+4Hf+qkc`D?8%&PqV5<^%~75jqjJ(%i^1uL zMHj5}VMhPf7-Gf(yZP&mLThP4rsH5Pj;g&3f4wt8`|>wW{B^eii@&xN_~QJvixM&l z$IapZ5UY@S0|wU-37*hUsvXA9LQsfTQ4Q8_T4A z8CmVisFcr3S6vra`T#*54DI zxtA``p_xC#X8sUU^~?-Yrw*wUCszB2qt$Nq;Bf=Gkp~K0WZhd4u{tcWv7*W3D~Q zLQB!tp00D(u16mIXvQ-uXFmJMb1!UoVbK>0U;J$Gk}qF>ee;`deY^CnZ$DVhghIQ2 z{NecF!?|b9dd{EoK}62PHS2_3^t_zO(waAozcgI|;AKZOvCB1Q-UXj+Gj81CJhR%20^reQ!V zElflj1Yz<0R=ngB*sx7y)WaVRvYn z+LiiNsYHe%;_M%ibkWKC?W z;mB?26Fg}X^D@Ss&l>HiH73`N1y(O;D}l8r68iT-{(7gwGW_kGcL9I9J#kU{OM6A}m^g3-s^pxekAg1a|Y6>7WbrZ~k1+Uj8;bAJy<|RQ;1?+6|+BO}8tj z<<~U(hSMOM$vT5YC|}4+YcGER)xHQz`7F5VhLCz&%HDaTTF1Q9PNoZ4g-*GqIlERJl>5;-^GZc_pagvcO6olu3OzDD};-YVR`2I5=f_ z+AZ_5`_3NGf8pQ}FJ0f|v!v?|CpJAA*Ysrl7JJ7(y5Z@$tDl{}cJ2bh-z7^nzw!E3 z$h+*_tpuEZ`uXUQBROZ!vxKe_C?;s^Sl;>Eb7ynUp3XgU!b{FR9Zd)5x} zRhzG7xH|8V_`MW~`j?hL|DHX27M7t&;qSO{cO@gI>q%e+nGs@D?f% zLt(H9Cpf-DTJdj)UYT#ZQ3-x6glij;n~0!hhEb%1*k!>D2zf! z7XxA;7z*Pciq%XEj*-U16(x%E1+llwmKDM{)V-F!s+LKqrDfFHn8C1Ps?t^4tNy2| z$H0Nmi~}-64fuk-lK~p5j$so#f<(eG%pwOmx&Bz?S(Pr(r*PiB54};XWVA_-q#bl>6)4d)*(jWmLdtQ{Mu73qsKC zTT2DAt7YeoZQHiJtLLMQN9-^&VmY&8)f;^#pTA}xl4gV!g3WXs&box@LU2D1@n@e9 zG!nR=BXs_BSn$`~3(MOI+&-_M6*xZxEd(={g}W8FxL#P^wHOqFc18iy1zLX^2yFT5 zOt|56do}}(41B{(G;4TU*4M(Z#Q&9I)YqtRJ$X`N@FhU(Mlc{2ixr?o?8u~xMP%XF$|5RiH;b(=B8$S(T(H1k__NQb`5i=f zyHaaYI0hxCV;}-5i31GouxF%5v=0r3cOuVxwR3<4oFj4t#uu2a9 zCL-I9_nwfqXWtaVvCNKr@WyjzMI6 z#TIa2E-CjD1Hs&I9B#5G%suCE@N~$5vksFDl*uIJ8R=p1;8aX#=2^pH`+K&vy&UDc zGYjXq_ZH{dVgJM=aYB+OCV_9t-SVm(U{E zJ0o;2rz4ir5!%iO?e2wTlp`Q>#sb4%A=nNCc1vLOf|d#{+zXlzwD@Z!ux5dVzcFS- zLQiy~+^7cUqU)cDs(T#%hSxa|k+qLM%U>gYYcN0L_hISZFvCVj+LwZFNa_Yw7z|2T zOQ)%@s%s-^ZmQV&WW_Ef>}<}wlcRq-daATCy`AAN${O(-Q}1v{!`(Ci(-0g}_j~_} z^UIWAy|6l&4nj0EzY%{zD6gYrFjG#Bh1-Jf@4 zUoPqKgC1Y_Iukp4805==w4UI94SYpssATyIE@{s#%wPLI#r}Vh1Qvyr5|Ks-V`yQH zKtC=b(omR)G+0Lq(=?10rd=30Oi&sjj2wo-1f>ze#K1WXOrdG%VkoTWG$1BAZCQ*i z2E-b;gcimS#ZF|}v<}OxBDNIfO05x{#w>-cG*;zI{S0~0#iW?@6e+$~tg4<=H9U?4 znlu{t(56sA3Ry@IdNL?%xeTYEk{ik}PW**vRvL?RY`Wp-rm%&n8_K`W*I{jH55igL zeAvbL=w!&$xrx8{8xF-r7*KhOW_Q_d zSB@>iruF}3$DW&yb1A3c{z&2ScCX##&Y_Y4vKS5p2t@0z2RWv5N{5bZ+qdd5?8bpB zvmQKOZGy+HOGrbo4}Uc&H2kfuu}Jw6SSr}PE|Tqq<(?55_=>;YD73@hN^QM!ai}A- zmB8Lb37sgkj|5I~H31jN-)M)w(G7B<>z_5Fkm?>5f5VyW%F(}w->{7B;WfTD^E0P^ z6$*UQzCiX0z9A`Vf~&3$N&SRHeuL6Jy}HFQV$Q53feJP&N`T;2c}cgQjl1SpY~!P` zjSPju>+X+jxHq)!&(SpxmCxE%CjOz)5&iul#?!(Z5Hmd_c3xoQf`G_{elZJ5B`yr8 z^d>#5!pl8!Ra}=+QT@Xco)1Wv>z6b=Jms~}^kwB5EUi%I&3ZR4ZgMM(SHZ_5{s4*xJEuJA}tEjOA*0ZBQ5L!uaz0AHX3ZZNnbJV9YH@lnTM zO9+#1w54OBo8=%5Rv47zSZH3NBYgW5_R+=cwcjO&0yuz}(;(I9kz(4E!&TsLQCtKL zn_L}N3X65gTst}V_WeXkS@6}{3-=20N+Xl68>?3xG9`++=QzSKjvfIHPlN{qf_a0| z(=k+ENJoJ%~2Jq@3a+s)#RV++_L6jxID z?qc?{+68>uVcDiHmT3!itZV01J=?YE*r{8q4xKx+YuUbgzZ(a<)nMf5%+a}40@rjS zSiP_Yu{zhc}>J2^{@%tUi6@{j6bl|&zRRxi~2EI&! zQT5}HsviYcT;W&gg^kmso_2zYl4<7XF*>h&^-qXj9BX*spUjAV*g#3837h6C$ z*K_7n&YoQ-fBoeIqm59$$X>c&(H)wYv*wmGgM1lh#H`LzzCH)>LE!(zrg@!k4C25z zx=1mMw=jQ+Fza`2|99B`6mpdB{mMu=-!D1<5M6q-+AXY@$fv^|E@OQ-u zGo=zK<^y6$V}vk@SSBL-gr-5T)y35C7(}L?$6*%^T8s)`VvSVNOd^gH7Q++_3S%G! zGy^7tA?AohlfWi1i&O{`jxG3bWERIhB>k2uc1dj8XS3qO0|wQqNB@#LKMjake-{)UI&>&17z(R{7CogE zlvdL)p=l^gXc{?;X(|slh0(%pMGT0M!;A8bW@3e=k;67dO&c+yI6pXDu=;~UF}fHW z%Pfn10@S>yaIfGmsT|2-B$W`1gMnSamrSu(DJo3-1q4u7fm0ZP;lmUt3_BnNP{#1Z z9f1Y}!zqg@5gA~?I8w|_WFM94-h_rlnl0nrOQw4h-xfP?;DE5J95#h!%HWg9DJh2& zQyHBqDLH%=;0njuWDix`M~XX+{UBda+-HmYcJ~MI zsT_(d_BUky^PXp#j`*H+39AqD)Oyg24o)BLsXEkCcUVsCfu5}Xh~M1Qfw`&1@njA- zXVyh>0@2>FNX}SbFM?Sb_`-Dwt8_9Qp^Iz~g2G8m>Uf7Ik-4yL z_jpGk-C}w{^A~@UX$7VWwCM%y%z{PZFHOLv3v?q75;(GcZbZE^;dPFM*E$@Tbs(bp z?&z9(;BR1!?fx0x1!ryzO54QRzC@l8zadrE8thj2Fert^0apZ6`H-$qWl}zhzJ6Q9 z&gaT^&a2!ux8iNbP1yOGlQB(CF%%aHM>jhf+w4ffHAivEUUM{|@u8>&ha#^(!Ey{S zcb!kX+mqBhr^1~%an~OYZ?G@2{{H9&`=T1|53jc;xW)%phW7}JyX&f`R(?_4Q?nkv zsrj4^-DdXaGt(@u(Es_tBVQW);KGsPUmG)N>4Zl^NIbQ(}z6{e9bbx=I?BtcbqSrGa5Rd>A&qu{=(AY zZ%$5*;?M9G9g6;ikGB06fa-rJDgT==_kSGaxKsAp|Is*vqa6r)DJ(gR3g#;?Ku^1{ zx=Azi2}29hE)0l8VFjf{VGUeD1w&!fI)=|{gD8wBR$Q7kVjMb7V~Aovj3I~BSgZzO zw6F~F;?PViQ7ijnIu@PLfB*;sOc=l-1y$lNo5Gg3W}%D&^#nn{he1iDhYlTrlJd#K z$HZAuOq+7tK9D6-$HZY1qkvL!+(t2bSo8Ic>9eHbvimBeg~`Fun}!^GD6GrJVG~&6 zKw<8cc{};>M?egAxsA|PuQA*@8JX-7h26j8!oK}g7vA;%P>%f%YyVeX;>p_&USj#e z#s1H4;9c$RVWoy^2do0YNZ{JTPSqNogOf7YQ*BUQjlrIb!Jf21p5*>#Q~RCGfV@mf zS(v}BbqRge1-ATkw*oT?_!9YR5PTtjwH8u7fAie@jUohH|7=8^lM%I#gx5aEQb!Rr zc9|7^Gj^J(o>RV!NM)+4&*|!H`dlT`;Op==c|~CIGXIM2M$i?x!m_xAThcpwDzx*& z{_}KVljDS)`HO9GBEH!v#BXe~qj61+Bs4n~)%09s6Q-j)7Tf3yGl5k6mnXToC-qK` znNjmjPu%sVBN`lvsedT8(Sf)|`=aXaip<<}c~rOHxIUK!_r5HkdBdBgwC?$I$8NJb z_k6bZfO!uLUr3*;k)vN9GyaY7liqr0>WU|y`skUNtENA@ir&r(U;Jv(iyPm4f9tnf zkNzgqIq=G3>gKbjJg1I2@Xa4;gm7_3qz7$@L1a^Yc z-eJWKiVG64SRe+$SbnV9+nX9Fqk?6kFe&O7_=00h;ZSgF4Hiovg9%^(i!mHzGCAlz z4A#IPkq93sJ2dvL2n>}lfmq}PaAF*rVxOC&_@Xexv^*6(*<~q-kC9IbWDg!Zs7;%r zP4U;g3*VX!t5iqU`REMYzFr={uG_dSUM-Yz)i_+Z-buI{a=1Sd%P?15<`&^#?9!d& zmKOdo`{dZ4v`_wDv3Zg2(tjxXf9kh>yN>MsxDI&n<6Pu?iu<7bB94zQE3WY0kbh5h zo9qs4TXwzoroIcah91ip;mKk-q~YfwZ?)l`D#K5u3^|!KD7Vf)Px=5)rTZQJx)x(LFAFRGUP9e(Qd*sfy5(eOlM^hiMA$jun$t`I33lTf9cBLKL_pm5cx2<8vQ5vG zYqTe{#`=UNKUTacx7@9s#JkQW-0CU!FHigpXCfONjHvr-RNXzXG!{2F5L4?%|MCyV zm4D7JaoS};ch|pWNOt!}JNKU6qwk_#gJ#Zub;BD=f0{V)gRx`YdU)#lk4}C6iD|25 z%wEr!qxlQWR2v_Bux;m0rx@OQ>1KGEOE}rYqR*YlJ9ol!?zs8OJ?Wa;*$F$t-F*A+ z)xT&!_zUb{pZY%+$=^%)FQfn3_CLGb6o@5!(R*uOo}cB z#Eu~LMyJJMo4NzkkXInKP$mZ=+pb#@$ZUdR5Nr(!8%gY#h%6`*qlU$#7}8i8Sri5$ zzy&pji84YDP(}cPBu5B(=cHMg^dEXHu^3)mb$sBPyF9=LFO9-cjrK%0{57WGe#R>?M@M{v{lQni zc~#g;r4wJfDse>3`UARkeY#t}*?s!WpZD_0U5C$p_4VmVBAnvd$drUV0UU{_M%FYE($l;|*}P?-)> zd~hs8cIK>JQ>sZ#%B68t!E!CGE{a&C+#7Y|R{7b$o%1SqExaNM@g1+mOoY6=2{`gr zkjncY?~mSBzY$-dimU6iQlFOr?n*z`Qf)A&TTXG#o&kU5medOw;0~QH_f?dzM?-N* zd1*Ecol#7uYci`ZEcvW?{uH>NeM+)c6a6&3*kY?UBIdQ%GtE*uh^^aL+~z+7Pgc zKL?pppiTY;I#WX6{L^iJRRM-X0$Fs$0w|_vlyL zqF?fed&xcS1;j6@Yr^v*5?^qMe~D+2f^)Y*1fgi>(|y)348MAut(%B^1m9mXQTvA}|GfWTk{G zCgfGb)LDry3{_xNjyj|u+ovP-Rhz1gDp3x1$lb~<;c!=S&oEbRm_kgT%ufylXcZIS zO~Cr=($Zb~JNng?b6wT=0QVq=^vdciar&&#UxWR%qcCb|e1NPp#fey-_b|Y@U&Wz{ z!t!E!<)YGgC8d{D@_n~(u`Zs<(8$w<7}NV&0X^mRt|b%wbwQt!Tm z7XJR%rbvs;eUW5e;NAz390+D11ezz!HL1 zk07ZjSRs?U*#gO&e}(=v`P=26*Xp0sJjs*Yt)PGvF0BV*gN(GulVP^l3s9)eTEX(sMkE>KMK#=ADrL7uy5#$M*pex zzT@lA!c4vj8h_9?^%d8|H$%o84bSfg&aLsx_}C-;9iQ|yK56gUQhBm?b69?LQ2t5B z{HsHO6ZeJW?{Uq1%{A!_*W^{UQEw)U`B%vmf38^ZI0L)D&@eh0n~Z<_YwcaXeEHso z-hSZW4}bme2Z-ONpWd{4cXNm1vD{7;bUqzef-U0DEO^!8fG^^g$g?@@YbsxJLnAZn z41B-!{N>%@D+?r{A5oW(4)6g%PzV{3sA~LofDZ^CH~px}@)=Y<733p{qsO9YALBw? zj-WKxMSAlC0F#}S7##+|GE(Z#W)NT17hSbW5lGq zb{QaMf)*f_X<8^^K#Vau423~3L&GW+5DS8p7AEVUv8j#)$`Dz|E2G8uN(+ml^H;^F zDHIk9d_@{VWaWrJ2E>?XVHr3E#~39*S!M#uG$fgTBtn=J1dB%A-D`jtgI3^4KrFgg zQYjG%iwIR9R*q7{f=Go<<@8rB6*$^wO$A(w1F5Bi>vCiG!eV@3u>e3r^=E;5HYJosfsUHi7M6c-SlnAfBOf>`Y_pd$h+jk#+*o-`z;`gO3$B(ze zNppn_NO_v9G!fitbha4nP3A5P=Ee#%1I9ZzV9vSv23758U79ashDsq9Pv8>rWvwb6 z5z_e!F4YIk`Ln~JK0m5*3WwyVq!daEj$)JAl+eCBEDVJ~uuzyA;5PUrKrmc_()=($ z4s(YxO&So(=rFgqr)g-%n_XK*=`9r42UHKzGz`gg3>}^5R8KmCMYeU7)8uX zEkKOP<4Zze2}^y^VnB@HiztS|$^bFZX@N2+zGz_uV&&+H81fRSma$`T zL=lssg)tlq3PWVFf?!f~F#&3DEMaOuEG9}>rX=yNFCkf_4IMN#1u}9NatV}$#gYOt zNGB;o7WSzW0_wO_gr%@g$Wo{uQgx(UZ%TYsU$R_RW{#0^GjdcY%uRAs-Lw37Aj>Zb zjF;xznWaR!ZhuFe%cZ_^>RhwG68&6NM=!)z<%4weQ}FqesS~ATmF?4!53C%r)R(Mt zsw%4nsiR+4m47`>seS&U((*;c<&NiuOIWp%w}9-Gi;5T6?bDauTX4;$T;^ikXpFqB zllb!h`vR*`U~^L>(Z7B2*MZ=H`AZbqqJL#C2H~$-g~OS@{`s9f`ZuT6FZ-l#`e7ac zW?FLMT*Ef?MA${mQ3c!3zr!P6MgqG;y##;VVqam{_q&PDxy3!}pYYr{u}=qHxGQCe z5isePYs7l*uq`8^Hn@!3?v;CtvE7J*I{)-d=Y%}t9rCnW*uPyO|9MX6pU(1s*dzQY zkEoZulis!^Z}lIw)qB*(w%pajl3(S4CR^G^K^Yr@Gj@9CZ}Q978a;}i1c%(S)@4tB zseH*(*WL2e-~ax}_AQ6o+l|^rmjYSueg~%9LuuEuKvNBk#)Ui0=Sc271 zSa6I+hQDgynCLX37)6XhUI|c>QVxRQlv0b}7^4J)0bfjXrH)|0r<)E|-Pa+DkDe8? zl=qpXCYK-;{^CPkI7?+p2ek4RBu-IrKWR<-on5~^_pLn?|elm>92j~`cl)moRU5pnOj<9FP~RY zHgCRt#f&9?8-Lxt+?%>Ht~au-?`Ap5l&j6ZjBC16ukMV$vOR8vF>0xiez}pnyenZ@ zSKLw~cCistWyCBoH$_S)H#Y^2FY66Kv!lIZMd&z*LjU(DFnck`j=(+JA?ZWFv$~mr zWj+Nw%Fu0x~FV$ zjals$^_ExcE8cO>F)hj~?nT$Q7u*y7?G^tNvFMn&M-r~>N?BoqPd)CIxZfpi&#>ri zF40@v6LxsSZygr#>Gy&^I49!G5wYvc=bJ|F_DtXGmA1n*al_E04_(u$L&w+nB)`Zm zNZ<3j!Iu7vPxdyy^aI}6+dZ?lvrS<@_HN(YEqb#eiuKf3nw?F@j-@JYZ z0z2Z&C#pL>diT&1|5^K==l3+UAYV;Vwi=Bb>^AXvnkEruCP5Q(X0^&r2h9Ixgl~^X z=Q|(z052vu5$RBJM-xZdx3puKHcvXLp4wt~xV@fhX zS{Ck*pfo}l3L}KMPlPbfD=}eA$zfD5<`@|^H+KNRqJ?F2m{c4h?TW<`qn0sZM6qaL z;?in>7*Py}p)jd9GE5AP;V%Y@QN%J+3sDSyAu^_j41Xc7C}MCdp=l^A2o@ZZiYONT z>O=;_!e2lPa21QiK@P)N_=|%Hh$W?5DPkP>3wedb$Yl7-z%hj~d<<>zF&GVqg~D)| zaZMGHz7U0idHoC-a_e?q9n{zlI?;scQ&pr?|W^Yh> zqb=>(A^wZM<5%Stb)PNuRkk?v%iZRex79m$2a~Y_GWYvt@A4bHbL8|*v&!E7!PT$a zbi>O(xa;MAzPPc)l(*(YtLC<@)>9n^ceOS&IaI1SQrp=RIzCPOnjve)T9mZGgTQ9k zna2Ki_{+;}Z*K=800>|qB;lG&enx>R{z``j!Kx=KNB=B{uMXijA04>F!Fdz(a9>fF zabW>5T38~|%#@bpvj|6{g}G-y434>fenQB&FmuUxMQCA1K)PosEmW`|*n#4nxzn&1 zA_HRHgoht~nCLWeScRq`vXaA47?a6bGC&M@l>uT55KCxU@mF`?uOJu-i-QCf6)YeY z3M(87h(!y7W|%7hYDHumAunjg#FrEbqlnSJqLB$lOLUqP9~MJf;ENFe!BmVI;9@eB zix~B8#~!|v0A)ciEEXK2mz9GqR@g;d;wzafPzH-25B4bz0%*w!C3SA`s%=aQa`Htwq7`Zuj*SIb&BN%EY--WnmGDVz1-P%K2hpO3wnLM zP0Lw&wJ+#fuA;K~T}h#HiSu2l(=CUb%biQ4{bejv&mO`>tX5f4RZ?g#ES_(_eD2a) z#$EnF{xt_OZsLD?$0=X-^EqyZd&=TTYvc4%A4P~ z@4ojouB$eemo&EuWCKAaNtuJUtws~7)x@x=eNR6CE&A6vJzb7}bM^U-LgE1?WFtZn zqCq#tUO^slV9~$o)2H`m@zo*SQPuQ9-KT<{72i@Qid#Sof`!7|m^?2`M4I0T7+M$; z{)!gnRX|}0O7o(iu%s3c3yT$qB{WT3T38H)VKE>kK#j=&G1IjE=9n_Ao+Bm}Epcg5 zKunlgqSH`VKn#m95yhm!V$s6*CX82oHi=pku|*eKSPX?#Xc|XFrxlkS9PVK;2o`lL zEC$E0ScpssT3Df(LqM4laEt_In3z=LunZPcf`c3uMT|5?`~qL-45L9aESAtTDdmKw zaRkIlCPQ1eObP)>;jdyb4u$ka1xI{As+60Qb#PYdkcz27HVKEC@lfcY^w#>o;!SGl1B4jNK^%PRrtnQvwC>`-<27iMlo9kZ% zIrd+GzcToX_+{p^clJT}i$3*EKkk`c#GUR58$FZO zd5_%SJ#v#*`bJXs*tKri>$9%yOuDfn`3fU!RjxBKL6^~v2ga_Yfp3)V0B{&P3p{>Be(U3K42-+JuNA00T-&U7na+r}Qg(3WU1 zdkA(IEuHP=HopH;y7kK>2g>^u`JwyHWv_!5Jn3Vl;){nv@kD$p%)erDnsiCYobo%SEMJv%)$#PJx-wT7=B9)zI+L$#8@a4= zk+Q6j<*-x;+VL!~V@HO;^VjhdlIUNVf~CfP6@P;#$dgAVfBkY>d`H*& zWS;cSI802~H|t>Jlm_2|TKAml5vj+0M%DSUDRAa7_vC%<@jJaoZuLps0(O0pH@l~8 z@J`y|7Qex}U~9(p?I|~OrY|>_pfnfM%5R6fEbGDk!hz$Ok-&lZ4c=qwZKGM8@?cm& zGpln1Osr>7tjNjr*#$e#pa0|8i*Ah1f0~hBWVK)Fha*zo^-JIBm%WFb5Q#k7#%%Y= zJ&-v0;KaG>F2C-Lt8aeg_Mfi0>)zMyy!X|AKDDm;c!OaybvPzUF?DLsfsUQ~jb@_} z72IwwbvWuBTmM{q?k7SjIDdScOQShR8BHEOJ;tEUAUXLSe;X;0ulw zh{e%IiWQ5M7Iwz5a9JpfFD!=3;s9S1F@_@umZ&v8x)>H?qK<{d_(~4r2$bP6q8R2% zuv&bfFhs`C#TbsnrB#?(#4;2X6C&d~6Iq9;@&(GD5%<46RZWT|>)c)Y?1#?PzF7AYhNl1aMbybYSZ~#$Br_E#ieXn$id2z;>Bzc zQD`^GTWGIXSY|IPUr<%PXkppPX^Wp5edV#tD~+@(3?y*;G9zw@k>Gd)7z(T9D4BxQ z`z+FD2##}XN{Ie7C2&s&+I$cg35@<_A!RiS8u<3dUwQb~Kfl{=Ob1W?`eifnTWv<3 zQ}+6eIWVfwNLbJjJgd>C;1uH5d(<(nlp}6&`&?tUdnIqNrEO$KVE^3>h)(|*!#wZwf8)B_{v-NUAE*<{_Lan z<&8&}{%j5aBZ|+&c+^PjOiunr&uMOMMz4VtU<9Y&FNzYPAux&eG6Dco_Cmupu1WDX0Qin=@*msamtP++uF*HYCVXtY*XTE+#?^;RJ`p&zE_h0F*!Tw9 zxLS|g%|1DsY?<3UGIw}nZKH9&q&1$I>wU-U@g03McyzUY-ci5Y<7wv|o?f)(rd!{> z?anuEzw5=jfAQ)azx=5DrZp26u8*I*jy1d3HOX&!{je$3$>-I*yTd`j)1UtQjl%Ow zxHw;fpaZ@Tp}p<4+Zg;sNHWa{jS1Rx{;E%bd_bJLw5sr>IF|NB4v-3e`Bi|Sg;h8j zMQlE*bj1}Q82&OYELvD7%u55oLSdPsg%*aw0%C&F$YBf+LteqI4q|+SFsU-MFayMr z5A*rc1rOy3=ZK`(8z_Gl1TKL>|K(6vd?wL!l zDs-W}w2%N>Ny*}p(xvF#QdWt!7gj7RE;Emm7nfA9N)Unn;vz_C`#p>`uC%&1K~7VTrrL#y5sfsAp>= z&(xisDZ4yUwuPqe^-ftIxA0_qMLT=`28?M7DCi6r*Uq20tzmw%|F~Aau}!}Djif;Z zb)mU6XT|?3aeQ;c^i#eQYS^PNa#BnD1ZFrN@J-tvlDRn`XC0wtkIapJ>8m|6xBBMq zXR>r)-VwG#3K)AV?c9Tt=YRD5y9hhK%(9c${%Gy2s)H$W8{_Aj>w`sK&>1_qCA^^3 zHoZ1te9LeCS!WLZp8oVJhLZdI`x4OjwKTz3DC3(D2USSGRt^3ler50%%!&S$&xQK@ zl2so!-B*P;sV<; z4~Pj$W4v&*u$YVv17hSb?+G|2#lS9HrjS&DSSezn2fT;CSL86iXP~f{_z+p*(jb_i zG(K`z;Ol^J4~P|o0Wsld6fp*Z@f|2O6MWIa!e7N=uq!NrXWe0?N7NZsllLB8Tj6+I?k*p44_zQd?GAZ$D!7=0o#E4>{u*}_pzhGB1vVt!q zB9P&)GC?rdg~(`U=uC-7V_~uQN+v^I(A)!H$NzK+Q=n%Rmo2?f^xgJ z*YL_|XJpnd^MK!|ecs7OLz38V@FSOz@B5DWIAPYokrgdaIJ(qu8+n-EbNKWQ|MNTi zXEd-*WBYF6WV+V4kr|~u_~smpeA5^v-fDjZ+wGaK{ILnuiO8vTO?)nTLbGQnRh6K(#lvYs=(wg0oc1n!e%pP4lT zJKzqnS@48%L_b0?bfxh3OZjfGbaL|>&0*?es6Mt*qOv%u4o-jV@FPKlunY~Og^5T5 zVhjq)svRJh7f66zBGOFI0>iv&5yCP-i&WRb5|oC&0%G8cg9(lSF-9QL< zu-Ke4{ReYDVnB>K2En}5LSYb$k1;e%@SjvfF&Kutj1G$;2EJr5;V)TetIJ`^RaOaM zox*}(Qe{G6vM?9mV&b5Mb)PImM*osxkQW~`3x6e*=rq1aW8flq{v=L!7efxI#WVTk;9|{Tydx%XhsE7 zj?a=EoT&FM-B%q?@2IL<>NWKWdigi&b64sHzMXfdZts7>DYBQ@OUrmzsiJgIxqU&Q zy<}e5vN>hf&n)}Xgo?K^%a8FaQe1@*#}i5R?xa!!jTvX}j4A4lF6@d~)X5*qahU5u zGYUM{h~_C^(Z82;MqOfV#1JyOHTZ(Ip!50b2%6ayIK%Lt%J{4iG0un_X9SHgg7S@k zOd}+%#V_%gTm0Uk(eJv1JbzZy3qvzLu;p#`8N1DG+=0;ZyJ9YG4Ifj>c7&mm>H?>? zN6au{ry1ch+CpcwM^0r~kEXbyc2=LZsGmasAH5o6lJ$F?yF>@%jx zXH3foHayDN=aTYl{N(1~DXn2Mo5LnGMNF>uop8c8_ke%KKHt&%eDV;yhtRyXoW1^e zN1(iK-eL1E=TLC|f%s|r(=Rx1LCN~Ne*WIWzgd0P10P*{!>KGLkn{Aky(_w;D{e+h z^!U~|Hb9(IJFc|)qy4NP*+X8YMR#>~nt%Ks^7hHu-pb!v;5y%!LU2ciDfJN`&;fQ3 zhJ{BfSFS`b!YueD!DmsvU)u*ned!JIihQxi9g-3%mvA&fSSTzLv=|rW7X>CyDv1yV z!H9icvKVu;pfEyMVj7K{R3X2Jd;jcJCUI&oPsI}mj6bj2^Em+KN8=0&nlckxg zg~4Ks&@?Jog3?eJ9}2@_F<1;2EL#f1HlrSmK6A+j!7}NjE^ox6a!gsEL6^rk_ELGXch;7OgR)56aG>n;pjp3G*!*Hi+)9P`-08tr;AUj zUd0!2^p-!joxxxFw3@YCcQ7yQi?nZEjyQF3SxF&FM^}}V*sJWNi%W}^loVE!6jzqA zD$!M!+V7uae>JOgUutP9{7oorV~iCEoUq88d=5QJ+ z5p`(?2#%R$M4xX&%`_s@32Qw|1ckH*M`%p}+Ku zdfp}GCC}uS0#a9nWUUG<*dI2&!zaHpU_wjS^tRy1?IBa!LZ`LjN1WRZ=$WA9V=mco zAa3e`v{?rVF4=R{9cv%`{U^Wq!v|OWCI$}nx|Kz5$ zi<|%ca+5aw8MrbR%UsRM{8Qprn5(DGko#7a@Djx2?(q3(!Phl_04@xPGD!)Y2&b4) zEWu}pCUhH2_qKc@zP7BoLmYERxOdeKZXODQU|tR;acP;CrQ|TbH)IhlSS(tYl(#}y zEYqY_L>d%>T_LY9SF(Bvg~@_o1TrbJreQH!m^T?i4kL}hF>+Wvy99`ttR-?-qSLS# z>_TC1j0u885d&h#D<=FUB}=M6EOBX-T6D1hnnD~QGFn&=EbvvjSP%?+F$H3@Fj+YS ziy<$EFnka!T3D%L2~b01Le>~rSPXw*F{UUCeDN{lFccP1j6*p@#?ZpB7~AbwZcCsn zL`5Zb2s-F|Ze5^rc;pH+r@a zHOq*cX+)fBgggGs^(SX^2T$t^nA%~g;4vLh(~P9~oo-`49TN19p}v3ruI=w`L4O_U z`NzO9Yt4m0uIL`QtSfwWM`(^=8)N=?jcxTBdm?&zW7yc*(1HfPDX08%k4NSm^-W%H zOZmVp;q}1eEzx7!{KmEVviQdMcHe?}{(QzZ`s6pmZUWJf<68U^-aE^Gcf-m zon4)s?8RWNVZ~xrtm}+{D)cW|S>8%C^8eyGSL$~G34)<8a+t7yM5LiGI0nJJQn+VLEz!b)U4b&G=weaCf?z0&Bg4c{7$Wn| zgJ4F7F&-ku6o^F;BZt-FO9Ef?FDB0}5tIhIDlY9zVdBz)U~vSy3cfH`xUAyRio)<$ zOmHlz!mb&Ne$PZODcE)7%tR0@>R4Fpki|XH82Ac>K{JXN5Q|J!A!|zDGUP=dW58D& zfiLAaj1hxi@QOng7OO0UsAdL^DOAB~Xe$U7hogX4SHysr3abCmo%BAY`>Lm@%F0oP z#2I`l?OWR6bmx-(3I~6!FRP}0&$|Cb+CSabE7u+T6;HSQ{#q_9VJdWCSy^F4*+NiD zAQ~0SAEiZQ_TqAL9yJ5RrR?os&YoUWRkVPoi3w1jYrl8A{jb?YZ)MEem2qiJ^t>)} z3iKRD2%1sgIbGqG7z_bN%oc1e87E$XrV^SX72*A+uNmksf`!6oS*L6c7Tk8j}*5C>0eXa9xZ0_J7a z^AvFCxN4S<9^!Y?5bvAM^8dk5uRHnsp6!magB}PScPQjMBk24tc8g%2#PIXYUk<2j zo?H%@*@YYqpVE|YZo{bAC$cU+GIrhvmsNi9=RdA~_CIU?_|Gl&d)j7PYZP4FQLx0A zct!K<<+VTf#i?grYTdG}bH|>#-FsV)A8DyQ(b3$aLMG=$AOf6Kf1f?x< z7z)c^vFKu@h?N`$!J>NFln zzOp;%N+V!)w{Mo=Kd!@Xd`IZm`tSJudB}*Hhk52ncoSaGYL3%5;hN?Y5oOHX$_v*5<0CVeDbOA@rUB4 z>`a}xb@akd&M*G-SHJ)8`4=}o^UCI*KYsX@`xRxW1;n@l1#6+R#KdQqx_a#-Lsws!F)KS&KnK`N*)%d_A&PScEtJjfcrNp`Bz$L03 zOEpz4ja!aNR+$Plo-*j`m!R*wEHD_Lk~xs;Ofg(YQ+N-Egjfn~K2$VKMHhh->YbJV!hZbBSD zJ1$Q-r(aO`g9{6PG<(q<7cTnA?1ewOVE+9V&i~bg^L{gP?yu7?eItEwbJDV|n2MH| z#YQ5le-zhwGe>?6-vT3eOub9kKZXX~?H2ujYwQCa zVZR*~@=MRqN4%qd`8~g@&URny;$t7;xjZ1@Ro|@Ulu0|rOnojj@ApFkfBv1o-wzM| zwP(mrh6dl`5%4ox$Q>j6@A{tY`z}5|9csJ%?7*M6M?W5z^JT^_}f`m(^1@6UanVyU2K z#pf*L=q>0qrCe3RkrF{LDJGM;NzwQq82*|M3}0~t4q6x$EbCZ;V2qj4yfesQw6L&P zM=(KqeQ4N1UcoMfgcnH3;^-!$!xEH64r8!bg3@SV#)tv2IaTWkbFvnr!)RgA#e!o% zOn@5f!e5At{*}-)jxwPzSrx3d@E1``iAZBoKrBL7904&UIGC_lIb|i%BUVi}=NWG9Xq#Y}7HD7a>egT39Sf zS){S(VzjX8C;jy?y}wBvRie6|Dmi0EH6@PTj(*6wTraWs>O@seiSh^UsCM+zRpDUT zQI-31^hTtPUZVS|1-)Kn&iJCSva(4P{~ooxoA`6avTi6G!FGq0#>g@wV$v?xQ6D4}HpVSFl~C9eIHS%# ztI;>T!IpK{Z{!AB)So=Vetu5aug?zum3zpeE|I?)9`WGN@ZSyz`q>cMl`giWL)}(< z*ZY>C!7B@Z`02)_RA%U(%Gwe(oM_YUCeow?6ymI``Se9lsia|`+*dH%EqC?0c3i>AOXihk=3eI#e9H*WYet-1zB`*>fHfZ+idCE!m`&# zXK#s_^8Uz~>zA*1?EByU$3wq;^|8lZ{owr_8#f+ayW!}k8>%<1Ke~Nu&5mugq`S5^ zAb$7lYCp2iIDVk}TYi7XliMd@!yX2?oPH%a_lqs?Nq$_2(MzU z+^Rft)Y8(zcP8+K1&nMW@z8pxKbd(Yk!PZ{efE<9`qh~ovV2A?eNxZ%*S>sR$Wgt1 ze?Bb6pfF)}!qJk-pfEo_h`_^N-VKc3B=A>2%uf{Luqa~QF#)l}rGYO$V|XXwFE|zo zlY(6_(ZBc<;*;{ulT|Fn5fH;-3{eb@fiebsVKH)8D2xP#!WjA&Q7kF^g~AvVMhiT!FudkqSFu==2{H+LS7^=4k^qP1QVCW1j@iy_=`YB9V32Wu0WZT5_*oMt5BkM zDoe*xl`UP)lBJq+i8@yuwKPuFa>$Z(uHRpYel6uo`zq_~sMh3=s;?YNd7mxlg{ncl z1y!imwD_uya-@P}^~%mA`qBP;)vU$ouf8g`)IZ&rExU3^-sgbbEh+opi?n`Vy95VT&$H>hd2^(BvHn~J@8XmRI zE&3y$(07Li{Mt3>@4m4cJQFs#M(uNn*zFa)$s=xyN8|?A@ISf*-gl1gO=o*wG2HEX z-|z}s$TeQUmwj*OoFT4rhMaTJ5V!e5d=`%gxN}7Ky>4Om4iEfgQ1*Lqb30=$Gh$}7 zcxP@I9=m#I_aeRo~GarkiK-aWMk4>TM()OzGl z+wp@PCy#cWI$_k;b~iP4x3+e-wskePwlVn%_9(tj2kre={aP+fOHN6m@SI0{e1nXLu z*Nzqj!OY9TctbEKY%1X!&7GAngs?d<{6lkpB~&mJ2EmXQlWEehSXactU*s@_I)8=2 zq&kH~5tGU^E&hQ3F>;ucA4`~w6a!-Z`G`v+jb)4&IShPJ#DEw@j0uG)6j2O|)eLF@ zu^^aKh3bg|B20DwtMY4TXlR~||bBTWROZU}X;haI^`sw!Ji{Jz4ZPho@JGYLABmoM zAab4&cu^O-CC1F{@*jVASo9i~(09FJKJbit&o%a~5%F(DkNxxXIXC4@|C`_Fwcgol zY#BS#X1%`r@_TRm{;z*>@8b_Y^6Xz9XIY_l)~(yKcmK(qd#m^DKhfCS&6<-94Q(~G z4NXlQpthmDgE3$8uePJ^RC{AXXIq=m!G^&dOovAK8lTO7?*8@;{VEBJ1B)e#1B-d) zk#Ar`7J`ciDkzbWU*HRU(1Re!!rwFNW`pdRdJp830j?!A`%9fKXQ`8Sqr-w=gfJ%IXado^X{7vafx?(RIt-L`93yp=IrCSQ0AkU?l7e7|4mSUd z5W@HlDQw25p)f>74ilZmF{9FsxHJfc$fN|NF?6x882)15SWE{o(imL~g3a*sOXkx| zn2Jd2j`)DMm&w+>5fzA)BOvY-#Q*hw6^_<%417f$_bOxa|4u{fjzrJ*s5 zmN2zInTgX786k{AiYV5Fu#65<2zmJ-iaB>V={c&y4AOCKhZ8NGP|x<)tfd`Gw!gE! zc)5Ndxlg@K{V3&@tX{J}Uq8jU{r=8!F4x;pNBb;PN55R>i`;yFcfyxaad8E~=hE_p z<|r@$n6d@)%k6W^uE|_+B=AZj^76LiW$irbo4UlD1s#8RYw{KCahJ8bCLJ6ezI#M8 zTm9}p-g-u?ACa^_dEDx_tbcmOt~w`X_gRsxd`r+my_z;20~T*E$szb;Yte<$eY zXZ!vzZq%~4tXn+e|Km0CwV>!%h6g?28TF2L^r!Ce>xYN^VTjB1-}PK+%Xl&7vZl}l zM(Esjwv7mx+ZAzPYw-A^=5E4KAGk)n4S!wY-t>xHoi+Nev*#|KeExm$S?iMWKb&25 z_qA8vanlce_S1VAPr`~$$`S(_Tz^0`~4cwuagSK=$2>fm3uLZuk{%vb(ILEmf_eEuVbQ{BTo@HhP#Ody zgrP9x<$aS0TBaCw$YI`085)*3TD-kzVGKu!Usx>6l~kcw$|)2R90Omn{7Zpj(ZW!e zSTqzSMGIpHVPeq;VH|WZK8hG3lR{z9!tfUdEiAfN2QfZB#xOuE2v%|!MJz^%6arsB zEQT+-SW+d5B@2b&uY{~|{)@iaLR+d_K&*>m-4`M&U98{>b_KqaKwgXzOjrzp304b; zNntUfn4q+b3v&nuMJ(gLmM-+=X8Y`r&V5o{)N;s@Rn@+9$8w?5%AUc^SlT~>7QU%d zzKT2NE685KgTr5)k+Clo@|qRC4v4`PW5fKYLExZkM>dZjn0xv}@cpHve@G z|7dv7U)@6f*MZ@3ogd{_wrcn>X%-zekUpI(ee0 zwWR}|n%M2=AO&7MD{piVZKl)|ypWf{Us4Bx9sG5ON<})Iao@PF?n(qN_hY^$#|`sq zpKoct($QI{HoyT*APXbE@E7zTej$;7N#Tk9_EmH_`S@5`wq(!XBWB*K!#?+1^#XB3 z3-j7#Tv%yg#)Wxjcz-a0(lRv6n+A*Jd13S~IOd&Xf;8e+jG#2J1%xmx79S8pVFJ;Z zU>COP{MCI9Vf-6OiUWedF)6WVSS$f*VKEd|a+rTy;A_s%dh$s|he0qYrTg+g9ftPm`6SXiuxEQL@Q{sLT`!opvj z!V;_&QLI?3G_oLAaI7c{ktq=n16;DAmjN+_!eS`=x&6daL3JBdZYddL_fw}^98RZ% zHl=4 zrMFzNXlYQ&Q{K^Uy2Za3l)F1%`th?zuCXPr;Vk!rb++WU0!FWizr+Y;d5}wuxH;W1 zvyJ$#v85_ zF$jjm09R)*s8w7RU-*kJa#&Ij418fRAVv<8MGiAx8VZABQkgZ45EexYkwGvxhRecY z;?kJR&H~L6k%r59XxgEP%>)eh>R{_0Og&1t_kVrjSoo`g(qu8kV&w>e6_<4ogIzrf zkrjx6FNes2V@V;e0yI8QR&p5r!eTKYG89G>L*&!#TB^S4KdR(Qair_gxU^=;p4la6 zMA{kPbX7rJTCc2*>UX7A7{EWXH_E)@Ga6tW;7-2uLw&wigSm>lIz25fUd-~9_NsY2 z4a{mBHdZ2YhmN+LG6gNZv3a`Xi5#tAnN-4!_6uYBCPfYle2Gh&&ksLg zK0yqTF$RdCFeVg6AR~cA6pN#SSVXbJrOmNnhe;MFD=jQeFNdwVSeUB^s}**I%Ty3Y zm4jnUVOJcLRni#jD%y%7CMzH&3wfmw*^5D55x)Xrd>lrHVX<>p9GDlXU+L9Up>u1e zTOv)V##Q!o+tKUOh-ycC=Ty~KmsTY>a=I$9WL0^ePM;0-SyL~RJJd_QZT^|PF3#%n zg_sW&msD2Si>oRYE-Jiw(#$6!GIyO5)9xDEeO6e9dt{eenh|_qM_Oeo@#nb9nFQ6~ znRMJM=D02QSk~1>+Dc>8l`KNlIAT=I@XTtr)cwIJhXO|K9+AA-CHYOyxL1eAzwMLw zN<)0iH-_DdCe#N^Iu$VaWMDp9HMJDX{c}n2 z;>*j5mn^=jYUxer-@ATt{~sU!`#+xk&#JfH{$$;z4V!mt+qrM|uEWQU*45NB@>f^i z%q%PxnS{TsElhRp0JSO*Eg)8kSfJ(ro4GZE1%KaoR)8xMmbAIKnXe|kmJv;S$rB?5 z5DfdG;F#`9d=n(Sa3{M zg4F_LQdQ0&vKWqVSw<5`(Zv`JI7SEq;zu5N1O!V^8X^mh85+hUK#c>4iHeXa{wf5+ zUrbc6V3$;hV!^IHMl1*xA*|yV_)4Lous~VqVjKluaRkAVI+Irr%u#47KB&c~CMmL4 zlrM#Jdwd*Hmr9|3P{u$qu*JhIz0s@pB9eOP$+uo%N)Q!VpS9!8%M&hf!BVQVx`1U!mt43zu z$2uV_0#a49I4JW8SHF8)J#HChyY4LC>sh8Fe8OhG8BOjZ4+rMeMV;3f%_hZ{c1E&c z;#>xQjS!|lU&4ll?d)?DJh_ft4kIQsMvrR_8`~Z}tu}t@_Dc$HUdB=-Ri%romR+%w zZ_1m0@{^zc?stED>Z#}6c;mg*t9eL&*Up{$ckNE(T%t}5t9DYRr&wJ*_8H?JIpU>vltK0AwFEc|rAcn^6e z;jjFjA*7(@XvrLD_$vrT4(kzVSPY0sMGgy&p{k&k)PdQagz`R(!xEQ95d&X-UlESR zK(GX;@u4t3y#&5Qr*TNp!Vno3>T1jAMBI_VlXoj<3SEba^MKK6grUWwlRqB|dV3!gJM_am{k z!FgkUSzJ-FpuA{KX{jy#2WR`NILG^H7UdY?d7~}w`NYc_*nrq)RIN+$5zp)s;pcY5 zfZ&U}_+$Qa#AWQ3*cmddF>pd%z~lzM$qoKf>jNAh4xZSUchNHoidL|ANI8pLS1w+@ z^qQ47-+Jd=_dM|6Lw|kZA1}T9+6Nzgymi~IeftjsU;YjsK5?q1v7xR71Os1F0yne) zU$$M)7Tj<=cBJSl!ROuq)^D7`+?UQ`?nfb*avrz|zd zd-;Wf$+$2P z>Rn&F6Y8zetR<^1^bI=l8lBVrZb{YbuY#pq>RSr?gPo;XpILPSeYV`^DT66I-CN@7 zgK2h=t}&9Abo=JD`sTC!Uz6A97T>(~;QaQ0tQ!AO2i;=VGdVdR z<(ZK5f2ECk?ED#b&s$J2apsDoG1qwoUUQcFHJ%~&jtKgdTiP=*i%zglB8YcOIpLO4 z?VftVJ)_!pTwTZ~ruY>Eqkp?PO{j^9*t8(;>!+~u4N$_sH7WPW{owHABj2uwAilKu zp68pNVM@ZJ@IonH-X-7*T%>zjI!1rpX)x8K!NIg}x|bfz)%&~d=a#FRu{estqJ=>) z#t#@M%$q4%n4mPq+sm7bsf9ZLF+u6uZ#UPG#`uR|Xc+zqf)#~TP#RGTi~SSU<%8U%x5te3{7I>taS zB{-%e?ll;VE|yeStU#<3u_YpH2~Dd2wZPXI%EDz*4D5=DulOsDP*|nHUx+L$Cad=) z^)LRpout1CdTZ3NWcxeo>nvBV(c<)X52{*!6)fdv{F3EDme$Cs8|bfs^C@4v#PTZC zJ$&(&r3L5qSs19WxY$%d_R=DI*_`F~q~6&!?ng$#BExgEVaqW5a$9WK9bOrRcSg5Q zMtA1q_w40G3+z`GEZ>)QgOPr1XIxQtNKUs;UbEkrHd{`se@=&gPBRZEc_r?3i{9d& zzAAmveUr|+eC&*p#LR2FVy_+%uyTa$s^MPOdj#GyBH&@Kq*d{AYokhy=tV}rlxEMY zlb)kadZbi)j6Cj@e!?%mKJ47K$cwr|nR#_?bI8O~5fd9C#y5o(G)GKqj-1%!JFPBb z=KIKM_Jt}ct1PJ~udJ$Aarv^9H+}z(+wZ#nm%n=K&wqX4`IkR#d`0|zS-op8?dUyF@812D_t&OgU)AZeP>%L_sLw*x znmUncio)`Yk^{n~7M9srgrkMOyvZ1HSi;f7r7dNa3C> zmY}VS1uGWgDEKNCgJ9rGxf~@cleHu+4UWZOnik<`2ZtZVK?q~8m;f~trng{lS>{WF zV}jBsVjNNjlY1s^5tkMaJ0NUQ7}{bGSVXa)*fC?vOq3!P{tAv2lwmRamDB=aMP3V$ z;WCFr3!4mfn83Q1#^(Q>S*(OGhd?kO*8l18#Vr5ygU@ohUfGh>4}DX9&ntBL-{;O$ z*0%Ipjg0FIk8v$t86Cbk%|2P}KADE^Xv1%Gd+eCw%$8nQRXXj;HCZ<`B(7|aC~6DM zZSou46fmaEFQ*O1Gp+hNA?sbDHuxlMagE*Y9`la7-yhELSaFWmva|fk-2Jce^uB(G z?+wGl?{kg+SLB5UqYJyD78v2P+k&SzFud!NbHXeAxGnvpExpD)t=e;RZQ#V#;8~4< zQ%{CWJ`pjwK4d}zQRtw_Cqt$kg~+q!J;<&Ti+OmtoMl8R$`_Yib@`I3ue#<(KfLY1 z2Y&VVV}E)6xfeco|HDliH}BrHhYe7OxShr{iW;l5GMD?J95LtY~^UcpNCDII~1}qS6 z0$%}&bAQvj$5-L&Jy5PLC4(tf_ai5&ta9{5RG~P19_q7DKT$5Er>I~N!n}>JnD>)d zw1lIfFu!mBF$g9W&D#!z`{XY_iZDRTKM+A_0@3_q35EH|1bH!W1hr&!{wm-Kk<}q_ zAhK{7_<~@}3{3ZKeJF|;A|sGNF#N@UF9B+R>p*eO05KGnpfnWbQDQN)u*}+$xU^uG zR7^lDP$q@H!eRyDK6SAL!LWFM=(O-xn5(D4Vx7XuS1MR>S@^5|_0_+x{!g#EjU078 zq?f3s)LHt`!Tah?EDa96h5l;lE$e=N^;NlEd60LdPU*7|RfwZ%s+LuWUhS*%Etiw5 zx}4>xDnDa~2K95zER(Ow%NJJ_vd2=Pz3kGerBiP`p7BE?^ZT7%lUi(Lu5Z-;9WU>Fk(Sheba;M*1!(FDopsvZH^OExz`e>u$g84*2`WKm6&Lr=NZA-S^?|UiRfaaPaWaV@Hoy z3xBJR*VLS>1HmoLtxSQIKlsaB=yr#h4<$KFDD2E%Vc*wDUUe<~(sgxp%<$y9l&~`~ zNxstgZYS&v1;7FDg%RjAnR6x29EteVyM*rR{lwWhT+O*euk1Lr=XB-w>FDj~ z6`afU65W@x1}@Q$imzWwe0l3g1;m12k;A;h{K63}EC@yj17af5{3`%rhKBhUk%yJk z(D3cO`z!HJh5=%wg(0$#7qE&c39LID0=O83q!NyH6qs_DtfYXLUuC2q7?VgfL21Z~ zp^Kp~iWq~!z*oZ5AQ)d%FsY(24lEW$tXK?%k;bBkVKMN`Y-wz%DF?!s3erR{cT$C$@9|{ZN0t>L>cS{Z$^IT(zU>=nXpi zs+z@duIb#e<&@LP_Se3poHq3m{Sx~9^jF7nx?auV>n-cPrJBlGT2`m13KmBy=!MQD z`q6=X=c}{$Mj`W-*y6C9A>hjSr6qH2dVa#4t$DW_!Ltm%EWnB|La`03mcw)ET*fyVWZ2<)xp_4lU@=tlB?;jq&$riVB zc+wt^xP7jXF9oJ;wx#a&PTA$1dL(ev?x<;Xar2EZp76cQ2%Fl>enufv>PYzuozxI8 z{*-U-Nsm#-pfHoNOumn)4VrM$Z$gdV_=ey~ZBY{%5+>EmyyOu=&uq(B$~LcMY?NGS zud2Lq=`#3>{=NT~4?OzFAO8K+)9<|f?uPXn_w3#){5^8)`0-=a)yGf3-(CbaG&MHE zU*K!W+yGbP-dNt5uOPlT`BLRen6Gi*>zE2;PI#8EGw{_T z&-8@T;%^^4XTYu|y|m9%ou`gcqWnG`b&92?bGcrk`_im)iMpJANcrlha%9Auw+;t` z!XOyKQ52SOVT7>AVS*3*D>z1mdzP{k5EGivDU1-t_=n@44+NVqc1+MR#c;3na=2&H zL$VxEN*SLLI)GGD_~!Q*2$q>zB8urJC}JTpKiCLO3y38sO>|l!(lTEQA8CvMVsI>S z7!{0xVCF~@lm@|=M5jdy3y6ituo#2Ff?y?wRaQY+&@8FKu`ZBdt_WlhEDk*%UrazO z6qb|{;H#&?V$~nizpN@5;9uWTnXFV+j>6{#a7dVS|Q{nhO6to~ZC)VE}v??kU4K6O+fJ|BOTJuOFXhZD(GRF)T3nB*-g zS#WhZLEPet7q1+*a$D|g1}k9rW*dH)jOTVSu*;-quZ-@G>`opd!brPEj& z+XFIogI^-%4$T`hxrsma^9`HS6gssb*zp%Iw$>-J+ILj7OUiNPWqG8T zL&JVqM-wJ*&piK?ahE<`RB|;N9<$Ri6b8YlU>483V%c)O`uLXPtBLOxeyj8GA$$YD$vlw<11b_ntUywoP!K4?7qq>l#d#G~hDk@90K5I((=cbl+ zR8#tia>f1*S&mABa=L2V;y54GFW2W$y#-a7cTA>GN(osBM}uHu(WF9Qd}0o~^ZXMi z{t}MHL<{q;!@m(D!pPytd9``UmeFVS8%L@7+;K!xdp*w0Wsy00$&^?F#ovf-?YzvXmwN^ zy^h6quF&VX6w1dMYePj-|4y)1RZC+h5Cio6hz1lK!r8 z2IZ<*b#=WFj_TPyeQ7}*vScY&ml)VlEvQqZL~jsZeQ8+w0Lsy1Ioltx{uK`(;a4oJ zT)bk!jax^Sb&SaF^2sm)vy6belW8+nT{Q1*Ib9l;l*>_=e%{ugnTGF7BlM!qsPl}7 zSzW;wbj21l_$BW@D{TXtGPp+n+mi*ak~h1ht@Tgd<(j@NVNQ4Kd?Vnz_TVYa;S(ER zZoo7%4V?;$8v`db2Tf^)!a)Ufe%W;%BTu-b*Z3wMch5fIH?A>m%C?IaUccD>*}J4( zJ_B=v0r}qJD-JaQmH4jU^Ul);+qP}nzwf}2!$*6?FZ%Zc{)y_7I44ikoT{yBY+!Zh z9u+J?SP(2Y7WOF$D@P9nf2BB9vX`qgHa7C30+Ax{<@=T|ZAKMk%(p+~Yv};eThzNJ zS@kcgvZ~r39o2%~Rq*xG)gcO%KS)Q~>94_o8&T&vSJQ8=KVLtKI!Xo8@i6$yuN`91 zVjx(?h511!Dwv2g4j`7HVS1?`__o{3wX^WevEd*8`1adx7yc>)OI%tgESeXL3Ro3< z1+VPECz@%MuagwEJ$O>ixB3ADRcRkx?X7U)hT*q~;o%OUssBvi!%nMW6bOt4W)*@q&vVSY*GlxZK<#Np&H;eF|q4{U&?%Zpa&b zo)I<62%lvH%r+ut7@>J5+>?*mf}i&ef5tWKWA~KREb{C&a;N2#sd$`@J)gz&7|TPHdO0#KcZg zl`l>OryR%5hd3|gIJQ67DW~iYjtc`WAU1EZ3`jx}pcjM&32D&H?>YauOH18*@AEw8 zoI5iDx=!u0diCnny?b}}zt`&C`}x@Ozx@-pKlrg1y!!Dkd*Jaeec^*;WB2Y&NQU;E*^Ui~5OG~Mz?-v69$_{5jI^tUj-;SK-lHE;Z%E?m5N?czDN zUo}C9ngdOJ@R$8-?lO&-84PWQF1!_M3;37c_kJ6|1;N2z5bO^Gf8@g-{n)Sn#&14u zGx$?>f!V^4m*wjkqc~P@$H4&Z%-IKs%a~2}Qi9*J;}6ka{Ka21N3l&9FC2;HVT%oO zIPf*M+kaeiJIDU*eP*W9o@vb9ytCv6r?QuZa5_IpQG$O^s9Yf`daRO?kK_=o?8RRs zx|q%{XxM~!q@geq*cJE+7KHjFi@0oIC>#jRHU0|V%MiAL@*EK$_{b;yq(uyW1HsH; z0R$J?!d7&ydP0yl#140lQX`P4Yk>F$2=Cq_2EKq8!48f^43R;w5hMU*5NwZFU$pGG{xmy(AA0CTvTSqa)Ra>oflJ2 z$*ejQ5rsqapi=g%aKvWKRdg5VI?WY5SK;sFD?23K;qSRik34eu?Qgku{_=nJofrPx z!x!Gcx%=qFYu7Gbe%pmddfrZ-d-S1i{ocRxRd0UcD_*xd$$Zxz{nYK>{=}Dj+x4&h z7B3FJ_xIoNxBkEj{_%hGqJR7QU-%=>`9nYTg)jQ?+wT7VzU-Snc-QMc>I2S>G~3LD zzdmer=j(s@d9VKD?GJq7wpV}1Ip;6A|C7FR<}FAjTIae=8Lu+ zymLq22ti@62!HWzc&2wBjxG%C5VK<#vI& zCMDCwO2a@b%D53t4T1&DE@=Ol!(|8`0rKwiS%F~t!VKZyueFnqP2u1#2o^kCJ(+VO z!KyMq?9u1x2Z%fDhAzylXrXhG${a=<*}=Q>T9$JO@lJD43xJp*EU<_{Ff2B#;+l4i zMI7r`&jh{}y};MCa2X0ShoP{+7^gJA4d%MCg^yyN{nq6G#1#d*J(M{-*upn3`N`AN zLE!@8{xs{kcjo?dvUmAXI1pWCrc1bzaEe|ejujYkmHY`tT&kChp$FwpW3=uobr_<( zVv9+giB9ObW_nv@NbS*~<@ukb@8dVWeB{j+{_0o1{gYq*&G7g7mw(Ik7kujzc7gAB{YRg5|GU26g+F%di{A6B zuYd1tcmLe;zW!aeeBHnOeJ}j+FTVTTx4rULc$mNBHNOdb9lL_Rx4h=Vcf98D=Rf%I z7dQ+3>c{Vd#jkn%me+jr1rL1mj#oc%`|F?hiU)t~kw?D&+9N#bSKqRG<><*z7N?0s zO?pfZ<_07(O$C3AZuYNFGQR6w?|RRB-t&PEeBgs0bO!5Je)T9gzcd6G_u&tJ*zXtc z@iKvfwqQ4OP#E$Ce1pFoC}$Ym=E!@j5@kL9_~U*+&Gcm&jM;12G#j&+m`?sK8lMG=%%n%kV5j`xyQ?pi#A#4Q&f@28(<)Z+OL9j=h(^;;tIQUyA3{{1I zETRnFaC-De@UuI}We$@pTR1?>5VpFDEgT?b1w-L}Qp*Yu9K&MB%OZx$z*hjr*(OHt zNDFaCyH*qsC+N?JSj5IDLwE>~H^y%uxT1x^QiH<92^NFk0hAfV0pkAD(0QN(bN}d^ zeeNN%%>Me1mDKBwl_8)G5!+Kf!j(%j8E@*nq|k$|y@oOl(XMJS39}jmozQd5^tO!D zISY$62rp^gF)v(t>$N}q zRX^~dJ74GE^k=^Gwb$=@?Qh-jswZ|QqF?^0=iK*O&-%Kb^TN?BcmMS5FS~xreNVjL z6~A%kD?Wbf{f|HAmA`rWD?j1nm2XQv@4=5jTkdE!@AJRuBe%ciL$^Hm8@Imt6Mk{{ zD_`~TFMaUS&wI^pf6asc;jyb1u3fzJ-RH0Q3|DR^caa-}zot9$n`w>V0HMqn2EL;g zKlzhC=?K;@{n9TD_**Cpb_H0B1D%7>P#Ew5-?*S-5Tk|QFZ4`^eYy>`LuxV(%tR#> z@zIZd6!MyR*cv87v!dw{@|unR^3hKU0^e--y73?{%PZhp_`BF8I&<;ic7a3bdM?R0 z>mLO6*FUS0cagbP^!{aa$yB(mJqexRlWPp&n82={g(nge_Kf0=&H=eNrE>+uf~N_H z8O5+ThOnm$f)mOd2E_V6xub)vv4{(f1Hs2$J8H)}4UY9O*EpqF#MvFz{oJXjfXU^Oplx*nPNTPf#b-R>GmHpDW%U3U)|Ne{T9}~H7;h`(%zW3@Q4_|%jQS5WT zJ)Fyznah9jYc9X<)>nM`wpV}Zxv#i>%l%J0`(@r2{>-f}`OIw(JpP=o{)t;Bbq?*G&myyE(uuXy5)SNbKv&)ojN_1hl!Z4PJOlYH(2zwYq!oezBcwg*4*oY#K% zc@KQ*55MYD_q^`s?*EQ|^c8RTe_rsqAHU`9cYpcaKXT#WOYHHtUbt-kcjynIndsPn z@CZCv!9Gca*~0NigW!a}@>h1|u&1vN@JO?Q69U9&5G-^EE)%#LyfY}vl3Wq9 zb`2KCB6ijH3@9O8kwwe|4iNKE1K(~P8+RshL^_3Yd939_sy z>@``FIVE3HY_!IZG(`6)I<3)fWLMtj&R1Q}MpDG0Dq^AMB1jSlKe_mGFEeE?oPYGu z?|$scc|VGD{;k(8pL_J$`D@-$>J=F1OH9(Y{^^%|_s`yS?-O74vM26%>1UqjMd15> z>#kRP=8IqY$y;9WtG9mDzr6K@|M;$#{g3y4=RbYn13T0Bt_QB)_2Bh8UgNWqpLyN` zpT6sxKEV-uU0$|40AxZ+P+F{DQCiSGT_CXK(wO z_uO^&&wj_7|H30z9=Uk_+_ftYsYca5_ma8Jv}P(ZQ<+c936|W(?~nY*kL-?M{lYIm zRoGho=OC|Zh@i04;O~3i`(9bz{qA>r(+3nYhka=(=dwWX&If%IPGI~NGzWGoiePao z&Ym@YooUTP$LL^>m=bT8LGN^Q)-3Hd)dKskh~Jz_5F_^9D8*agbqm=)YZ9oaIF1HnP$Sj4%;{tfaL-4PiLg;~LQ z+@~KD`}C{ob#o_4QVH}88%cxYcJ!z* zRvTn!s3E$jISMN&H`Q-#5GctI#}<(rkCLuD{LgB;;d3Tw5f6N?T)ODbdFjg+ePiS5 zTd%^o^WF>Qg}!#->Sr^4F7>c)PhB|ovWNcum%jQvU-Q5(f9Zoi`xW2v?_TtpcRl}s zPu=m&*Pr{!Pkg~w{@?%6ANr?X{*wRt;4*GM@N@3@4|jg!`)+;7FMQEU-uH@c z`683P-R{+Cm7vED;Mv&Sx+UeEF+`zkJs}{nJ0qf=1v2=#PEuV=Uqu2)sLp)iHEW8u&&M!O#5jKmYTN zSE;ZaG!q)wHQkx|Opm5nv#wwsHb1+;fNwT@&F5xyp(gzCS+_@)j?oyOLrVRe_(>z_ zc$HgpyWEmImKbU{MCa@g80s^N?aAqSw(qDU5m^y=I!s`XDTc7829C3KViDU8_Dlsv zF*=*Vv4xq#d0B}^T3`#qU)R{ePQMof!`z_o&I~>Z!PeNe1J2IT$^wFA5rWPkbj2WY zY+>LFc>%F2*cIS!9Mn!JAa-ZA{`TM2nJpu;K@5DsFgw><3Ypo@Wp@so|peGuYdht^FH#I zzxv0Y{gPk2{qFbPa`$@?FM7rQ`{t{c-*)-osu&`*Ma2Gvzh*Gg6r;d|V1OHUj$rw1 zpnvZ-fZy{T*a~5Vg5XZTR!J~A_zSWFzRYI`PDujVwk$)H7}U;Tt>9^)YN0SrcT3*n1k?|&OWY(EM56&=w3wW8ERYn{fScBZ!Na~e+7?52nvH>jtf0j zU<+sK#ML8qjXN45$K7G+g*Zaszm(nKKyaZjAhu4^XX1zknrK%zi*VJWgc)|pB=n@t zNya0Cc=we{Vy;kFFJ%jZ+F)_q(E(-MnCm9?Z`{!iYw<#d1A^Je;8?d8fUgiBW&)!@ zuqYb%##4=8>avl6GVlegqG1M+1GV87A{$u&Ws`s;^xC5w9(_gg?B;9ql-Oc)t*mDP zf4-w|>PAZ7X4kd~LY%&=u5E)}E2y%p2^`8Vg#)pshgc<57Mx5h;gmq}xvrh!a(w#X z^HvdBNQPUbQf=ck0r_P*X5-`k-JNWAeR^cy@72<8~ z;ETo&{&G08e`N{&0$dt?;wOH>o~&O{E(2BLBv1l)`Gl)&pC6u zYnlbopV4V(3g_&dnG#E;Ct(iJ65F2`^zWZ>Te5(%i=Do%Ow(L(|WG*=L^j((68V`33h~|HAwH;=^y>^M?QV-1)bC%Ul1eFL?2k{!! z2a977!(R)wtl0v=XhgP#U4z1aI8J6)1EkF1C$aYEUj#ZQbbvVPLs#I7Qv{0`T^?ym zU#m*j5NM-7pEm>o!A1eXND+d<28*#{QED6+vk-Y_6(7Ay42W^Krg^Fn0u*)y!LGnJ zrf~>HZZOvs;JSvuhr(-pY<^6=-}a{&T54ymsV)9N!j^ThN2Vn$D~P#PtDo^@m)6 zuV9guby_^qu595T?{G#-HwzXAUIWAd(-~@m&NDw8sX^Y3$iZKoT!?p?Q(DmZL9J21 z1Qulx8z4A{qXp>>jv+4;j$I6P(NLI;Y)nC3SBMOGC4u08uMrmrM&Oh=99!6sLK*rd=8Il({n;=5^z&cx z$y-41z1Q!&=Q_@v_x#$oJp30a^hwM=_U3nf&s+Wzhru3s`4p zl}9shs-fyR4n)ZpL7?b8i6KixtE{f4Qakfxbm?G)E9Hn}45uEVu8ZT! zts&$=d+3G2dV-G41ZEn;-}DfmoC8|A4OfX?6gUp@#v{$0BIt4nx?hktS9rP&wTlp( zECJtKiRtaoJPS*N{*Q*m)||{7xK`ji4Yef<+v27)OA@h8Q3Y z1T%^OG2{ixP#7Vwg@d^va)rNO*C2Hb9QS82(EXW8>Q8Er+(_+8&~wIcN^DKwZ247O zRjG42JydT``MI`TXQ$UBi(kUU2@(Fl+&@}s2R+3fR26?92C-wKL-u{5rL%;KgBY2+ zU;n#u^moZFu)j+eS*JeS@z}$cAAa52{^g5);QH6T?fMH|`q4Y?{m8TL{WT`=ZTEfn z_Lu+K9ryq0ox7h8zJ9CC-`)Q2^)J5vlegdf@h`mp#zHs$nzxaFf?ds3=ZBsOv|no7$)s{9HDc~bE%|-Cw27fy1-1=!%dUUO1i)z-LphV#Clnk zv6#h4mO)8RU876YK&;7ke$UeR`_R3r(KF}j`b$2{g5VVm+$l-cFO3ixpO+5f@ThWF{?5-MW2|6+Ma#p z^wg8lbLFFFjeoLI=3J$JAZE#`PbF2B;vm8-PIh~rlx+A5CoWyPc<-P5ci;G@Kl#-c zKK0!De&yDeedKxff9Maq^4Fhz|A%kA?_+*j;nsVfca#v@OL=8fFQuHuH?dzbVeVS2zn~xe6@_dSJYmJY93l#?)$iH`6SuClhb%punza z*$oD2`(2}F{M9!2PqtATBjFF(d$h8YWD$c{*I&6JQ_)_KKcNPp@G# zbPnZ%+Vhvs`Q4=5fv78&T&whRk6gQa`Okda4}SEXKXv`CH-GAjUh#o1y6@NTeCdau zckhSpc*(Cm_oW}c_2r*@*2{nUi|^g-{67EQ>o0iV`U}46x1M{?ul&bf|I1(fs(i#tR6C{%HXOk9u)qM4C`zx-XsEUaX- z+Qa2fX4L{;CNP{Wzzr=L4qUcPEMyDVk!IL!2O0QsJ_BE#=N$8Z?1s5{AQOnGhD~9j zW9Nch)u>5QtrFNTg6S0I3Wd4Z;WgO`=H7&|dG*iUMeD{j1GPMKtz7X z6`5V}&GatibC!X#sI9U``H*F1mXa>n>0~+RTG@N9V(v-ETau**r|2#)@Ou(E&Ff0c zRe#RYchx0y57(T*(|`0F$g4-8IZp(%<(xI1UI&OR|6GMYaIShLSBxt|I0p}czdCIP z(@qaS9FUDbB{6kzD2WvuK03QFR;0i;Sd1<>wqAw5u5cOJ#v-<0Ml*rIF%*Wp2@GMY zT!t`5Q>^0{%jJ<~6!TGo;3I2z_d>A%h+_^Lr*Ihl&JQb3s`vwu)cvo+7?F`ehy6lC zd1(_Z`m6{Q=yj+fQgosO677X{P6)cisB3$Dj2L*PXw*^}g$Oyz#eQ_)VYw@_T>7F|9xJ z@}K#(hyGLNul&ryTy6?VDLpmwRZxsC&OBoVfWHPNtc1Tgf@N1X_zPr%wnwP@OmKwKMQ(7f?lC}=qK41*3Ut3@K+y0Sm{Aw z_zQFOy(3Kivj{+}LmCm*gaSGcY=Meq4ujxab4Cl2;sj42DZ~t_x)x012ZCJ-h1Uog z0=}+sO}oNegT*zz=wNYZR~9i87K~qkcNz_pVKMv-3LDo3ovQ^lmCOPjptk%~`C^MwWM6z2H|8-gy28zU$&U z-|*1ic;HR{;OpP;lYj8R_ucl=-@NN(AOGrC{QQG&`JqQH{P8!x>A$(}P5;LqeDLwR zzT=5!zw$S~;ND-o{k~th_dEXa_g;R-)yr?Wc6n#)_EIWZ_gJYWt0U~%{qCE&$h2d+ zFp!N+D9LH;1tRuujzD)4coBaAF&V~kT+sZ_;M*3klUKF>Ymdq5+88(9*}ux-TQdup z*-UiI5cmsoO_c%{qM0*64TS*ilZNh%?Ol`Y(Y(8JHTO`rIS|zj13|1fLzbsKS`|ZV zS0<7rvmrkuCF91mbk0QOs-)t~M9B<9B#T)Yi-QlBKW9n0mlWMSCD9M1Phe= zoKD_o$oXeO-kRL{oDa?PVji>IrVgwUu$$R(FmJO|h^ZUQ?X&Jo_eR*C?oA}u5Zy0Q2%Y={Zkj~d6UZ8 zzg7oGUj1%om3J@dUcU0!mCKJ__TKJ8mmWQL?XmCngAP|5kbd-`^H+Q?>(NJc^U$N; zdEp0M^~S&Z(r@|aZ+PPm+fcrG@#rIy7vDa#!w{|d;CqOG%+v((Y>k;@ObCXpvB~cQ zF--h)rP=B_!`#?6KUmV6yG(8j5Y;d@ znkNIkg|n(%Gb&>4t94(9?bI&0O=}`yTV_r@L6%tw&Qak9SHQh@Z9}vt&2&nf`TKB& zyB?xvrJ-u*zCte+ln&rpeMUzTg2L%q)_6IW1%l(0hR6s#P_Pt?MeG^~4hp+kC_-VF zo2}uXumvQJz!4n?4tg3;A<80N#N3%#*$a6~2FH@M9Mpkhh-@73CJAU*95`kU7Z7tw z2bV!Gi#Von9MpD-1p}Y&E6D3Ai0Uo#so|lzZj!`O8i+Uq1JiOIP1? z;q8z5TJ-rV7cM{a$TdGTeA#ER`~dOQOON=u!}C|JzU9K7ICu4&mwX>R|8{`-)^pc} zTN|QvU*VgecCOxcyu;$(++rFre)91N6Mz0DrBkt+9i@N;IX!1m+1e4XRHj$qu!dOT($VsE%EnGbA)o&VelI z%;=b}CEV+__7n(9+6bj>Pa^dx;a-PgJ_Uq3I%O%_8jiiMw1aDP8-{SpXIq6JBzfv-*B`8lR- zXa31J^MgKH{U@u{+17!!RKv{{y;ds-vCJ&S)cYSMKoXwR~| zFXT&<%)HCju0U8vq~Ct=%J*Hk<`dAnUs<|v<>)ouOP9{Q?b@Y_Z`osXxuEp4n^&=_(qcjTm%G2@aF0i=@;QC11X3l@s$?Yg*dLV+-JqvnhfFcoavfBSn<`vY z?WJ_)({c+c(Cg6aHqh6uUS!q!bB5~L#Y=q7JGb-si{~z0Wf22n5POXm`huSmJh%IX z)|K-Ro4@+fJKlWpv9}zd_r;C<->OM<284OZT*TjNo-vu2F^pX6WJ8dx%5}_#TwkGt ztt{LDb}I^?yxV!=kf2s0K%bb7CD@cYm2bW=P;9H!Vg-l%LH?BW3VN76C zWuH0o1grkN0XLGm*s*lAQY80$c3tga^}4__gg*0n_D67ncI(Yj+1Dz$#_vi(r&hfe z#SnJYy9A3pL4OmVaH7FtOF_ZV&?jB9FI>m8^i@k%0T#Q){&f|yDa;U#FB*CdVFQ0F zsbDt*4IQat{NhLzg2k@!OGDuV!}-W2-kqIB3-DLSzHmV>6gCp`O%LNShOjGUf2?!! zo)sshl(u@lMO4yR5sR9`bgeKKm!#s07G1=^tf-Ei?8T`pAu6>C6tfF=fzCgcj<#dP z4i%^|+cS1%-NlJ(-ZdXfrxX?Fb*Nl(WgNRYfBDKeAI-RQ)sOc2dWN@yuUXw~sI{F@E{q%roW_ zo;0I1OJDY{eOnG>-?PdQXy6NE3vkO3jT63W?BBeF#CPotVn?t*Fje&muq|NkIPh+< zg6%^Y^=1R}2J|;^ndO)sWjtZ}_b0l}?Oc(ZuXC={E&N{3 zS+aB1?xJh!@`uug>T#!Y5uI7LMy&JaT%FT%6~D4e#hj}ee#y@S4GGDv7exjEbJM9@ zbuj&(6&xbq>uN*@WeWpeeKIdA!D3!$z0`PN2qS=R{L=AAvxN(Pd7;Z44T}?k#T`r+ zX{bu_2wk7NL@be_5gnQX#L(G*as|6Lpm^t@6g( z0A~vr1UrHSg>5|9Z?fbzIhd^24$N?Ko%+CEzCqPf|M|W;2i>D{vpf?xspNb;+q(6q zysf$V05Nnz&yuQk&LS=2%zw%rN3Ue3=PLDjMlx8OZ4Ltg0gGb@BXmFGf+1{asy7CU z^Nz49z|GMtgaC;3+xVps*0FlB^`tABV+R40gQwXV4rmsbib7{#T7Vmb4JR3kvky_W zFwE@%9E%!moYFAYU>9r+reKH`CycFuK8&l-PLwI;dE?{(Oq z2PG$~^PuE3(W>fcl$>qer?*X%-fyR()lhp9T}kL;hcK%P0=`>ey`IgffH?0ph~nU~8c;Vjr|!lZl(Uu$WP7J2*x$2u2HF*XYaD zN*MlzhR)W;)qn%B-P#e3OkD>Jq8myimHdWS$((?wigo?zCzVucaf&Wtky)vqU&MUN z&*b`7%U8AcB<7n+#+kp(sS0$lMP>;M1&IcKE%mMN;jg8;wQ)9p7^iGib}Rgaq+H7I z7rZXwZ{S!`@HZc#luKS)z>H{mSkv_(%0O^VLB|9(*cEL$GHaR5%xNr+azU$SuY9NL z?uyt>EwQsA_AD-9^YyH%@pS1Ka4pqvn+MhBQ2A1x_N+qp*OQF;mHML#i-W=(FWCXn z1LKqy4Gprvcca%+x_vkORmw- zxquiJ3&t802EhqvRxlKHUJGFb&iECK%4+I?=q*1aRWvf&l545>v!3Fd6|qsnp42OI zRz*L>diw3G6&;zi)RXaVhR$A-eqa00J#Xlf)ljZQRWq|VLqVdZ9czBGP2sO`YV=w6 z0!R1@G}*9_)GNSHHTb&-!M1~gzqW~kzpQ3^$38@96PXJ-Zy`B_<;^DkXZqQ{Ifdo8 zm$R3~zL~*{WWF+kncU2HWh zU#yrcYw|s*$|5|MGIQ2+7QZVmW{8cXL2{pHuUn_(9ioG_q~;p?HxL{S6xQqFh31h) zyT$|#90!GU(FAY|b_GDpJDmk2EY^+Lzpimg#}^HM1IG|q2n3f!42TPb;buXqfw^ep zmcT$P3KtL;9CJqlUm*l@I1tPV7GUwvZpTJ@!!8O(ppu4Y=XZKdtYi))W`#3{&M;j| z|Dsr>K4nBzY#`Pu(8an8{$jMtce)GjLnrSn*>&zi&l*QFG;$TJ)@;l1kf#ObK_Q>))=) zthwjyIy+qzJ3Z0WE>>nJqU6J`=t0Dw^Vn!rY$)Z}jK>NL3ipgsJ4-Gy2eGP8@Yhts z$!0z=W0(z$eQqe$C|HEQ>|ZbNdXvZ}H9+v5`0J!rzQVx-X8&?Q=Ph8`*uV8d4FB*S z{==BSc7eTY=&+@=x3O=oFio)<%w{Gx^PXu?Z5QvZZl|YqdhPam#$)BXlAdwqcTT5! zu1yhdPIvJh@MpSAyf1~4A~c>Jr(-u-y|~7ac>GU5o>QMZq!fO|aYz99wXfQ#yulU1uy_ z1J**=5Hcq3z)yDg3vFR8f`H=Kzvw!h#qtHj%;DZ>i*%Zt1dGzFg4k-?*T&3(WL37B{N6(7xjoEds@w?2)=&pGmS}7$~CE^r46N7xBv)HkmK~Ln1 zIS_N|%;{OSOONENq37z_YPY%sr1m2>84>Ab)!E7-j$b;quvKd|g^eA7Ic%*6bJ@S? zw}`;8mF z%2k{qbhhem#YB{nf#@=w9>j)dmkb?&P7hf`hg>C4{8^?am3)XwI*90bOW{Ep)`Yv} zS*FSw2$BOwbdedcS#vmm2AV7J5Sufy&-97IT|O7SC%< ztm~ZVH3$KrzEfaxOUN)m#wgFtjj zg|?DJBOrlD!voI!fj&2XU$<$yL!s z;vmf>-0RutLBOq}rkqVHpPV+dk;jn@{iEnW6+eT5@v%l<|5fCHY1 z!D}XP*}slpc?+pNgav~87BF+$7BCky2vz|T0*k;LW!5r-fnal;887ppyQo>T?g+8i zfS9w)KAdW|S#6aSJ+r{+IlYFRUaVEsXS>|eqxFuJECIRF+Eq&Fsmc_mh|0c3bV>bi zO>B*y>^-$OT{D417mJV-4V7i!BvsxW65l}K5CLEKn_vZt2nuIk7zD%LbYOkhN>VV& zz-|TjYmsT(F@e!WpKdSgF!(40g<}y1D+8(ExUARk1EZJ;0bg{mHP;)7pTjHxsmT=% zI6eXX_9xQmv~cGXU5&rNk+h*9sY7m2AP2{RK5T(g;FuCO>a_L-mYKRX}AT?{ng zZ(c##z~2tUX!x5CLHi1aw~%PC1soT&EnqHa_HW@YTRW$)yzkHYcJL!h@tlP=gYoQ{ z(^PW93U*()so{P*6WwpWOZK+ySq8P0rHEN!&%QyQI3t}yt%m4Yp($~na=XIHRcdEW zl8WE6SFV95Vf|bkFu&ZaXf?XNH`l>59)?*Rz z-nhmh=8@K)1rQ92fv-VloyiJ@!f{8tipD7ogpGn+VQ%0UK0@08TRV&v&UTqFOKh7U z97A}|#;*n}d974*QY$(TbKaRF%dtuZwWozcs+MU)kcCbNjYbqbpOTW=785v=p#*qw6qOL#XpGXO8Q(q zC@HalD6#M>iYUoq&N3TG8^Ur0e=~6OMxhMh>T$#gQmpSYj z6lVMyeSkQIuxPh}(dC+k!k{zOu4}>!ra{}n+=|YU(MBKyg^0>n4RuqAq0L1PEpE_o zX!cotPlbDm&HA4qoD($lnbdr7$Uj|`Ig>kzlC}OY-&*h}D|yRxQ-l>b$g}Qs`q6=8 z=c952i`~kM^%Y8x$^_oV-ykv(qDN~R?mW-D^T)tYT+*;!3s7g ze1yikw+UFpg}*^zwlE+TbYtKvFo9j+uMl%M_zQv=#R3Sn_+$&m94-hpBI1sYIqX`9 zX}nY@z#RwzPh$3sZQo=W@VE5LjdL?Nb2}eeO4pE??NAMaeEPt^oTI(mIra04Q^V&e zsP^JB`W?`iYqv1-(*l`2Ocy2xW8ZKFe9m75e>sYQFWhAR!ryEGFXC^E-+-?x{Dsu; zT1I=vjzBxd#gvA>*#gdszz#w?g_XCE;(}%Z=OgfW5h?g?@sh<&<> zd#|u2zb1e`XDMdoD$Xn%PD!o_9K;`r8=_s+q2+c}$xGWjFiY%E{d3(q=d9?eUMZ}5 z!5Qe1DWYy_))Sd@KRqym2%%fT-;5@^B-snrU9D^lE?28ZK{q~v-`xck?>y0e{M_Bt|36M0Dl?3@kqxCE?YQQ9E-RRbFhdDe`lNxa9746x`t|#Ly6vWbN{JkJXGyI z@_8uxNdE4T>0P?hLkp}usS-O@pd=3>Zj#!A>To8)z1x?<#k<2aZ)E9imCiF}>>JVc zUfI9=&kR!F$WZkIf(%&S)5t4GT+raP18(TfAwY}?{0qPE3o?RWPHZ@CH#u)175*}T z`-@0SV7tH$VsSyMiP^(!!zss1FlDJ{AXv3C`_(-T#6};BWCSW#$rnfa2#f7GFb7qo zp%b(Io;uSdKM;|`>{*8Bo=IKo#B^2f1R9d}1Q}0|WuuAq(N?!vCq{I?^uY8Jbig-O zFgRui3%V;TE;#1E(T8IW!{V}tb2N*e2LX}wb`Wemd<4b2W75W^D=Szq91IG9AzTm~ zL%3|)HEhiZs}k#&iw;;9{)+C?I46@yyB(W%Pq9JI$#M-!em6ulRKLw3+LJ<`ZNn~( z%3j2xz+9_m4rj5#i>->83B+>U5*@l3^%mO(9ov%;3JTe$j!Usyy@JG&W&eWIMf_#+ z4*1JVW&+zameCO`U%`t18JgEyNcABsCa_&#h|lf@{Q?`@L1>4;%rF-J>c(CO{+ibI z$KO*vn#J~9WGZN}o%g9gx?HaN$PX15qWfrgx@3l`4$%|TYX3$%f$|}X+E$P>Jheb@ znZO{}$kJC4!C&ATLm2XcU{|3a*a8^%x)%Pz+(58v=$$kAuYC5$9SjWzHWCVm3tJ0D z3uF;>!g)v)4gN;BqC*R8M>R;=XIrc{-I^plN$StHm~$>-omr2jGY_JBxd&xDTjA5+ z$aZ}e+ifGuS=DE5UJuveR?)qPjVB(-jjC=W4W)~22p^QRSm8zen1#Pq>G6hHV|(eq zC$Jcy!C#+i<}n7r-XsF1Yxo%FA zXA3wkX!y$u%>@mA9fXFzf~mk#-~7W1ZINK&Qd{_Iq7xQxO^dDZ4{A)pi|rYvB8F0i zXfJC>qM<@+yVG?P)(Y*~7@DF~ot6Gl zI1uy~2W^Ug!dB^K0LyRQE#r>;n=RnHf&_nkL(&l}-;;!={Rmd~Ja@VvIH#cDFALfh zF#NTl%>H$m~EgK!hkql=(wPFN3xFI z6pmjyK}KCD{dKcw69p8@B)}EM(`(RyJcp3Eg2AFs za4=W7j$tTIGW=x%*Ac9axt%Wjty5UcXD(fYSuWwL$ z5sCfF1+7Zf_Llu-Br{bY*lece>OZ$wzsI`Svn2{3qBbRldA0=|q%BRc*dRBlO$N0? z^q|TgBz#u)xLDyu=04R+tz35id=#?2O<#q@0b&lEK(MQj9bs^spnJzD%{12At%`-h z-*}|sjz+^@;{p&Hxk2IXjxLKhN2ZOVjS&2eK+*f$^@dC}NGG~{_?;7ajbD<-3Y6rT z5LN#((MHK){V~_{R|U3-IeW=hQaBaeCJqwbR&|X7URM#xDi1+hX{R8vscD}SW~hHwTsL(4JYGQ z^%k>NDq>OKSmvG?tDr&Qp4o?7qP3nmv4&aaKAhZ0mz+60bsst!a@9Fyu~3XT93bYs z0l{c}*w7P1U5&wP5EuS};OqzkVnk5b74iyDIEHXGg<-MKZQ;<2--PaG9_WJIPLSE> zevg&u4N`P+B|2+ZO;~d)G)aPUct>rrO1|wg&dbHDXag|z0rKC7(MCC=S$($ko zsVOBD-oFvf@CK>s_lPz>KrxGOt8N3_fDQh#J!AiR1u6D#@Hbz9b_9!s+YR2CjtLB` zLAEX6{1zcUHYj%lE2p4=yZvP@==>IvpJNFAD%vhE6Bq$%;H4tp1AmW;i6`ZR+Zr>->-euc$cmD-6#$vv5~*vzT2 z=A?Z%m3=0T&7LgBij_bw0<%XuUGha7T2N&iO6mMFr|TBZT=Sa3(=^MP&VBgGEits2 z!8~9FFxa`dj9EjH$q9cMp$t;~VSBaqZG*p#K*Q4DT;4euKESJ6GoPwqb1lv=l zwp`F&bYg46-}s-Iz#y0jY!{d(Tzzawn-6UPCV? zFz_`1;crkF1P6tg!v(}4tdJ9cuK;|Fg@AGaF)WT<94t1Xh1w%Ff`p*3kzTNCaG^UV zNp&N85_1bAWB6-ID%U{F^0S`K>9o9}vxd$&RKD^im5LTEi-*A$eQ_!;5JI)p`{LNQ5nAPx?eGTHhh{Oe*Q&>!3 zA^6J#t{0K=MJzLksm4-4ZP^PZE|ZwMs3uK=RCJ9vwB6R^qkk>+X7h);>&5k?;vZDo zuA%5s)d{IRxDMVr4Ga_JeN|O%3HaLGZSQr8Tmvj@18^{8Hi)E55}UIbB=vJ2SMTnR!Z1*NM(joHxvP=j<|a0UV^W@#+vV zYZNSU5!xh>x@H1{ z&K~Wlr78kLbkJF;oftGr>YRP((iY*0t`Ym_>@stebkPKz*1Ay$1Rp{1V}Q5c%$ZY3GcgEPbRd#(V2aKP*CdC$gP3Ru^rX(;C@xtB;V7)6n@UvW4<+`m z)vS5(e)qZSuBs}~nWbcAo|4n+oTAMGS$G@KTvbM>r7!%2eb5jrIwA!w;U@bR{^l!K z$J)QFU?woJxS$=u0^dGFSzEw4f|V^`Mbx*TfiJt;+s6!WyTDw~jBy8{eGV%wGL`_xuJiMtU}A}U!3ZwkQa@A z1j4(EVOYLsy*hM!(b*b~MGS?(uE6*;W@7@w;uyk)h7gN5=CC6Z@kK-AoiqAIu+oOY z@kJY11O6sD+}B2Qt;LdMF}2!cPQ~eEm1Jjjx&)3TdVLm!yFjNGg^y)!Xh_n0jn3lF zMO4xnae^#^s-X^22c3)ZgUqqfu4ES8C$;BVlkfb{Jy)l@WapoN9tsjIC6$!n4}WtY z6QUWXMx~`MdlUW&@Yg|Q$EDye==3p3F6iM1^oAE23I~6owj)@+W9bxhT+npphZy35 z4*upvB>v~x0_K7S!A@a$5h*TclZKhZY-0+7zu7n&Ah>S!ltgbgs)p#I@-**;WC@f^ zIMLQqXL^>IIX#!u9xXb#`ZYTrmx&lzu9Vmr;JGRZq%U!N~Uu{Z`ZcVN3wG|y_P!b z->2NQT)o6?JyJK6%t_%4Iv179d6TR1_UHz45L>K3XO=3=o_DU#8mI6Vp$}UR2ZeR% z0CBd50I?7V&eguK&L4L)EEd?p28F-`2Ej+B@Xi*FAq;Je8W1eRBF-LhT+>iEHZMX5 z9Iw^+(3`E6*-$v>tSr5S*Rl`78_{SWP^wC}k}5SxCAmMbsI%0To)Rl!PAX0jvz|&i zD{^wdM?HT{F0jk0D9L*5fat2o4V_C=ivRF&9l$uiK*LV+HolwdajgJ-d7{Q(TfdvpAi( zR=0s)C=7xV^kiK+A)CTw5eJBY@6q9`A7uF&1%TLa5CXxjF@(z~?yn33Vh|ksHRJ=q zF^U7eu9!n5hiKjJz@MZ0OD1n`z~r5Eo`%zP4t1N8PE*jHc@;WK_L}t6Md2>c=`|%? zW~LX5h^ob;S;IDGQOP26O;0MbmbyQG&@)8W^ek4jGY373NwwYvUPiQ0Y@KWja`WaB z9L!JlFJ$C`X09??8L<6_fSJJC_OI010_M1O3X2OG{{HBX{%BqVjtT4tR-JRiCxg{rL)-g{$--HI?kCp=S+ioXWcN^b(7? zmJ7ejFN#HALoB0mfZ*C14iLKiezAq;s9oVcdriw+7~ z(1r;90$)?X;w=<&<1R`j#C+FoQy9c5O1@~s5ba4Pqr1YYTT~@F(KP@oG57D(&A~q*==AdUWDgEC_hrdR#k!!#jp3n`_3CvF} zXh)#!)jBQ(H{mZga*jZ=e~)!R`$dMrUvB}&1?^QP)^r_#t|M3=I4)==FbFOaST&fy zUPN*#Os)JvL?GA#-ZWx*vG~tHED+3U=q)p}Lr>bD?yV=+5Zy;lsv;fZ4x3d;$32ApDK} z>+K=m&|t&n2z24^_W7&AU%B!jN?X7&fq9{0|AOGSpy6+hU|HLUTcb;5vxq zl!%GK)M0IJl2LiLz%DRNWoXxI(C@t(;i)02sY6ussVRLfrK-`BFne^7?u~hxyI3r% zGdry&Lv*ojH-q^!maFKLo^Bin?!IUq9w;0`80-%Ci(@Qs3JLHR_y&J-HCTjzZ@Hrp zaJlaY1K&gsYTN202j$vdIL)%Z{Dx$&YTCJkkDC9<5z*-qxEVx$;$8pZEiW>AuHOyx z;-d+3Zl5*&=^JXX8q^N_UZqOX@iMOC&N6HbOrU0il?&QiKdeq@m{*Wktj;ZiPJ6g4 z**XH9?`*7jq4Nq7q$ba5wgqel8HhWARbRo%5iF;mIl7ev?zy0I3d>u-!Cy5IRLQEq zK`dXSgum7aJZ6^emJMbbGY<&PMzC2+=%eiPO?{|_v~ya%=tN7^Q(wc>Bo(MyRef$Y zG2DJtqsm>Z(o^3`bBVp?MbBb&BPSzhcIZ0#quez;`KU+lF2P?A9H(?_VM90;u^|AF zjb({~?zo}q2o@X!!R%AEDx)<=u)GDFBhUfgZTmM{z&QdP z{Ivzl1r5#Vfo%cj6m)ih0kK_R2ch#tN-k&+Y?sP(VbUga}81Wn{y6vN*lZx z!jM<65Y1ZD6%glWmffY8!w7@LNRLw*A+Uerg+|9N&ULY#YFJh30*lNp&}qWQ$`1lV zv};?Vt1(Mp=2Q}5SEn0TNpj#+QnC!uuIFi?Q{kb`iKafgd%F?BNo!QbFzZUTXv7fh zN!#>|GCxP#c9tP^vFJtSkZ~hg_r7-f8+m(D-Q5Z5Ba0C&SUel8MyPQIfAa|}z{d{^ ze_5s+#Vl5Kt1V#o>j*SR&HnEO{@VWy{xX3{(L~9yx%L<6%J6P>%u=sc;C2_bdh4AEpSB}3{nFj^H>x1tdnRqZVkIs;bs7SJ(= z^?4yyaGAic*rHTm{04q0UV=ud&5V;YSw>O!)mQ!YBDD+GH0=;lC#*h zi_BiD;YKQ2M1+TE*YNbxL&bU&-J{#}93+S6cHW-4EAl9G=0UXFv-~1+7JCXfxw{k8 zM;4h zA_ae)f>uy{2#e{RBUqLJz&9@1X#-iFTRo+WJ+6n4${jUk+UVf`Nv8wkPQ zLSdr=5W9xR(X1H70peWamkt*1U&BFic%X^84r0%=Xxe$LwnP1g=riYD&Z=UAo*}yb z{mPiIf0jW~_JJe1$ehKtIj5}Hw(?_BYb|ZeS|`I_?p%Id-dz~S-n0XoSCBv?tYrU! zPDik80hbFJ@`B*S5KsowbqXscaD9l9PQQi3xQ6eF0KshS?t%^k1K)(WpdEyELd+t8 z37pSylo#46!py@KFeACU(=_jyJl|so*(PX`Mhgbt&zK!Tca8( zH&tSYKrky<2ny@`fY^u@fG=}6!O$oyW(C7y5F8XX@Do6Ac7YK%XVr%D9c^nK;OLjZj09Co2ADN3h^8uw#2V4P{#vI5Jml+Sgi~>XZ z2#R+bOxDw1)f0D{isGfjLC? z*L;GE`zSwinW3ITbpPUHOxQomASwI65xt>x;r}cg&Mdknc~kjAHH=v!G#f*~U$_R~ zID75A+KLVS!b&@~>|d`DF=IKCecNhJ{4EpMTS(yB5okxS;(uoU)+sFhXKw*>L6-^a z1!Ok3Wk7a;EeX^r5X?hf?*ivtBu+E)hPkD@(7|8#duV&6i4M(msQmCCD!Qhp-^f!_ z!?l|H9{)^Qpg+(UU$fdSBQ?*xUk3<|A#6|!AlT4`!U1Af9KSRI78~+{@gf|V!n>D+ zcQAbP;*#r7nJRSPS2O|@Ma-OHO6ro&Si0(2M5;PO_o=@u750(eQ)W#k{+=2Z#fI!d zbTP{!bFF%d!i&tsqD$>eEGoh5l4~+Io8RjYcrsv(Q{&MXj4CAH>f8FVzXvD9irB{ShqEYpVKPoW6#==(Q5h zmS6Snl`rN{)*62h`yCujD{Ztx2_QNO+Z4{A2Eo~jag7yhT<}60AdokPuu&hP>|)5v zE*5&*_Ogl}=2{eg5GctIU1z5Uv16k>??BIa2Z0`)g>eXkU&LZ`G4H@!E35N6J!D^u zc6oG{8KROR++{ZCA^Q;B$T%dW&=Y5;Z82}Dor$3WCyvgV2hIsJcMXB3ERw;N)vvQm zc?H;y9e_E8ryW?XU^}z6XnBmCoAN^pIRYK~Hy-9i{OwE-oKw(DU@mATFjW+Kv$(c^ za|$|dApw2m)`vLM1pabC=O8o_xORc#g;s5g2fJ79!c1a0VZt&0n2Q8=s;&CH4|H$I zO6tr`m%u=DnKim+*+*uOuW02h&P*Aj&4<>f?B!Bhgx;>t>--3#J6Mc>!VKZyF9=S^rtpy|yhG#|!U&<)vy}IG zhS|l?v*e=KAi0>UYbMa6o$h&O`cTQCpo$g|g+sKLvPR3&Ly2`}r%Pai=evTPEgfAu-AdTzib1`jaa>dV6%-`$oz8}{7qX`JD>7d^z5Z`Ai7MaiB&XND!NDv zYKLggG9;Zc8qHlvl@(?eKo^u$mM&1tPL#qTdg?%z%s>ocCyowkD>^7#;}feS#E@%9 z-4;k*y*)w0>i-EihB-R6aIVG(6b8ZNh_((l72xCaT7{nLHgkHeq;}4pbg3Q6owE;; zv%vnGQiT|D^`y{)z&_DAt!HS*B8pm}PJ(wG)x-oY0Y9)PtE(nN_i+FZIW5qS~{v6lYID#yurVtXH*|Re?pK#10~&YREEF zxQdHd&(i5ZNf#azE=m@&irXMccpx^iEG7-vD@wR%L`4^sRBEzxnXaVMU8d7rrs&c? zONLXDh~iYA2e{UsqPfNd&eiD1!4Fpu929m9C>uU=iM^~fdd}53d(x%6em zk~}d{IuTt-=Xbix>_aDSmz+6sYAjuz z)ZbNA-bJD$lN$Ytk{irH3CZFZp+=(N#%v7!dauU^E&{%J1(;3BOAIA#+U5u}3|+K; z3w#lUzacvQ`U(d`%QRX1DGu!N6uLCsUG)ubg{oD&dHa!|%9cY`=c;jzLB>M~Vsn2FAG&rfg8BPh5W`qte6zmpVzUa84Yg5?p7udXp3tYnI}0%usY6m{0&{;8~pVxXlJ(^!D0e4r74UFoDWgvEhHu| zr#BNgpM&NDSB<^}90;x-Me@O}ybBD1xzNi5wvsoKfZ({G>y|@QTMhh*66kc~aVq0L z%)*NT19Og+KXy=9(SaB=45^FJA&V%nFpC(X(NoM)8&1ELh7Fl6-|5P-L3H^}Z)90a z>UsB}7nNYHXe`fStNC9dUN%e5`vQ@1rF zHS#4Xy2kIC_o3-2v97<0SQO}`SN08J(7dR;XD|81(o0gR!RgxZ7jiKneS!m`^&`;U z3HoRM?4R*J^BBWT`0EIC@RtjE8-L3XF8r0z4zhDxc?%f+(i|5w{EZ2$L=ar3u(AtW zTfpUlwhPP)?G&_KU?wonx%wCWW+%%`Vus1&v)wp76}{Nh;a4+uqOx~p(Un>niXfBJ z2+xu;e@&)Tb%8}XI=kkghos`u)9I+~!j)RgD!Mq^M9FUuYZ^APEGDh#!7ure!6|wm z){;uep~S3zD55Lu!o|l#8{nPDcy~1xgdi^hA_L#RaV+1=38gJW6*TaNXo;ohA$9-g zoPFldR>keFc^}DATZPV?ee^8KMAc%_$(Y*;d(At2nzHsOG5SgNf+|`>iACpp?b!#q zgo_`wYy2)Y%T#KJ2o$sAi>RbUdCXa|bBsHKvGCXauUBZDA_igXU)Cl2SMUZ<>|Z8o zAeadZe;vU(cK^4`VHgd6Z5A_`W#qo*f{y*`wc^5GC?6A8i7|omAr2;RxuAh>@RtiZ zCNLMYU0|oMtQ^?y0xvWdbl#+}q&K$+ZZ@Gemj)S{v7$Yxw_6De#F|X_UAQ=N7MxkK z?(&1SL2?kTj6*K`HOa~nqB8C&KV(0XXfL|zLvzssG1oi-hgPQ4 zE@rG$L>E}(bD@yY+mnipQ{~18*o}Gt_!<|8xQPP3uHpAmiXKWYei4iHsnpXDi$zy) zr_ns;Ew#PSFlXVXowHrBelMLqakcj>?!@|&v8uYEXO_Vszs4_BB@p@IccLei{G#%n zYo^!q7>tCCzU=?PUzp_;Bwk$j%d~XN$(AeIlQrrUBq(XSmeCsgjs44?yk`I6!{3j7 z^rPj7_7<>HTiycBhbV0U=Pe|f^A(Q5UpvkU<${L4PCrwOehSi#OhyQ%oo;)TwVBTdwsbZ#`9wRT$+j(l_u0$oof6?4ck@GF{!RoOR) zD6EXLAC5afT=j#R;*dbCF+p7gLXA%3da%LF*vK%>bZKpys z5X|N41Qb6oG_(cmtTM!8x7xskp^VuL|MP&qP&g(q``25*aY0k%OqVZvz+b_KE@S@& zf0@8eU*{Kra|*hD2rJ*h@-DEibqT!CAeadZf0^)3VFiDAq1~NTea$)58pjfIbM?kN zHhTmXvlKH$kPN~mTGu^`I76|j*iiYZCw^6L5bo6|na(_xu3Q_Mk5%$JOdxI2Z>n?V z7E99&GO~vsJuo)`)Z)Z0&HxD_OO0gL-*qOnU+2`B)8$V@fr{7?vwOQND@406AnbRLZ)gfX-6tg%XW^HSn$j5y|X0CQJ z5-SZu5pz;F5i{s4dLfio|2S-ezxf0f(~`Z(_sa+ci0~IsLQG$w{JEd|IY+Pr# z#q2HnR}>;MfuS}Nm}~8 z>~#)Hj1d62@cVS|2h5FR(~6y23n zm1gG5Dd7{;f5i&l`J|QrQQh^cRsPs_34?pthoWW*@|452xQLPN^+{A>*;p zXgF5vSOH@pb#pZ|g2F>>XC+m7Bu{V`rD0IMrfN-I_R2C7gYquilPY5|H;OBn4PsC@ zL^m=Xlyu5U9#qydP57*ubWu-d9@@x}?;6&cE@RD(4|rlEX8#xXa^%7?MkRCueEiSs zUzRCDmAlyfuT#+MUuG=ug{M%pkhjow=73-U_%ea>7E(@O*;dZ`#q}X9+s%c)aY5Sx zjtja@K?i&bfAcx4n8210`CX*E3(N%0R|VXuTMqsnJHxCs+8Td;O!Xk;kKQc7YuyD-+lamI-WME;UU*X_B|Drh7dz8#SH=# z9VCl?CPb9Go>*IHSW^;#(mzCtzfDvri();s9$YaOiA6mdOiFs{5ba5!Q)uVUoSynr z(rKcNE~hd{-M`M&Al3eqB>SS0ed^HLgnShd{>({ zz#y0v3|I?fH;A19d<4PlUt7Q+7@F59X!u?~2Mq3W3JdfzfgJ;j3)=foF@bNu@9q}~ zRW-ke)OUfIz;35ZUsKU)p^cZuzBH|QCnXItk*ZK>W+ZkQ!Mq!$0I zh+doyFGTYhmK#;kT*Vy~wJ>#;z;J_SQlB;DLs_ScRvYfAr*5scNvc{&T~!zB{8>1X zu0vAipu3V|=|km@Rd|yGhFiW#rF`D0-FSS*witn9Wi}dQqv*9<@il=YhN1IUAlPd= zUg7a8gdDl?Kj#Rv7joI8@X=l^xXf3u9AgH)?Abl>H{i=zEmuxKb7B|%a&9w$;jfKm zSkDCwf0Y~jwFY2`JB7sr4*r(^8U6~abtbS~;QS~!@Ws$k4XMf4X>>Es)D{P1znp8Rm;!r(Li@Z9o zm7D&Pt}@G1Y6&c=T4Y9Bnrqg)!I1?710#WL=oKUm+Z@4yzxf0fyyJgnfjSCh3)m58 zAB`**Gzhktn^Vwb_BwVI`o;;YC!?4k7+Aw!2eUkc)x7l-=GM!Tn)zqTshUtb z_l>hH>uk04n$Mc+UL=uBn8omC<~HX9S+*4(lsc3?L>E;(H63ZO=$Wa)33Jj@#_1K% zINRmksPFE7Bxhn#Ly7g&fhn5MW%i_H?2<#YC!L0VvVQH~X|#Pl<~_ED9C}m3cwBsN zi_8?1N3nmQkQV?6kjN2e*u+Tm<}CY{|Cu9~Ey>5r-y8g8lL|~!hAR7)|C#m51-*g4 z9fb>>5ix;nAM-yu1?`UFQi}H)iuH*!CZsY_RPnM-_uxGy+_to{E6}?#bt~`x-n%fy3M^`xXkY4Ug zR~+Tj)|S^}l2I4Kt&XWpDDvC6ne5G($kSxSB%A~zDvDeGjVbPfBI`%IIm2YTX) z)#F~&khUF?7MYRRehNdXXi7)GUw8z61$H8|vU3{y7rL=Ad3~9mHe}hPOw=5~a&#H~ z!q9pPxDYmGFH^VUZ`s1^UxCRiqmOt{0?paKAh;a>Seb+FYrDAI^|s8( zQnxkFsWWGva+B+1dH2!(w9BN+RWl**^->PIRef01cmUI z@e6-htUwcV`izyGTwB0Q+QQ#$qPw7(&rD!n^T=Dk`4)6eLFYppN(}z;LNmji!UDle zVD@i)i?SeCZH2g?3x6FaW7NZ62cc^t*e-B3g57@n0Iq4AG|S>cl$6xoj3=WP^$)7Z z>?1bhIyO4o!Vo<+`{@OCjd){l(bl7#K7Bz?jfT{@u4h>2=VNP}^7h^Gnuf)sMdq4@ zr0=Iun6>2zdb`~sukZ(czv z7j#}hf_F?{N1>o0aI^(%$2MEQ>|aNqgTFam74R+NcM*%(zqWumuJa*i_!}2AWM^OV zKeK-Y5S*U_2EoHAEcS0dg~jq%`U&Lb3vx0-a9MLTOSiubcw1buj-X(f7 zfUh_H(@49)UiuL2NjHhE29N$kQ;ny-GN-@Cs(*+RD@^x$=6AfsXSB%NZi;HRZLvz7 zn|J1v@H3yN7OQp`i2ZM2Zih8h#ou4~Qzp4_7rhRrzlFJ=u798jAIl+7wVH_`dqwj} zLv|ng7YxB8_HX>p@R#Q{uOK<>#N=dn=KK|K4F0lzh2SqF1*rr6mcw}_vi}RUy@ka7 zwUz9JrnsOfw*_4IYyUSc=-_Xi!iozT1m|0nwFQh|{|XL|sXr^;jWB`Tk&WQ;Lc?E6 zj_d+!f&N6Q!K)>!#eQcHb%VK`A$t0IJXT>EwhBsgU{>lgpXl{RpSZ%$H2kf5>5ryv zw%=wK==?+Jw7^=fxs;i+miMXTtJPfGA~RySi}^Y$S>q&cPaU*XQt^xP%po@JqF3_R zTbT7MW+&G9r>Co81F@z#VmW^WiP*oK&(0}%XV$SLW+VHNIhjvT@;@^|oxg&=T+qIl z0Wle^3|J66<1e#!hTY=C1r4&<&Yal!3Wxn)p`U_|{TmZFTfkh}ce+<5{Kab*I}KgR zdrdG;qw{9uU98d~bGVVZ!4Uh`ZOAy6RRX1RmZ_wti%2DV>5J8#nLP`7O<+y`kp0Bb zDt91`RY)EN<^7}V|FRYV7W=ynKV*(3+ zJ6pg`LBn)Mpn2#CLR{Ou+0I~(lIm|?bzkUS?Xfj<-fWLq^&T6~B`4E;Z zVBTyH%>Qf)xITnc_{;hh@-0fva7zL~#hB;$IflLk426TgUPNNW^FmurS#IM%IA90jDE7s{?7K5?3bqs2 zue-)|>Hs7~{oFh4+0laxf(3x0?zjYyQfKJL{TJsMI=dui@8ywnx9`;a0GBYFF5eDa zpzoIjUwGHJ%T9WT#H8GjKa!?QNM86*&TAJSHIlnw!5Cn@HC-^K2pzfB6!XKTyd_K; zrfr_#OrIXZV->SL_yM!Bn51gvDStm`?ml z3Jm{}pOUEZ6)f^!c=H1P{`u#h@Gto<{7VTM3Z@DTo3jgA^=I?1c0ubySo#*0O3-|W zgDhAjXl;bnE@;k>FOLmc0#*u~?*da@=YWN|Qmz*k_D3o8K%(2dnC-=U_M4(fw#g7M zRNBNNNlnT_^M%q5g>f@|-jN-;J8_qV#Gs@(>?$y0-YMi57V@)0S_FDSm##&DEF<*L zLuDGue0^Ty>6Ljd6I;3V{9Ss7ms6B#F3vgfV(YGM?k))iSZ_@ij447#t~JH{uqkf| zlP3R%?1%}Q$p+hV(a@aPqR(D?D0-WB&xaap%{bJb;a_dOf}2Pc$r*WthvX4PgMX>_ zLcUahNl2*-!;(-ijLG^hpRvkUfL&ys2^62jzuE)~Ct1R5Vhha8g13Gxq?M4VNqOz3_hOq$H`C{XvST@rH3$wQrJ5-lU?I)l zDSH5G;qs8yZr|UV7t*6=ujG!AhF*82m6b(EOv;8ynN7)4fmxWb!bteUoV97GsKX(s1nlg;i-1M**WO@)RHC;|u>KzU#VMXpf*BVm{q{AAh z)_=(gAto4#f-U?Dg>jJll59f09IzqDsZwAn#^kMM`4?V>f3*Y*1@rnaBaW|zD9Oe0(M&itTH^E5$ktCZI!_Ga6KU~uuDCW%QoG5d0Q z=<>dwYsen4Yi6E>ob_(%yAw2P+djgzX6@~Dy|YnWi zSd^e4ah8(#rWS7@kpgQAmi`a}88<s|B}&jz``tW zvk^-rXi{J{LT43PDKOK*p{Zk{JclV;d0FUpDuZUML`u$H24JQ2(&X3@)8$0Y6|V(TWok`tD4`b?w^1yEN%%hmmJ_q^83B4U+YrI}rl*HPSSLuuT!V7*NcN{9qo zMp&4*EAcZq!6_%+`XVG|UoK8&&3%WbkQwfj;Selu!>*aKo1mG2rOz?nk=IeaPVaDv z4rggG{_b!H7L5Pl^Y#tvzq}92w;ACh_?IPMO0|@2SwCg}GYhO_ny?<}C#k5mK=ZB; zTd;V0ml8At%FDbYv#jbanAct8zoKC9@GmJaC1{qCSx^@LQi9Gc(4Bw%A~3aa#>Orz z#wq^wMriXdyRcM(7XOk0>vJ4r`W$RI)4NE_0P|2v(3_JvoZ&;|%(?WO<-yG&&|COg zfQ*|aslO(tH{|YQs1&T&x=F9(gjv~PXoO5m$~H;2Hn}Vmw};JHAPlpsG_y~g?CdzcTzM3|7`V~&yG-F&DNtk}9qujGWKY@cb;0q!k=koV8U z?XbBM1;d1uW_C#)23lANKl6h=9hMNbN=%70^KaWt;jEuB43FI5io?<@u%S0&o)R>M z*+|YtIpt>-8vWV0&*IAfO7ng!U3mKGnssl%51Uf<^V;*UmyAy(XgG-VUnmI*W}gy- z#kM7qO1}au{-q$yD?%*P>MI;jFe$J;!J!lw3Kql8_*Z&hP%tLgY6}({y5Mx`&sqW& z`HFu@fuUfwU{M375)S`zuqqAzQiArkD9yiG|5XYs3icPVv=NIMd;VPp?S4g-Sw~*jpEdjF&i(Swp*W|zK!V(4Z783iu#J@^`84UcZUC@-E{TG4t7O<0Fu`sK^ zP_X!yCkj68#nthEp%j=BbiRv33QRTN%@oYN(5;ccS%;O`MEOtu$A1gP8tI=pD`JV& zonMGz)m{&ducSn;W>x&)W}Pq43TmPr>1Rz<2XKL&cH0B)azrq`D z0h3wlMPLH4+zjI<|B?bT5)PN3c@aq|F#OvoSp2KU2{v_W6_|INwF*qWuf5Rh!eR#e zU1(DHRtD7jK?|v%j@{P8`qHz%v~VH1P12{7(ilLLwcf+{ z%0ga_ujtNzJxeLf9QNp`v4>)Ay@dieY&y#4Kc$65erXme8en&3{@sRuK}@q=?zf9Cch z<o+bq*PyeLfkH3YKDKPvi z3f77?6wE3xDX`u}@?L0dgnlOlGxHq2S==VybPK+Be0HEK-76z#bfcuYL1k@Bg#X;2rnDYe`qb=^83?Jn7-Ayg7kq-EQLbJL%x3<~gTs=Smar zQCZ1oAzv!4dIbp%;uR$FUp6UGrzK~Exga$N4*q4ml@(YLQa+BsD?;L5NK>yMv6BiW zg-L{d#Z!U*Q@byqveW%HPS`f-VBhekV`e-*UaB*#|ZRp!7Hq zAQvcDpWuLrRDXtoNfpT%Au{$jLB5oHRexsvmn~Rqlw$ptO;hkM*()5%!TK+hy2HOt zfytU#0>+jSG^sR8z|MdDAuOlB-UZEI^esy5!r}=*e-6p~`>_Z5KmYm6eZQT=zg!e` zbtqW7prK%;z*M23VDm2pdFF)qWPUVVoH=rayC!>)X8`Gk-nz2*r0IKCzy&#sQZQ$m z>xgH)eMh|KFvoD=>g30UrJ2r$vhLBaOG*KJF34hDnt;(1lb_A~8Q^ZtW`5tvS!BP7 zXFVi-_&Xme)5`MUOI2j(irC}25{Lef1%gm;dEHNB+F1XDKKB~fPbNKQefPY1w+0N zy>?-Ve-|$TGeYgcDqrD9{zc|-f_ITPD6MmiTqzG5?DuBXn+s9*388|tP74~ZyN?nJzRFK!8^qv&^Gt&G_ekW|)P3 z;dx>8v&%E!`L|{!liDv^u#^I`N=v%Rz9~w_yv7UvepH`7UjZJH zuar=*dy&bP^DQK&z$`IS<%Z~40w!YF1|gDE9wrND)PwF{c$7eN$E{tN%Iz|AVK zc41M1)}ID0tH7#4GfR)Zk(57I-!J`RcN4)d35upMUP`@a8@~q-zd0FXZe$v9ET?*T(a4=i>jXDPNoI zLn}hSDLPzyrT`27!bGqV^u+qFXp41K)_=7Hnk8Vq%nU8^l?<{}@h@AT_xac4``2H8 zA;Z_Cz;HKjA(8)b;FFJAl3&BWehWz{FxfW);1K`%MI?QQL%X17{Ht78FCu9pwBJP{ z3#JfF3d{`XU0^n1u?kEUOnm?r)*a!Y<#1v*0mI*U|2Hy(ZH5@ahCi*LQiFMX0K-wu zlqGs;&aB?A_XHk}(8wI*p;dx^%CDG#uX79dg$#crH?Nut+_^@us7WD*X475Ag02jpyiof~mD4|j$-ylVY(cxl`_WBzHo|3l4NDJyAq z=CDL5&7p_loF-P}za)3;HB#}J)lc?ck^jO+5EJPk6by^8w95J~IVL4v_!lZ<2^ex@ zqcU5ts6Ugm!oM7(u@sX#)ebeuzYw=R1g$^BK>kZ|trVD8Fg`)O1)5!0l)<6kQi9eh zuwF#^*nJiJ3laZAzaQV?fP%R+a(tG#IjFaD$!x@;_O69s@h^`h6bCpoQOp=ePOqC5 zvNz>2|Jju?uthVwcH}au(%kXz?09w}{_q&?!i5_#oR;FsZY{{FG>5K=GEI=PS&;8< zdOYRF`N&A*yqxV>|B5+#4DPxnIM6loeXGj@)+HYX@`WHAf?o&NjPCo0z+hyxd8NW< zpp<8q)}3Re0}3Y5qvA>m4F8e|@_8t@iA7TJFXRgav(p&XV-plqs1%qK_4nU@r(6ta zlDfjb>|`eY9kT6AN&T7p7elsSao~yrpD;UHtf_KSf~Mk4L=I7~s?ZE3`Ii)!7m=V~ zvURqs4NWw*VORRxgr&($)?hf#0A(?4KE1x=_q#6HSUs705m=Gi5w~c4D~qSNb@_gyq$F@E01tt?n`i> zA=tflu0^(TCE3w0xJ^Hpm*%EJ2B2ex$8C0%W_DTbBRRAx0D0(s9HI-wg8=rE_;g#W z+(dv@pcwd~x;NK_$8eF6*qC5?ql z`xY!xU1htSg#mMD3l=44c0vE~#~<)7yP(Oh#lLL9A|hYGf`2*4e>wOTrN6?#vjO}| zhOS2i2CP+JI2RV?>_W6l(CmU{BbJtc*$Yj{okJU;c?p_%;AsR3W@cCg<`IR1>E)cW zmlJ+U#)?*j2{b^aIT1`zAA_Mz!Nm$eEwB`fJ{b)q2;~UKz8tK{ihm(rQeZMxNRzjaNMK=7)_=sI)?H2ycESRSYZNwrArUcEQcafL@D43@a zD45DTPbMq@b1-{P@$dRq@rGXi2Hp^>hbTYD4!EW%ZnJsedM}tT>}yunuJ)LgdF)W-2S@5&jUijI+s1j?_(Bmxl;gE*PVwla@^(N+y z?7@3r*38@*IRg~^5Iv&Y z{LA}C>|XZzZ{LD7OMXd*#lM`%owWrE9#;t(&+so%*o6iEY6%$r(BnS6>%rT5aR(CVFa;;7jz<-1JbaXzECF zG}+vjhlWF?d=9%%>VSL^$m}SwlI1}+e1nlcNx=Fq`7c|b;U*SL$$x+Q?Kjn*AwKd@ z*boY)ILuclVM%=ji@cTm7aAo6CZ)|3c+J0}V65~O5~(!&i%+W1EHSgunp|5YXeb!| z)t@6&7M#1VU|}x-I|Ww$E7~;$!@t^v#X_(snCA_iIw(Oy!P*N=DS(4HAra0hG&8oC z+j1+vO?3NDf$cjih8|4OyQ#=-TA1k#xF)m<{ieX1yRLcOv3k)(IW+z)-w}!*H!aAy znw)hUMg%s)EV?jR_omN8B4;yUmJ6UX4Z9$G#GYU81&2cuMd@dOFAu;Dhe01vD#TN+ z9`SSNq|9e&9-1!z#Z_r83`^J0aHy2wunVR163FS`UnmBmfqzMXp&|H}sw~_DbHTsR znZ5$8Phi1=@Gs;@{h1|TZGjg5lKeuxtO6(h_GRDHfYd8Ul%UxKP5w(ljZgTO{F)S) z7lBEE^&t-NFXSu!r36h%&WlKpFNaFd>=sM@b=oTy))FxM%VGZIV&PvNJhTy-hY*&4 zIhYU$l)x#IvcLw zUvyDKdDb)Da^!AWP_LStbqq~Xc~-`42C}*JsTq!;BWYc|>k zLzJKyF=b%;L1mcu;;IC7Gfk{~k+3n``Y&v#6qx*%uTa96yt)eolf!Bk)+zoKWy8OepebdO0+au; z1WbMn%kv^qroiOCsy}n)TO3*ihJ3XPi#(lOSmIww(B!|F0;~A!{Fe))#?DH&OVA(N zuzvlO6qph;2PrTVti8}o5frQvw5E=;rg3(24Vwuw!?Sw(PeUsaQje^zqI_L*7_N`% z>;UA}euh!b`t0};B>@hd%4g+a^r3P;ZZTI=<|(5wGWAyOM=Z$nHjHb0N3QWUyeZ7$ zUUNJ1w$`h6=iEnS&o(y(jpY{!j{YM5>Gs)JYj4A;o0)WdG5=Wo{pA;OI`c2&EB<9M z6jmZVguEy|bHHm59GNBuNhpL!{h8zxmLyT-qZv>z{44V9OTd}%c3CB8_*W%p{E+|p zZxO=3+J&WWad-(B^3^UZZ-izQI7`qB+e^S^Ugy7B0#*tP5ktYsg0&D#9e}AI1%`sz zh{ZvPUSGu0ym8iimRZf;#;fHFjjV&97CeBWDNV!vMS?CNF9bQqpIt?t%|qF4<et!k@1!=2TkQ#w#m#@0tzNQ7ue+{KKTh@E*>HOrNqkmuRlSlSAg{i4hReW zrJ_p;48g&Aa35d8p#Dtp8GeL+Axe0Yw}&{`NmcS+y??acg~bvuhHy7az&IhB#wV3+ zLcqV2yUDoWU$%Y`x^KZED`#w40#*tP`RXks{)7{kFg##kNE!0wMI;WMH(2=Q!Gp`^ z;B_RPMpT8?>qsmFXA123_dT)(!OAXd!fcrM9odH8MbHQxdS}3!82LDnKa!p+8(`jlsbOw1kGqcZ=(EKm&FeaZWv z9%zVs5dMXm;4gMGaghH)bF8%M*Ug&FOLf3zdSbREhO)JE-Wnm zB?YGb%pnS9FEmTQY{b$=X!w_9ac#sR1%`jM5z7m~%;D^Q&GdQiW|-6`en(E*_sfhh zgYFFY6lULfBJarS;icz8qye_FrVGNP-c~~)ktq+sD8abPcafb6@tT?8=&jU@*c0_DGjv?Yo+dE%hnS zJSXOkjDMSJ{g=f}mN+T5QgnrP*a-~zQl5o>At_jl{Fg1z+X7Q?0lttvF+s}gjcU5I8Q7W~Uo2mH$tFb^TTi^S6i{Hu-7JfElp zZ3@=Y%LV?;`|BHlkouGpb4pGpZ^i&`%EFZ@e_3C+R3Fd#grU05W)5G7l%NLopOA<$v|YqsqIDKJXT@Gto< z3=Wm!ko*_^B?aa!U~+B3LBZ6Y^&+r7#GzeSECDM8hJP6(sXC*Df*CpQPjNuO=3iyO zurLDr%fVv?{L8^p2mH$c1v3dMK`Z}demIl@>x&#r9a*quGH=rMK zQc+T1@?X6LObQJDLcVOHO8ynMLa!vboq45E2^yLDGv*xdID5L-1+5fVZz1U|V92-g zFIhSK%i$6<1NMiov=Cfg1QrW_((lKKCk+m&(3t{Lh4x3Gc{tI#NbJI5x;S8A^DlQ{ zcGuSWynQodVs>QvDPZfrh){-i*wnBS)-~BXllL!w=E3@OW#vLJ-WW8Nhk{LvOiju| zbCiiGvQ4bFW?#V8;Nqt=fmzc9J9&}NBNmO~7UiN@#yLY4n42?v(SuKo&8<((9obRr z#G0XC7{U!UUl%UDkwF`Q|zhuE&AdeZOz~*0nj)N4~AEo5UghDh` zXlnIL7Y7u~)G>z~x*d7r&}4Ha=Y8D4Bz`6rKZX_ktDD4Khw#8Q1$j$w*Yw`?7fv)TBH#N12!++r)Zn_62MWPCpC1VJXx2?6n-^q{b8Tx_ z5oT7vvdc}Gm#*UTPE(%kAp;F%BN2vx7bz8Y-}!8usZV+4IWae7Lf}E^8)rC0`>$Y` zkG;R22Q)-I7H)!}DCELuB$!Yzgl&pO}<0bVf;8_?hQx z`rcBjd&1#_5JX9xxURSBA+EBmk50!{r{ zOTbVV#b*xXzfd0eFR3W2vE;u{Fkj)IP|T(&rN9sF=-{_{yA;mDKkQc+qt^^ uD@vq8Af$d@P7f)|Luw=+dM+k2JTQ0J#G094q|H;4@{WhZ+aZS5BmWO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/adler32.c b/plugins/zzogl-pg/opengl/Win32/zlib/adler32.c new file mode 100644 index 0000000000..20dd55c94b --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/adler32.c @@ -0,0 +1,74 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? (int)len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + MOD(s1); + MOD(s2); + } + return (s2 << 16) | s1; +} diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/compress.c b/plugins/zzogl-pg/opengl/Win32/zlib/compress.c new file mode 100644 index 0000000000..87910ef046 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/crc32.c b/plugins/zzogl-pg/opengl/Win32/zlib/crc32.c new file mode 100644 index 0000000000..39db700d64 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/crc32.c @@ -0,0 +1,311 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id: crc32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, and + then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/crc32.h b/plugins/zzogl-pg/opengl/Win32/zlib/crc32.h new file mode 100644 index 0000000000..8053b6117c --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/deflate.c b/plugins/zzogl-pg/opengl/Win32/zlib/deflate.c new file mode 100644 index 0000000000..10374817ad --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/deflate.c @@ -0,0 +1,1502 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.1 Copyright 1995-2003 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, 255); + s->status = BUSY_STATE; + strm->adler = crc32(0L, Z_NULL, 0); + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy < Z_HUFFMAN_ONLY) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/deflate.h b/plugins/zzogl-pg/opengl/Win32/zlib/deflate.h new file mode 100644 index 0000000000..08aa37c792 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/deflate.h @@ -0,0 +1,326 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/gzio.c b/plugins/zzogl-pg/opengl/Win32/zlib/gzio.c new file mode 100644 index 0000000000..89d40993f5 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/gzio.c @@ -0,0 +1,1005 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatiblity with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/infback.c b/plugins/zzogl-pg/opengl/Win32/zlib/infback.c new file mode 100644 index 0000000000..110b03b857 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/infback.c @@ -0,0 +1,619 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_stream FAR *strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/inffast.c b/plugins/zzogl-pg/opengl/Win32/zlib/inffast.c new file mode 100644 index 0000000000..c716440a92 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/inffast.c @@ -0,0 +1,305 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - 68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/inffast.h b/plugins/zzogl-pg/opengl/Win32/zlib/inffast.h new file mode 100644 index 0000000000..1e88d2d97b --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/inffixed.h b/plugins/zzogl-pg/opengl/Win32/zlib/inffixed.h new file mode 100644 index 0000000000..75ed4b5978 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/inflate.c b/plugins/zzogl-pg/opengl/Win32/zlib/inflate.c new file mode 100644 index 0000000000..a53b5c7446 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/inflate.c @@ -0,0 +1,1270 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->wsize = 0; + state->whave = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + if (BITS(4) + 8 > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->mode != DICT) return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) return Z_DATA_ERROR; + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + *dest = *source; + *copy = *state; + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) + zmemcpy(window, state->window, 1U << state->wbits); + copy->window = window; + dest->state = (voidpf)copy; + return Z_OK; +} diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/inflate.h b/plugins/zzogl-pg/opengl/Win32/zlib/inflate.h new file mode 100644 index 0000000000..9a12c8fd29 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/inflate.h @@ -0,0 +1,117 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ +#ifdef GUNZIP + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ +#endif + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ +#ifdef GUNZIP + LENGTH, /* i: waiting for 32-bit length (gzip) */ +#endif + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/inftrees.c b/plugins/zzogl-pg/opengl/Win32/zlib/inftrees.c new file mode 100644 index 0000000000..3bb56398e1 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/inftrees.c @@ -0,0 +1,321 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.1 Copyright 1995-2003 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 66}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || (codes - count[0] != 1))) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/inftrees.h b/plugins/zzogl-pg/opengl/Win32/zlib/inftrees.h new file mode 100644 index 0000000000..82d365a7e9 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 code structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 1440 +#define MAXD 154 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/trees.c b/plugins/zzogl-pg/opengl/Win32/zlib/trees.c new file mode 100644 index 0000000000..b0c6e41c70 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/trees.c @@ -0,0 +1,1215 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2003 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/trees.h b/plugins/zzogl-pg/opengl/Win32/zlib/trees.h new file mode 100644 index 0000000000..72facf900f --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/uncompr.c b/plugins/zzogl-pg/opengl/Win32/zlib/uncompr.c new file mode 100644 index 0000000000..12eec9fec9 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/zconf.h b/plugins/zzogl-pg/opengl/Win32/zlib/zconf.h new file mode 100644 index 0000000000..1277c7ce17 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/zlib.h b/plugins/zzogl-pg/opengl/Win32/zlib/zlib.h new file mode 100644 index 0000000000..92edf96ff3 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/zutil.c b/plugins/zzogl-pg/opengl/Win32/zlib/zutil.c new file mode 100644 index 0000000000..646f572d59 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/zutil.c @@ -0,0 +1,319 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1 << 16; +#endif +#ifdef NO_GZIP + flags += 1 << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1 << 20; +#endif +#ifdef FASTEST + flags += 1 << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1 << 25; +# ifdef HAS_vsprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1 << 26; +# endif +# endif +#else + flags += 1 << 24; +# ifdef NO_snprintf + flags += 1 << 25; +# ifdef HAS_sprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1 << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* does not exist on WCE */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/plugins/zzogl-pg/opengl/Win32/zlib/zutil.h b/plugins/zzogl-pg/opengl/Win32/zlib/zutil.h new file mode 100644 index 0000000000..d0f21d6d86 --- /dev/null +++ b/plugins/zzogl-pg/opengl/Win32/zlib/zutil.h @@ -0,0 +1,258 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/plugins/zzogl-pg/opengl/ZZoglCRTC.cpp b/plugins/zzogl-pg/opengl/ZZoglCRTC.cpp new file mode 100644 index 0000000000..fb1c088318 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZZoglCRTC.cpp @@ -0,0 +1,821 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009 zeydlitz@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2006 + * + * 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 + */ + +// Realisation of RenderCRTC function ONLY. +// It draw picture direct on screen, so here we have interlacing and frame skipping. + +//------------------ Includes +#include + +#include "zerogs.h" +#include "targets.h" + +using namespace ZeroGS; + +//------------------ Defines +#ifdef RELEASE_TO_PUBLIC +#define g_bSaveFrame 0 +#define g_bSaveFinalFrame 0 +#else // NOT RELEASE_TO_PUBLIC +BOOL g_bSaveFrame = 0; // saves the current psurfTarget +BOOL g_bSaveFinalFrame = 0; // saves the input to the CRTC +#endif // RELEASE_TO_PUBLIC + +#define INTERLACE_COUNT (bInterlace && interlace == (conf.interlace)) + +// ----------------- Types +//------------------ Dummies + +//------------------ variables + +#ifdef _WIN32 +extern HDC hDC; // Private GDI Device Context +extern HGLRC hRC; // Permanent Rendering Context +#endif + +BOOL g_bCRTCBilinear = TRUE; +extern bool g_bIsLost; +int g_nFrameRender = 10; +int g_nFramesSkipped = 0; + +extern int s_frameskipping; +extern float fFPS; +extern unsigned char zgsrevision, zgsbuild, zgsminor; + +extern u32 g_SaveFrameNum; +extern int s_nWriteDepthCount; +extern int s_nWireframeCount; +extern int s_nWriteDestAlphaTest; + +extern int g_PrevBitwiseTexX, g_PrevBitwiseTexY; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY + +BOOL g_bDisplayFPS = FALSE; + +extern bool s_bDestAlphaTest; +extern int s_ClutResolve; +extern int s_nLastResolveReset; +extern int g_nDepthUpdateCount; +extern int s_nResolveCounts[30]; // resolve counts for last 30 frames +static int s_nCurResolveIndex = 0; +int s_nResolved = 0; // number of targets resolved this frame +extern int g_nDepthUsed; // ffx2 pal movies + +extern vector s_vecTempTextures; // temporary textures, released at the end of every frame + +//------------------ Namespace + +namespace ZeroGS { + extern int s_nNewWidth, s_nNewHeight; + + extern CRangeManager s_RangeMngr; // manages overwritten memory + extern void FlushTransferRanges(const tex0Info* ptex); + extern void ProcessMessages(); + void AdjustTransToAspect(Vector& v); + + // Interlace texture is lazy 1*(height) array of 1 and 0. + // It height (it named s_nInterlaceTexWidth here) hanging we must redone + // the texture. + // FIXME: If this function would spammed to often, we could use + // width < s_nInterlaceTexWidth as correct for old texture + static int s_nInterlaceTexWidth = 0; // width of texture + inline u32 CreateInterlaceTex(int width) { + if (width == s_nInterlaceTexWidth && s_ptexInterlace != 0) + return s_ptexInterlace; + + SAFE_RELEASE_TEX(s_ptexInterlace); + s_nInterlaceTexWidth = width; + + vector data(width); + for (int i = 0; i < width; ++i) + data[i] = (i & 1) ? 0xffffffff : 0; + + glGenTextures(1, &s_ptexInterlace); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ptexInterlace); + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, width, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + GL_REPORT_ERRORD(); + return s_ptexInterlace; + } +} +//------------------ Code + +// Adjusts vertex shader BitBltPos vector v to preserve aspect ratio. It used to emulate 4:3 or 16:9. +void ZeroGS::AdjustTransToAspect(Vector& v) +{ + double temp; + float f; + int dispwidth = 640; + int dispheight = conf.isWideScreen ? 360 : 480; + + if( dispwidth * nBackbufferHeight > dispheight * nBackbufferWidth) { + // limited by width + + // change in ratio + f = ((float)nBackbufferWidth / (float)dispwidth) / ((float)nBackbufferHeight / (float)dispheight); + v.y *= f; + v.w *= f; + + // scanlines mess up when not aligned right + v.y += (1-(float)modf(v.y*(float)nBackbufferHeight*0.5f+0.05f, &temp))*2.0f/(float)nBackbufferHeight; + v.w += (1-(float)modf(v.w*(float)nBackbufferHeight*0.5f+0.05f, &temp))*2.0f/(float)nBackbufferHeight; + } + else { + // limited by height + f = ((float)nBackbufferHeight / (float)dispheight) / ((float)nBackbufferWidth / (float)dispwidth); + f -= (float)modf(f*nBackbufferWidth, &temp)/(float)nBackbufferWidth; + v.x *= f; + v.z *= f; + } + v *= 1/32767.0f; +} + +// Helper for skip frames. +int TimeLastSkip=0; +inline bool FrameSkippingHelper() { + bool ShouldSkip = false; + if( g_nFrameRender > 0 ) { + if( g_nFrameRender < 8 ) { + g_nFrameRender++; + if( g_nFrameRender <= 3 ) { + g_nFramesSkipped++; + ShouldSkip = true; + } + } + } + else { + if( g_nFrameRender < -1 ) { + g_nFramesSkipped++; + ShouldSkip = true; + } + g_nFrameRender--; + } + + +#if defined _DEBUG + if (timeGetTime() - TimeLastSkip > 15000 && ShouldSkip) { + ERROR_LOG("ZZogl Skipped frames\n"); + TimeLastSkip = timeGetTime(); + } +#endif + return ShouldSkip; +} + +// helper function for save frame in picture. +inline void FrameSavingHelper() { + if( g_bSaveFrame ) { + if( vb[0].prndr != NULL ) { + SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, vb[0].prndr->ptex, RW(vb[0].prndr->fbw), RH(vb[0].prndr->fbh)); + } + + if( vb[1].prndr != NULL && vb[0].prndr != vb[1].prndr ) { + SaveTexture("frame2.tga", GL_TEXTURE_RECTANGLE_NV, vb[1].prndr->ptex, RW(vb[1].prndr->fbw), RH(vb[1].prndr->fbh)); + } +#ifdef _WIN32 + else DeleteFile("frame2.tga"); +#endif + } + g_SaveFrameNum = 0; + g_bSaveFlushedFrame = 1; +} + +// Function populated tex0Info[2] array +inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo) { + for(int i = 0; i < 2; ++i) { + + if( !(*(u32*)(PMODE) & (1<MAGH+1; + int magv = pd->MAGV+1; + + dispinfo[i].tbp0 = pfb->FBP << 5; + dispinfo[i].tbw = pfb->FBW << 6; + dispinfo[i].tw = (pd->DW + 1) / magh; + dispinfo[i].th = (pd->DH + 1) / magv; + dispinfo[i].psm = pfb->PSM; + + // hack!! + // 2 * dispinfo[i].tw / dispinfo[i].th <= 1, metal slug 4 + if( bInterlace && 2 * dispinfo[i].tw / dispinfo[i].th <= 1 && !(g_GameSettings&GAME_INTERLACE2X) ) { + dispinfo[i].th >>= 1; + } + } +} + + +// Something should be done before Renderer the picture. +inline void RenderStartHelper(u32 bInterlace){ + // Crashes Final Fantasy X at startup if uncommented. --arcum42 +//#ifdef RELEASE_TO_PUBLIC +// if(g_nRealFrame < 80 ) { +// RenderCustom( min(1.0f, 2.0f - (float)g_nRealFrame / 40.0f) ); +// +// if( g_nRealFrame == 79 ) +// SAFE_RELEASE_TEX(ptexLogo); +// return; +// } +//#endif + if( conf.mrtdepth && pvs[8] == NULL ) { + conf.mrtdepth = 0; + s_bWriteDepth = FALSE; +#ifdef DEBUG + ERROR_LOG("Disabling MRT depth writing\n"); +#endif + } + + Flush(0); + Flush(1); + GL_REPORT_ERRORD(); + + FrameSavingHelper(); + + if( s_RangeMngr.ranges.size() > 0 ) + FlushTransferRanges(NULL); + + SetShaderCaller("RenderStartHelper"); + // reset fba after every frame + vb[0].fba.fba = 0; + vb[1].fba.fba = 0; + + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer + glViewport(0, 0, nBackbufferWidth, nBackbufferHeight); + + // if interlace, only clear every other vsync + if(!bInterlace ) { + u32 color = COLOR_ARGB(0, BGCOLOR->R, BGCOLOR->G, BGCOLOR->B); + glClear(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + } + + SETVERTEXSHADER(pvsBitBlt.prog); + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + GL_REPORT_ERRORD(); + + if( conf.options & GSOPTION_WIREFRAME ) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + DisableAllgl() ; + GL_REPORT_ERRORD(); + + if( bInterlace ) g_PrevBitwiseTexX = -1; // reset since will be using +} + +// It is setting for intrelace texture multiplied vector; +// Idea is: (x, y) -- position on screen, than interlaced texture get F = 1 ot 0 depends +// on image y coord. So it we write valpha.z * F + valpha.w + 0.5 it would be swicthig odd +// and even strings at each frame +// valpha.x and y used for image blending. +inline Vector RenderGetForClip(u32 bInterlace, int interlace, int psm, FRAGMENTSHADER* prog){ + SetShaderCaller("RenderGetForClip"); + + Vector valpha; + // first render the current render targets, then from ptexMem + if( psm == 1 ) { + valpha.x = 1; + valpha.y = 0; + } + else { + valpha.x = 0; + valpha.y = 1; + } + + if (bInterlace) { + if( interlace == (conf.interlace&1) ) { + // pass if odd + valpha.z = 1.0f; + valpha.w = -0.4999f; + } + else { + // pass if even + valpha.z = -1.0f; + valpha.w = 0.5001f; + } + } + else { + // always pass interlace test + valpha.z = 0; + valpha.w = 1; + } + + ZZcgSetParameter4fv(prog->sOneColor, valpha, "g_fOneColor"); + return valpha; +} + +// Put interlaced texture in use for shader prog. +// Note: if frame interlaced it's th is halved, so we should x2 it. +inline void RenderCreateInterlaceTex(u32 bInterlace, int th, FRAGMENTSHADER* prog) { + if (!bInterlace) + return; + + int interlacetex = CreateInterlaceTex(2*th); + cgGLSetTextureParameter(prog->sInterlace, interlacetex); + cgGLEnableTextureParameter(prog->sInterlace); +} + +// Well, do blending setup prior to second pass of half-frame drawing +inline void RenderSetupBlending() { + // setup right blending + glEnable(GL_BLEND); + zgsBlendEquationSeparateEXT(GL_FUNC_ADD, GL_FUNC_ADD); + + if (PMODE->MMOD) { + glBlendColorEXT(PMODE->ALP*(1/255.0f), PMODE->ALP*(1/255.0f), PMODE->ALP*(1/255.0f), 0.5f); + s_srcrgb = GL_CONSTANT_COLOR_EXT; + s_dstrgb = GL_ONE_MINUS_CONSTANT_COLOR_EXT; + } + else { + s_srcrgb = GL_SRC_ALPHA; + s_dstrgb = GL_ONE_MINUS_SRC_ALPHA; + } + + s_srcalpha = PMODE->AMOD ? GL_ZERO : GL_ONE; + s_dstalpha = PMODE->AMOD? GL_ONE : GL_ZERO; + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); +} + +// each frame could be drawed in two stages, so blending should be different for them +inline void RenderSetupStencil(int i) { + glStencilMask(1<fbp)/texframe.tbw; + if( *dby < 0 ) { + *movy = -*dby; + *dby = 0; + } + return min(ptarg->fbh - *dby, texframe.th - *movy); +} + +// BltBit shader calculate vertex (4 coord's pixel) position at the viewport. +inline Vector RenderSetTargetBitPos(int dh, int th, int movy, bool isInterlace) { + SetShaderCaller("RenderSetTargetBitPos"); + Vector v; + // dest rect + v.x = 1; + v.y = dh/(float)th; + v.z = 0; + v.w = 1-v.y; + + if( movy > 0 ) + v.w -= movy/(float)th; + + AdjustTransToAspect(v); + + if (isInterlace) { + // move down by 1 pixel + v.w += 1.0f / (float)dh ; + } + + ZZcgSetParameter4fv(pvsBitBlt.sBitBltPos, v, "g_fBitBltPos"); + return v; +} + +// Important stuff. We could use this coordinated to change viewport position on frame +// For example use tw / X and tw / X magnify the vieport. +// Interlaced output is little out of VB, it could be see as evil blinking line on top +// and bottom, so we try to remove it +inline Vector RenderSetTargetBitTex(float th, float tw, float dh, float dw, bool isInterlace) { + SetShaderCaller("RenderSetTargetBitTex"); + + Vector v; + v = Vector(th, tw, dh, dw); + + // Incorrect Asect ration on interlaced frames + if (isInterlace) { + v.y -= 1.0f/480 ; + v.w += 1.0f/480 ; + } + + ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, v, "g_fBitBltTex"); + return v; +} + +// Translator for POSITION coordinats (-1.0:+1.0f at x axis, +1.0f:-1.0y at y) into target frame ones +// We don't need x coordinate, bvecause interlacing is y-axis only. +inline Vector RenderSetTargetBitTrans(int th) { + SetShaderCaller("RenderSetTargetBitTrans"); + Vector v = Vector( float(th), -float(th), float(th), float(th)); + ZZcgSetParameter4fv(pvsBitBlt.fBitBltTrans, v, "g_fBitBltTrans"); + return v; +} + +// use g_fInvTexDims to store inverse texture dims +// Seems, that Targ shader does not use it +inline Vector RenderSetTargetInvTex(int bInterlace, int tw, int th, FRAGMENTSHADER* prog) { + SetShaderCaller("RenderSetTargetInvTex"); + + Vector v = Vector(0, 0, 0, 0); + if (prog->sInvTexDims) { + v.x = 1.0f / (float)tw; + v.y = 1.0f / (float)th; + v.z = (float)0.0; + v.w = -0.5f / (float)th; + ZZcgSetParameter4fv(prog->sInvTexDims, v, "g_fInvTexDims"); + } + return v; +} + +// Metal Slug 5 hack (as was written). If tarhet tbp not equal to framed fbp, than we look for better possibility, +// Note, than after true result iterator it could not be use. +inline bool RenderLookForABetterTarget(int fbp, int tbp, list& listTargs, list::iterator& it) { + if (fbp == tbp) + return false; + + // look for a better target (metal slug 5) + list::iterator itbetter; + for(itbetter = listTargs.begin(); itbetter != listTargs.end(); ++itbetter ) { + if( (*itbetter)->fbp == tbp ) + break; + } + + if( itbetter != listTargs.end() ) { + it = listTargs.erase(it); + return true; + } + + return false; +} + +// First try to draw frame from targets. It's +inline bool RenderCheckForTargets(tex0Info& texframe, list& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace) { + // get the start and end addresses of the buffer + int bpp = RenderGetBpp(texframe.psm); + GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1; + + int start, end; + GetRectMemAddress(start, end, texframe.psm, 0, 0, texframe.tw, texframe.th, texframe.tbp0, texframe.tbw); + + // We need share list of targets beetween functions + s_RTs.GetTargs(start, end, listTargs); + + for(list::iterator it = listTargs.begin(); it != listTargs.end(); ) { + + CRenderTarget* ptarg = *it; + if( ptarg->fbw == texframe.tbw && !(ptarg->status&CRenderTarget::TS_NeedUpdate) && ((256/bpp)*(texframe.tbp0-ptarg->fbp))%texframe.tbw == 0 ) { + + if (RenderLookForABetterTarget(ptarg->fbp, texframe.tbp0, listTargs, it)) + continue; + + if( g_bSaveFinalFrame ) + SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptarg->ptex, RW(ptarg->fbw), RH(ptarg->fbh)); + + // determine the rectangle to render + int dby = pfb->DBY; + int movy = 0; + int dh = RenderGetOffsets(&dby, &movy, texframe, ptarg, bpp); + + if( dh >= 64 ) { + + if( ptarg->fbh - dby < texframe.th - movy && !(*bUsingStencil) ) + RenderUpdateStencil(i, bUsingStencil); + + SetShaderCaller("RenderCheckForTargets"); + // Texture + Vector v = RenderSetTargetBitTex((float)RW(texframe.tw), (float)RH(dh), (float)RW(pfb->DBX), (float)RH(dby), INTERLACE_COUNT ); + // dest rect + v = RenderSetTargetBitPos(dh, texframe.th, movy, INTERLACE_COUNT); + v = RenderSetTargetBitTrans(ptarg->fbh); + v = RenderSetTargetInvTex(bInterlace, texframe.tbw, ptarg->fbh, &ppsCRTCTarg[bInterlace]) ; // FIXME. This is no use + + Vector valpha = RenderGetForClip(bInterlace, interlace, texframe.psm, &ppsCRTCTarg[bInterlace]); + + // inside vb[0]'s target area, so render that region only + cgGLSetTextureParameter(ppsCRTCTarg[bInterlace].sFinal, ptarg->ptex); + cgGLEnableTextureParameter(ppsCRTCTarg[bInterlace].sFinal); + + RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTCTarg[bInterlace]); + + SETPIXELSHADER(ppsCRTCTarg[bInterlace].prog); + GL_REPORT_ERRORD(); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + if( abs(dh - (int)texframe.th) <= 1 ) + return true; + + if( abs(dh - (int)ptarg->fbh) <= 1 ) { + it = listTargs.erase(it); + continue; + } + } + } + ++it; + } + return false; +} + + +// The same of the previous, but from memory +inline void RenderCheckForMemory(tex0Info& texframe, list& listTargs, int interlace, int bInterlace) { + + for(list::iterator it = listTargs.begin(); it != listTargs.end(); ++it) + (*it)->Resolve(); + + // context has to be 0 + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(texframe, 1); + if ((pmemtarg == NULL) || (bInterlace >= 2)) + ERROR_LOG("CRCR Check for memory shader fault"); + + SetShaderCaller("RenderCheckForMemory"); + + SetTexVariablesInt(0, g_bCRTCBilinear ? 2 : 0, texframe, pmemtarg, &ppsCRTC[bInterlace], 1); + cgGLSetTextureParameter(ppsCRTC[bInterlace].sMemory, pmemtarg->ptex->tex); + cgGLEnableTextureParameter(ppsCRTC[bInterlace].sMemory); + + if( g_bSaveFinalFrame ) + SaveTex(&texframe, g_bSaveFinalFrame - 1 > 0); + + // finally render from the memory (note that the stencil buffer will keep previous regions) + Vector v = RenderSetTargetBitPos(1, 1, 0, INTERLACE_COUNT); + + // Fixme: Why this if here? + if( g_bCRTCBilinear ) + ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, Vector(texframe.tw,texframe.th,-0.5f,-0.5f), "g_fBitBltTex"); + else + ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, Vector(1,1,-0.5f/(float)texframe.tw,-0.5f/(float)texframe.th), "g_fBitBltTex"); + + v = RenderSetTargetBitTrans(texframe.th); + v = RenderSetTargetInvTex(bInterlace, texframe.tw, texframe.th, &ppsCRTC[bInterlace]); + + Vector valpha = RenderGetForClip(bInterlace, interlace, texframe.psm, &ppsCRTC[bInterlace]); + RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTC[bInterlace]); + + SETPIXELSHADER(ppsCRTC[bInterlace].prog); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + +// Put FPS counter on scren (not in window title) +inline void AfterRenderDisplayFPS() { + char str[64]; + int left = 10, top = 15; + sprintf(str, "%.1f fps", fFPS); + + DrawText(str, left+1, top+1, 0xff000000); + DrawText(str, left, top, 0xffc0ffff); +} + +// Swaping buffers, so we could use another windows +inline void AfterRenderSwapBuffers() { + if (glGetError() != GL_NO_ERROR) + DEBUG_LOG("glerror before swap!\n"); + +#ifdef _WIN32 + static u32 lastswaptime = 0; + SwapBuffers(hDC); + lastswaptime = timeGetTime(); +#else + glXSwapBuffers(GLWin.dpy, GLWin.win); +#endif +} + +// SnapeShoot helper +inline void AfterRenderMadeSnapshoot() { + char str[64]; + int left = 200, top = 15; + sprintf(str, "ZeroGS %d.%d.%d - %.1f fps %s", zgsrevision, zgsbuild, zgsminor, fFPS, s_frameskipping?" - frameskipping":""); + + DrawText(str, left+1, top+1, 0xff000000); + DrawText(str, left, top, 0xffc0ffff); + + if( SaveRenderTarget(strSnapshot != ""?strSnapshot.c_str():"temp.jpg", nBackbufferWidth, -nBackbufferHeight, 0)) {//(conf.options&GSOPTION_TGASNAP)?0:1) ) { + char str[255]; + sprintf(str, "saved %s\n", strSnapshot.c_str()); + AddMessage(str, 500); + } +} + +// If needed reset +inline void AfterRendererResizeWindow() { + Reset(); + ChangeDeviceSize(s_nNewWidth, s_nNewHeight); + s_nNewWidth = s_nNewHeight = -1; +} + +// Put new values on statistic variable +inline void AfterRenderCountStatistics() { + if( s_nWriteDepthCount > 0 ) { + assert( conf.mrtdepth ); + if( --s_nWriteDepthCount <= 0 ) { + s_bWriteDepth = FALSE; + } + } + + if( s_nWriteDestAlphaTest > 0 ) { + if( --s_nWriteDestAlphaTest <= 0 ) { + s_bDestAlphaTest = FALSE; + } + } + + if( g_nDepthUsed > 0 ) --g_nDepthUsed; + + s_ClutResolve = 0; + g_nDepthUpdateCount = 0; +} + +// This all could be easily forefeit +inline void AfterRendererUnimportantJob() { + ProcessMessages(); + + if( g_bDisplayFPS ) + AfterRenderDisplayFPS(); + + AfterRenderSwapBuffers(); + + if( conf.options & GSOPTION_WIREFRAME ) { + // clear all targets + s_nWireframeCount = 1; + } + + if( g_bMakeSnapshot ) { + AfterRenderMadeSnapshoot(); + g_bMakeSnapshot = 0; + } + + if( s_avicapturing ) + CaptureFrame(); + + AfterRenderCountStatistics(); + + if( s_nNewWidth >= 0 && s_nNewHeight >= 0 && !g_bIsLost ) + AfterRendererResizeWindow(); + + maxmin = 608; +} + +// Swich Frabuffers +inline void AfterRendererSwitchBackToTextures() { + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); + + g_MemTargs.DestroyCleared(); + + if( s_vecTempTextures.size() > 0 ) + glDeleteTextures((GLsizei)s_vecTempTextures.size(), &s_vecTempTextures[0]); + s_vecTempTextures.clear(); + + if( EXTWRITE->WRITE&1 ) { + WARN_LOG("EXTWRITE\n"); + ExtWrite(); + EXTWRITE->WRITE = 0; + } + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glEnable(GL_SCISSOR_TEST); + + if( icurctx >= 0 ) { + vb[icurctx].bVarsSetTarg = FALSE; + vb[icurctx].bVarsTexSync = FALSE; + vb[0].bVarsTexSync = FALSE; + } +} + +// Reset Targets Helper, for hack. +inline void AfterRendererAutoresetTargets() { + if( g_GameSettings & GAME_AUTORESET ) { + s_nResolveCounts[s_nCurResolveIndex] = s_nResolved; + s_nCurResolveIndex = (s_nCurResolveIndex+1)%ARRAY_SIZE(s_nResolveCounts); + + int total = 0; + for(int i = 0; i < ARRAY_SIZE(s_nResolveCounts); ++i) total += s_nResolveCounts[i]; + + if( total / ARRAY_SIZE(s_nResolveCounts) > 3 ) { + if( s_nLastResolveReset > (int)(fFPS * 8) ) { + // reset + ERROR_LOG("video mem reset\n"); + s_nLastResolveReset = 0; + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + + s_RTs.ResolveAll(); + return; + s_RTs.Destroy(); + s_DepthRTs.ResolveAll(); + s_DepthRTs.Destroy(); + + vb[0].prndr = NULL; vb[0].pdepth = NULL; vb[0].bNeedFrameCheck = 1; vb[0].bNeedZCheck = 1; + vb[1].prndr = NULL; vb[1].pdepth = NULL; vb[1].bNeedFrameCheck = 1; vb[1].bNeedZCheck = 1; + } + } + + s_nLastResolveReset++; + } + + if( s_nResolved > 8 ) s_nResolved = 2; + else if( s_nResolved > 0 ) --s_nResolved; +} + +int count = 0; +// The main renderer function +void ZeroGS::RenderCRTC(int interlace) +{ + if( g_bIsLost ) return; + if (FrameSkippingHelper()) return; + + u32 bInterlace = SMODE2->INT && SMODE2->FFMD && (conf.interlace < 2); + RenderStartHelper(bInterlace); + bool bUsingStencil = 0; + + tex0Info dispinfo[2]; + FrameObtainDispinfo(bInterlace, dispinfo); + + // start from the last circuit + for(int i = !PMODE->SLBG; i >= 0; --i) { + + tex0Info& texframe = dispinfo[i]; + if( texframe.th <= 1 ) + continue; + + if (SMODE2->INT && SMODE2->FFMD) + texframe.th >>= 1; + + if( i == 0 ) + RenderSetupBlending(); + + if( bUsingStencil ) + RenderSetupStencil(i); + + if( texframe.psm == 0x12 ) { + RenderCRTC24helper(bInterlace, interlace, texframe.psm); + continue; + } + + // We shader targets between two functions, so declare it here; + list listTargs; + + // if we could not draw image from target's do it from memory + if ( !RenderCheckForTargets(texframe, listTargs, i, &bUsingStencil, interlace, bInterlace) ) + RenderCheckForMemory(texframe, listTargs, interlace, bInterlace); + } + + GL_REPORT_ERRORD(); + + glDisable(GL_BLEND); + + AfterRendererUnimportantJob(); + AfterRendererSwitchBackToTextures(); + AfterRendererAutoresetTargets(); +} + + diff --git a/plugins/zzogl-pg/opengl/ZZoglCreate.cpp b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp new file mode 100644 index 0000000000..a0fc86587e --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp @@ -0,0 +1,1098 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009 zeydlitz@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2006 + * + * 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 + */ + +// Create and Destroy function. They would be called once per session. + +//------------------ Includes +#include "GS.h" +#include "Mem.h" +#include "zerogs.h" + +#include "ZeroGSShaders/zerogsshaders.h" +#include "targets.h" +// This include for windows resource file with Shaders +#ifdef _WIN32 +# include "Win32.h" +#endif + +//------------------ Defines + +#ifdef _WIN32 +#define GL_LOADFN(name) { \ + if( (*(void**)&name = (void*)wglGetProcAddress(#name)) == NULL ) { \ + ERROR_LOG("Failed to find %s, exiting\n", #name); \ + } \ +} +#else +// let GLEW take care of it +#define GL_LOADFN(name) +#endif + +#define GL_BLEND_RGB(src, dst) { \ + s_srcrgb = src; \ + s_dstrgb = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALPHA(src, dst) { \ + s_srcalpha = src; \ + s_dstalpha = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \ + s_srcrgb = srcrgb; \ + s_dstrgb = dstrgb; \ + s_srcalpha = srcalpha; \ + s_dstalpha = dstalpha; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_SET() zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha) + +#define GL_STENCILFUNC(func, ref, mask) { \ + s_stencilfunc = func; \ + s_stencilref = ref; \ + s_stencilmask = mask; \ + glStencilFunc(func, ref, mask); \ +} + +#define GL_STENCILFUNC_SET() glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask) + +#define VB_BUFFERSIZE 0x400 +#define VB_NUMBUFFERS 512 + +// ----------------- Types +typedef void (APIENTRYP _PFNSWAPINTERVAL) (int); + +map mapGLExtensions; + +namespace ZeroGS{ + RenderFormatType g_RenderFormatType = RFT_float16; + + extern void KickPoint(); + extern void KickLine(); + extern void KickTriangle(); + extern void KickTriangleFan(); + extern void KickSprite(); + extern void KickDummy(); + extern bool LoadEffects(); + extern bool LoadExtraEffects(); + extern FRAGMENTSHADER* LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed); + VERTEXSHADER pvsBitBlt; + + GLuint vboRect = 0; + vector g_vboBuffers; // VBOs for all drawing commands + int g_nCurVBOIndex = 0; + + inline bool CreateImportantCheck(); + inline void CreateOtherCheck(); + inline bool CreateOpenShadersFile(); +} + +//------------------ Dummies +#ifdef _WIN32 + void __stdcall glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4) +#else + void APIENTRY glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4) +#endif + { + glBlendFunc(e1, e2); + } + +#ifdef _WIN32 + void __stdcall glBlendEquationSeparateDummy(GLenum e1, GLenum e2) +#else + void APIENTRY glBlendEquationSeparateDummy(GLenum e1, GLenum e2) +#endif + { + glBlendEquation(e1); + } + +#ifdef _WIN32 + extern HINSTANCE hInst; + void (__stdcall *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL; + void (__stdcall *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL; +#else + void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL; + void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL; +#endif + +//------------------ variables +//////////////////////////// +// State parameters +float fiRendWidth, fiRendHeight; + +u8* s_lpShaderResources = NULL; +CGprogram pvs[16] = {NULL}; + +// String's for shader file in developer's mode +#ifdef DEVBUILD +char* EFFECT_NAME=""; +char* EFFECT_DIR=""; +#endif + +///////////////////// +// graphics resources +FRAGMENTSHADER ppsRegular[4], ppsTexture[NUM_SHADERS]; +FRAGMENTSHADER ppsCRTC[2], ppsCRTC24[2], ppsCRTCTarg[2]; +GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT +u32 s_stencilfunc, s_stencilref, s_stencilmask; +GLenum s_drawbuffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }; + +GLenum g_internalFloatFmt = GL_ALPHA_FLOAT32_ATI; +GLenum g_internalRGBAFloatFmt = GL_RGBA_FLOAT32_ATI; +GLenum g_internalRGBAFloat16Fmt = GL_RGBA_FLOAT16_ATI; + +u32 ptexLogo = 0; +int nLogoWidth, nLogoHeight; +u32 s_ptexInterlace = 0; // holds interlace fields + +//------------------ Global Variables +int g_MaxTexWidth = 4096, g_MaxTexHeight = 4096; +u32 s_uFramebuffer = 0; +CGprofile cgvProf, cgfProf; +int g_nPixelShaderVer = 0; // default + +RasterFont* font_p = NULL; +float g_fBlockMult = 1; +int s_nFullscreen = 0; + +u32 ptexBlocks = 0, ptexConv16to32 = 0; // holds information on block tiling +u32 ptexBilinearBlocks = 0; +u32 ptexConv32to16 = 0; +BOOL g_bDisplayMsg = 1; +int g_nDepthBias = 0; +BOOL g_bSaveFlushedFrame = 0; + +//------------------ Code + +bool ZeroGS::IsGLExt( const char* szTargetExtension ) +{ + return mapGLExtensions.find(string(szTargetExtension)) != mapGLExtensions.end(); +} + +inline bool +ZeroGS::Create_Window(int _width, int _height) { + nBackbufferWidth = _width; + nBackbufferHeight = _height; + fiRendWidth = 1.0f / nBackbufferWidth; + fiRendHeight = 1.0f / nBackbufferHeight; +#ifdef _WIN32 + + GLuint PixelFormat; // Holds The Results After Searching For A Match + DWORD dwExStyle; // Window Extended Style + DWORD dwStyle; // Window Style + + RECT rcdesktop; + GetWindowRect(GetDesktopWindow(), &rcdesktop); + + if( conf.options & GSOPTION_FULLSCREEN) { + nBackbufferWidth = rcdesktop.right - rcdesktop.left; + nBackbufferHeight = rcdesktop.bottom - rcdesktop.top; + + dwExStyle=WS_EX_APPWINDOW; + dwStyle=WS_POPUP; + ShowCursor(FALSE); + } + else { + dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dwStyle=WS_OVERLAPPEDWINDOW; + } + + RECT rc; + rc.left = 0; rc.top = 0; + rc.right = nBackbufferWidth; rc.bottom = nBackbufferHeight; + AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); + int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; + int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; + + SetWindowLong( GShwnd, GWL_STYLE, dwStyle ); + SetWindowLong( GShwnd, GWL_EXSTYLE, dwExStyle ); + + SetWindowPos(GShwnd, HWND_TOP, X, Y, rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW); + + if (conf.options & GSOPTION_FULLSCREEN) { + DEVMODE dmScreenSettings; + memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); + dmScreenSettings.dmSize=sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = nBackbufferWidth; + dmScreenSettings.dmPelsHeight = nBackbufferHeight; + dmScreenSettings.dmBitsPerPel = 32; + dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + + // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. + if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) + { + if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) + conf.options &= ~GSOPTION_FULLSCREEN; + else + return false; + } + } + else { + // change to default resolution + ChangeDisplaySettings(NULL, 0); + } + + PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be + { + sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + 1, // Version Number + PFD_DRAW_TO_WINDOW | // Format Must Support Window + PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + PFD_DOUBLEBUFFER, // Must Support Double Buffering + PFD_TYPE_RGBA, // Request An RGBA Format + 32, // Select Our Color Depth + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0, // 8bit Alpha Buffer + 0, // Shift Bit Ignored + 0, // No Accumulation Buffer + 0, 0, 0, 0, // Accumulation Bits Ignored + 24, // 24Bit Z-Buffer (Depth Buffer) + 8, // 8bit Stencil Buffer + 0, // No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0, // Reserved + 0, 0, 0 // Layer Masks Ignored + }; + + if (!(hDC=GetDC(GShwnd))) { + MessageBox(NULL,"(1) Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) { + MessageBox(NULL,"(2) Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if(!SetPixelFormat(hDC,PixelFormat,&pfd)) { + MessageBox(NULL,"(3) Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if (!(hRC=wglCreateContext(hDC))) { + MessageBox(NULL,"(4) Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if(!wglMakeCurrent(hDC,hRC)) { + MessageBox(NULL,"(5) Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + UpdateWindow(GShwnd); +#else //NOT _WIN32 + int i; + XVisualInfo *vi; + Colormap cmap; + int dpyWidth, dpyHeight; + int glxMajorVersion, glxMinorVersion; + int vidModeMajorVersion, vidModeMinorVersion; + Atom wmDelete; + Window winDummy; + unsigned int borderDummy; + + // attributes for a single buffered visual in RGBA format with at least + // 8 bits per color and a 24 bit depth buffer + int attrListSgl[] = {GLX_RGBA, GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + None}; + + // attributes for a double buffered visual in RGBA format with at least + // 8 bits per color and a 24 bit depth buffer + int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + None }; + + GLWin.fs = !!(conf.options & GSOPTION_FULLSCREEN); + + /* get an appropriate visual */ + vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl); + if (vi == NULL) { + vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl); + GLWin.doubleBuffered = False; + ERROR_LOG("Only Singlebuffered Visual!\n"); + } + else { + GLWin.doubleBuffered = True; + ERROR_LOG("Got Doublebuffered Visual!\n"); + } + + glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion); + ERROR_LOG("glX-Version %d.%d\n", glxMajorVersion, glxMinorVersion); + /* create a GLX context */ + GLWin.ctx = glXCreateContext(GLWin.dpy, vi, 0, GL_TRUE); + /* create a color map */ + cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + vi->visual, AllocNone); + GLWin.attr.colormap = cmap; + GLWin.attr.border_pixel = 0; + + // get a connection + XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion, &vidModeMinorVersion); + + if (GLWin.fs) { + + XF86VidModeModeInfo **modes = NULL; + int modeNum = 0; + int bestMode = 0; + + // set best mode to current + bestMode = 0; + ERROR_LOG("XF86VidModeExtension-Version %d.%d\n", vidModeMajorVersion, vidModeMinorVersion); + XF86VidModeGetAllModeLines(GLWin.dpy, GLWin.screen, &modeNum, &modes); + + if( modeNum > 0 && modes != NULL ) { + /* save desktop-resolution before switching modes */ + GLWin.deskMode = *modes[0]; + /* look for mode with requested resolution */ + for (i = 0; i < modeNum; i++) { + if ((modes[i]->hdisplay == _width) && (modes[i]->vdisplay == _height)) { + bestMode = i; + } + } + + XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, modes[bestMode]); + XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); + dpyWidth = modes[bestMode]->hdisplay; + dpyHeight = modes[bestMode]->vdisplay; + ERROR_LOG("Resolution %dx%d\n", dpyWidth, dpyHeight); + XFree(modes); + + /* create a fullscreen window */ + GLWin.attr.override_redirect = True; + GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | + StructureNotifyMask; + GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, + &GLWin.attr); + XWarpPointer(GLWin.dpy, None, GLWin.win, 0, 0, 0, 0, 0, 0); + XMapRaised(GLWin.dpy, GLWin.win); + XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync, + GrabModeAsync, CurrentTime); + XGrabPointer(GLWin.dpy, GLWin.win, True, ButtonPressMask, + GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime); + } + else { + ERROR_LOG("Failed to start fullscreen. If you received the \n" + "\"XFree86-VidModeExtension\" extension is missing, add\n" + "Load \"extmod\"\n" + "to your X configuration file (under the Module Section)\n"); + GLWin.fs = 0; + } + } + + + if( !GLWin.fs ) { + + //XRootWindow(dpy,screen) + //int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; + //int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; + + // create a window in window mode + GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | + StructureNotifyMask; + GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + 0, 0, _width, _height, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr); + // only set window title and handle wm_delete_events if in windowed mode + wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True); + XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1); + XSetStandardProperties(GLWin.dpy, GLWin.win, "ZeroGS", + "ZeroGS", None, NULL, 0, NULL); + XMapRaised(GLWin.dpy, GLWin.win); + } + + // connect the glx-context to the window + glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); + XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, + &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth); + ERROR_LOG("Depth %d\n", GLWin.depth); + if (glXIsDirect(GLWin.dpy, GLWin.ctx)) + ERROR_LOG("you have Direct Rendering!\n"); + else + ERROR_LOG("no Direct Rendering possible!\n"); + + // better for pad plugin key input (thc) + XSelectInput(GLWin.dpy, GLWin.win, ExposureMask | KeyPressMask | KeyReleaseMask | + ButtonPressMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | + FocusChangeMask ); + +#endif // WIN32 + s_nFullscreen = (conf.options & GSOPTION_FULLSCREEN) ? 1 : 0; + conf.mrtdepth = 0; // for now + + return true; +} + +// Function ask about differnt OGL extensions, that are required to setup accordingly. Return false if cheks failed +inline bool ZeroGS::CreateImportantCheck() { + bool bSuccess = true; +#ifndef _WIN32 + int const glew_ok = glewInit(); + if( glew_ok != GLEW_OK ) { + ERROR_LOG("glewInit() is not ok!\n"); + bSuccess = false; + } +#endif + + if( !IsGLExt("GL_EXT_framebuffer_object") ) { + ERROR_LOG("*********\nZZogl: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nZZogl: *********\n"); + bSuccess = false; + } + + if( !IsGLExt("GL_EXT_secondary_color") ) { + ERROR_LOG("*********\nZZogl: OGL WARNING: Need GL_EXT_secondary_color\nZZogl: *********\n"); + bSuccess = false; + } + + // load the effect, find the best profiles (if any) + if( cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE ) { + ERROR_LOG("arbvp1 not supported\n"); + bSuccess = false; + } + if( cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE ) { + ERROR_LOG("arbfp1 not supported\n"); + bSuccess = false; + } + + return bSuccess; +} + +// This is check for less important open gl extensions. +inline void ZeroGS::CreateOtherCheck() { + if( !IsGLExt("GL_EXT_blend_equation_separate") || glBlendEquationSeparateEXT == NULL ) { + ERROR_LOG("*********\nZZogl: OGL WARNING: Need GL_EXT_blend_equation_separate\nZZogl: *********\n"); + zgsBlendEquationSeparateEXT = glBlendEquationSeparateDummy; + } + else + zgsBlendEquationSeparateEXT = glBlendEquationSeparateEXT; + + if( !IsGLExt("GL_EXT_blend_func_separate") || glBlendFuncSeparateEXT == NULL ) { + ERROR_LOG("*********\nZZogl: OGL WARNING: Need GL_EXT_blend_func_separate\nZZogl: *********\n"); + zgsBlendFuncSeparateEXT = glBlendFuncSeparateDummy; + } + else + zgsBlendFuncSeparateEXT = glBlendFuncSeparateEXT; + + if( !IsGLExt("GL_ARB_draw_buffers") && !IsGLExt("GL_ATI_draw_buffers") ) { + ERROR_LOG("*********\nZZogl: OGL WARNING: multiple render targets not supported, some effects might look bad\nZZogl: *********\n"); + conf.mrtdepth = 0; + } + + if( IsGLExt("GL_ARB_draw_buffers") ) + glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffers"); + else if( IsGLExt("GL_ATI_draw_buffers") ) + glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffersATI"); + + + if (!IsGLExt("GL_ARB_multitexture")) + ERROR_LOG("No multitexturing\n"); + else + ERROR_LOG("Using multitexturing\n"); + + GLint Max_Texture_Size_NV = 0; + GLint Max_Texture_Size_2d = 0; + + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, &Max_Texture_Size_NV); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Max_Texture_Size_2d); + ERROR_LOG("Maximun texture size is %d for Tex_2d and %d for Tex_NV\n", Max_Texture_Size_2d, Max_Texture_Size_NV); + if (Max_Texture_Size_NV < 1024) + ERROR_LOG("Could not properly made bitmasks, so some textures should be missed\n"); + + /* Zeydlitz: we don't support 128-bit targets yet. they are slow and weirdo + if( g_GameSettings & GAME_32BITTARGS ) { + g_RenderFormatType = RFT_byte8; + ERROR_LOG("Setting 32 bit render target\n"); + } + else { + if( !IsGLExt("GL_NV_float_buffer") && !IsGLExt("GL_ARB_color_buffer_float") && !IsGLExt("ATI_pixel_format_float") ) { + ERROR_LOG("******\nZZogl: GS WARNING: Floating point render targets not supported, switching to 32bit\nZZogl: *********\n"); + g_RenderFormatType = RFT_byte8; + } + }*/ + g_RenderFormatType = RFT_byte8; + +#ifdef _WIN32 + if( IsGLExt("WGL_EXT_swap_control") || IsGLExt("EXT_swap_control") ) + wglSwapIntervalEXT(0); +#else + if( IsGLExt("GLX_SGI_swap_control") ) { + _PFNSWAPINTERVAL swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapInterval"); + if( !swapinterval ) + swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapIntervalSGI"); + if( !swapinterval ) + swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapIntervalEXT"); + + if( swapinterval ) + swapinterval(0); + else + ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); + } +#endif +} + +// open shader file according to build target + +inline bool ZeroGS::CreateOpenShadersFile() { +#ifndef DEVBUILD +# ifdef _WIN32 + HRSRC hShaderSrc = FindResource(hInst, MAKEINTRESOURCE(IDR_SHADERS), RT_RCDATA); + assert( hShaderSrc != NULL ); + HGLOBAL hShaderGlob = LoadResource(hInst, hShaderSrc); + assert( hShaderGlob != NULL ); + s_lpShaderResources = (u8*)LockResource(hShaderGlob); +# else // not _WIN32 + FILE* fres = fopen("ps2hw.dat", "rb"); + if( fres == NULL ) { + fres = fopen("plugins/ps2hw.dat", "rb"); + if( fres == NULL ) { + ERROR_LOG("Cannot find ps2hw.dat in working directory. Exiting\n"); + return false; + } + } + fseek(fres, 0, SEEK_END); + size_t s = ftell(fres); + s_lpShaderResources = new u8[s+1]; + fseek(fres, 0, SEEK_SET); + fread(s_lpShaderResources, s, 1, fres); + s_lpShaderResources[s] = 0; +# endif // _WIN32 +#else // NOT RELEASE_TO_PUBLIC +# ifndef _WIN32 // NOT WINDOWS + // test if ps2hw.fx exists + char tempstr[255]; + char curwd[255]; + getcwd(curwd, ARRAY_SIZE(curwd)); + + strcpy(tempstr, "/plugins/"); + sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr); + FILE* f = fopen(EFFECT_NAME, "r"); + if( f == NULL ) { + + strcpy(tempstr, "../../plugins/ZZOgl/opengl/"); + sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr); + f = fopen(EFFECT_NAME, "r"); + + if( f == NULL ) { + ERROR_LOG("Failed to find %s, try compiling a non-devbuild\n", EFFECT_NAME); + return false; + } + } + fclose(f); + + sprintf(EFFECT_DIR, "%s/%s", curwd, tempstr); + sprintf(EFFECT_NAME, "%sps2hw.fx", EFFECT_DIR); + #endif +#endif // RELEASE_TO_PUBLIC + return true; +} + +// Read all extensions name and fill mapGLExtensions +inline bool CreateFillExtensionsMap(){ + // fill the opengl extension map + const char* ptoken = (const char*)glGetString( GL_EXTENSIONS ); + if( ptoken == NULL ) return false; + + int prevlog = conf.log; + conf.log = 1; + GS_LOG("Supported OpenGL Extensions:\n%s\n", ptoken); // write to the log file + conf.log = prevlog; + + // insert all exts into mapGLExtensions + + const char* pend = NULL; + + while(ptoken != NULL ) { + pend = strchr(ptoken, ' '); + + if( pend != NULL ) { + mapGLExtensions[string(ptoken, pend-ptoken)]; + } + else { + mapGLExtensions[string(ptoken)]; + break; + } + + ptoken = pend; + while(*ptoken == ' ') ++ptoken; + } + return true; +} + +bool ZeroGS::Create(int _width, int _height) +{ + GLenum err = GL_NO_ERROR; + bool bSuccess = true; + int i; + + Destroy(1); + GSStateReset(); + + cgSetErrorHandler(HandleCgError, NULL); + g_RenderFormatType = RFT_float16; + + if (!Create_Window(_width, _height)) + return false; + + if (!CreateFillExtensionsMap()) + return false; + + if (!CreateImportantCheck()) + return false; + ZeroGS::CreateOtherCheck(); + + // check the max texture width and height + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &g_MaxTexWidth); + g_MaxTexHeight = g_MaxTexWidth/4; + GPU_TEXWIDTH = g_MaxTexWidth/8; + g_fiGPU_TEXWIDTH = 1.0f / GPU_TEXWIDTH; + + if (!CreateOpenShadersFile()) + return false; + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + s_srcrgb = s_dstrgb = s_srcalpha = s_dstalpha = GL_ONE; + + GL_LOADFN(glIsRenderbufferEXT); + GL_LOADFN(glBindRenderbufferEXT); + GL_LOADFN(glDeleteRenderbuffersEXT); + GL_LOADFN(glGenRenderbuffersEXT); + GL_LOADFN(glRenderbufferStorageEXT); + GL_LOADFN(glGetRenderbufferParameterivEXT); + GL_LOADFN(glIsFramebufferEXT); + GL_LOADFN(glBindFramebufferEXT); + GL_LOADFN(glDeleteFramebuffersEXT); + GL_LOADFN(glGenFramebuffersEXT); + GL_LOADFN(glCheckFramebufferStatusEXT); + GL_LOADFN(glFramebufferTexture1DEXT); + GL_LOADFN(glFramebufferTexture2DEXT); + GL_LOADFN(glFramebufferTexture3DEXT); + GL_LOADFN(glFramebufferRenderbufferEXT); + GL_LOADFN(glGetFramebufferAttachmentParameterivEXT); + GL_LOADFN(glGenerateMipmapEXT); + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + glGenFramebuffersEXT( 1, &s_uFramebuffer); + if( s_uFramebuffer == 0 ) { + ERROR_LOG("failed to create the renderbuffer\n"); + } + + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); + + if( glDrawBuffers != NULL ) + glDrawBuffers(1, s_drawbuffers); + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + font_p = new RasterFont(); + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + // init draw fns + drawfn[0] = KickPoint; + drawfn[1] = KickLine; + drawfn[2] = KickLine; + drawfn[3] = KickTriangle; + drawfn[4] = KickTriangle; + drawfn[5] = KickTriangleFan; + drawfn[6] = KickSprite; + drawfn[7] = KickDummy; + + SetAA(conf.aa); + GSsetGameCRC(g_LastCRC, g_GameSettings); + GL_STENCILFUNC(GL_ALWAYS, 0, 0); + + //g_GameSettings |= 0;//GAME_VSSHACK|GAME_FULL16BITRES|GAME_NODEPTHRESOLVE|GAME_FASTUPDATE; + //s_bWriteDepth = TRUE; + + GL_BLEND_ALL(GL_ONE, GL_ONE, GL_ONE, GL_ONE); + + glViewport(0,0,nBackbufferWidth,nBackbufferHeight); // Reset The Current Viewport + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glShadeModel(GL_SMOOTH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClearDepth(1.0f); + glEnable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDepthFunc(GL_LEQUAL); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations + + glGenTextures(1, &ptexLogo); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexLogo); + +#ifdef _WIN32 + HRSRC hBitmapSrc = FindResource(hInst, MAKEINTRESOURCE(IDB_ZEROGSLOGO), RT_BITMAP); + assert( hBitmapSrc != NULL ); + HGLOBAL hBitmapGlob = LoadResource(hInst, hBitmapSrc); + assert( hBitmapGlob != NULL ); + PBITMAPINFO pinfo = (PBITMAPINFO)LockResource(hBitmapGlob); + + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, pinfo->bmiHeader.biWidth, pinfo->bmiHeader.biHeight, 0, pinfo->bmiHeader.biBitCount==32?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, (u8*)pinfo+pinfo->bmiHeader.biSize); + nLogoWidth = pinfo->bmiHeader.biWidth; + nLogoHeight = pinfo->bmiHeader.biHeight; + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#else +#endif + + GL_REPORT_ERROR(); + + g_nCurVBOIndex = 0; + g_vboBuffers.resize(VB_NUMBUFFERS); + glGenBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]); + for(i = 0; i < (int)g_vboBuffers.size(); ++i) { + glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[i]); + glBufferData(GL_ARRAY_BUFFER, 0x100*sizeof(VertexGPU), NULL, GL_STREAM_DRAW); + } + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + // create the blocks texture + g_fBlockMult = 1; + + vector vBlockData, vBilinearData; + BLOCK::FillBlocks(vBlockData, vBilinearData, 1); + + glGenTextures(1, &ptexBlocks); + glBindTexture(GL_TEXTURE_2D, ptexBlocks); + + g_internalFloatFmt = GL_ALPHA_FLOAT32_ATI; + g_internalRGBAFloatFmt = GL_RGBA_FLOAT32_ATI; + g_internalRGBAFloat16Fmt = GL_RGBA_FLOAT16_ATI; + + glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_ALPHA, GL_FLOAT, &vBlockData[0]); + + if( glGetError() != GL_NO_ERROR ) { + // try different internal format + g_internalFloatFmt = GL_FLOAT_R32_NV; + glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RED, GL_FLOAT, &vBlockData[0]); + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + if( glGetError() != GL_NO_ERROR ) { + + // error, resort to 16bit + g_fBlockMult = 65535.0f*(float)g_fiGPU_TEXWIDTH / 32.0f; + + BLOCK::FillBlocks(vBlockData, vBilinearData, 0); + glTexImage2D(GL_TEXTURE_2D, 0, 2, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_R, GL_UNSIGNED_SHORT, &vBlockData[0]); + if( glGetError() != GL_NO_ERROR ) { + ERROR_LOG("ZZogl ERROR: could not fill blocks\n"); + return false; + } + ERROR_LOG("Using non-bilinear fill\n"); + } + else { + // fill in the bilinear blocks + glGenTextures(1, &ptexBilinearBlocks); + glBindTexture(GL_TEXTURE_2D, ptexBilinearBlocks); + glTexImage2D(GL_TEXTURE_2D, 0, g_internalRGBAFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RGBA, GL_FLOAT, &vBilinearData[0]); + + if( glGetError() != GL_NO_ERROR ) { + g_internalRGBAFloatFmt = GL_FLOAT_RGBA32_NV; + g_internalRGBAFloat16Fmt = GL_FLOAT_RGBA16_NV; + glTexImage2D(GL_TEXTURE_2D, 0, g_internalRGBAFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RGBA, GL_FLOAT, &vBilinearData[0]); + ERROR_LOG("ZZogl Fill bilinear blocks\n"); + B_G(glGetError() == GL_NO_ERROR, return false); + } + else + ERROR_LOG("Fill bilinear blocks failed!\n"); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + + float fpri = 1; + glPrioritizeTextures(1, &ptexBlocks, &fpri); + if( ptexBilinearBlocks != 0 ) + glPrioritizeTextures(1, &ptexBilinearBlocks, &fpri); + + GL_REPORT_ERROR(); + + // fill a simple rect + glGenBuffers(1, &vboRect); + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + + vector verts(4); + VertexGPU* pvert = &verts[0]; + pvert->x = -0x7fff; pvert->y = 0x7fff; pvert->z = 0; pvert->s = 0; pvert->t = 0; pvert++; + pvert->x = 0x7fff; pvert->y = 0x7fff; pvert->z = 0; pvert->s = 1; pvert->t = 0; pvert++; + pvert->x = -0x7fff; pvert->y = -0x7fff; pvert->z = 0; pvert->s = 0; pvert->t = 1; pvert++; + pvert->x = 0x7fff; pvert->y = -0x7fff; pvert->z = 0; pvert->s = 1; pvert->t = 1; pvert++; + glBufferDataARB(GL_ARRAY_BUFFER, 4*sizeof(VertexGPU), &verts[0], GL_STATIC_DRAW); + + // setup the default vertex declaration + glEnableClientState(GL_VERTEX_ARRAY); + glClientActiveTexture(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_SECONDARY_COLOR_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + GL_REPORT_ERROR(); + + // some cards don't support this +// glClientActiveTexture(GL_TEXTURE0); +// glEnableClientState(GL_TEXTURE_COORD_ARRAY); +// glTexCoordPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12); + + // create the conversion textures + glGenTextures(1, &ptexConv16to32); + glBindTexture(GL_TEXTURE_2D, ptexConv16to32); + + vector conv16to32data(256*256); + for(i = 0; i < 256*256; ++i) { + u32 tempcol = RGBA16to32(i); + // have to flip r and b + conv16to32data[i] = (tempcol&0xff00ff00)|((tempcol&0xff)<<16)|((tempcol&0xff0000)>>16); + } + glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, &conv16to32data[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + vector conv32to16data(32*32*32); + + glGenTextures(1, &ptexConv32to16); + glBindTexture(GL_TEXTURE_3D, ptexConv32to16); + u32* dst = &conv32to16data[0]; + for(i = 0; i < 32; ++i) { + for(int j = 0; j < 32; ++j) { + for(int k = 0; k < 32; ++k) { + u32 col = (i<<10)|(j<<5)|k; + *dst++ = ((col&0xff)<<16)|(col&0xff00); + } + } + } + glTexImage3D(GL_TEXTURE_3D, 0, 4, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, &conv32to16data[0]); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP); + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + g_cgcontext = cgCreateContext(); + + cgvProf = CG_PROFILE_ARBVP1; + cgfProf = CG_PROFILE_ARBFP1; + cgGLEnableProfile(cgvProf); + cgGLEnableProfile(cgfProf); + cgGLSetOptimalOptions(cgvProf); + cgGLSetOptimalOptions(cgfProf); + + cgGLSetManageTextureParameters(g_cgcontext, CG_FALSE); + //cgSetAutoCompile(g_cgcontext, CG_COMPILE_IMMEDIATE); + + g_fparamFogColor = cgCreateParameter(g_cgcontext, CG_FLOAT4); + g_vparamPosXY[0] = cgCreateParameter(g_cgcontext, CG_FLOAT4); + g_vparamPosXY[1] = cgCreateParameter(g_cgcontext, CG_FLOAT4); + + ERROR_LOG("Creating effects\n"); + B_G(LoadEffects(), return false); + + g_bDisplayMsg = 0; + + + // create a sample shader + clampInfo temp; + memset(&temp, 0, sizeof(temp)); + temp.wms = 3; temp.wmt = 3; + + g_nPixelShaderVer = 0;//SHADER_ACCURATE; + // test + bool bFailed; + FRAGMENTSHADER* pfrag = LoadShadeEffect(0, 1, 1, 1, 1, temp, 0, &bFailed); + if( bFailed || pfrag == NULL ) { + g_nPixelShaderVer = SHADER_ACCURATE|SHADER_REDUCED; + + pfrag = LoadShadeEffect(0, 0, 1, 1, 0, temp, 0, &bFailed); + if( pfrag != NULL ) + cgGLLoadProgram(pfrag->prog); + if( bFailed || pfrag == NULL || cgGetError() != CG_NO_ERROR ) { + g_nPixelShaderVer = SHADER_REDUCED; + ERROR_LOG("Basic shader test failed\n"); + } + } + + g_bDisplayMsg = 1; + if( g_nPixelShaderVer & SHADER_REDUCED ) + conf.bilinear = 0; + + ERROR_LOG("Creating extra effects\n"); + B_G(LoadExtraEffects(), return false); + + ERROR_LOG("using %s shaders\n", g_pShaders[g_nPixelShaderVer]); + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + glDisable(GL_STENCIL_TEST); + glEnable(GL_SCISSOR_TEST); + + GL_BLEND_ALPHA(GL_ONE, GL_ZERO); + glBlendColorEXT(0, 0, 0, 0.5f); + + glDisable(GL_CULL_FACE); + + // points + // This was changed in SetAA - should we be changing it back? + glPointSize(1.0f); + g_nDepthBias = 0; + glEnable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(0, 1); + + vb[0].Init(VB_BUFFERSIZE); + vb[1].Init(VB_BUFFERSIZE); + g_bSaveFlushedFrame = 1; + + g_vsprog = g_psprog = 0; + + if (glGetError() == GL_NO_ERROR) + return bSuccess; + else { + ERROR_LOG("ZZogl ERROR: in final init"); + return false; + } +} + +void ZeroGS::Destroy(BOOL bD3D) +{ + if( s_aviinit ) { + StopCapture(); + Stop_Avi(); + ERROR_LOG("zerogs.avi stopped"); + s_aviinit = 0; + } + + g_MemTargs.Destroy(); + s_RTs.Destroy(); + s_DepthRTs.Destroy(); + s_BitwiseTextures.Destroy(); + + SAFE_RELEASE_TEX(s_ptexInterlace); + SAFE_RELEASE_TEX(ptexBlocks); + SAFE_RELEASE_TEX(ptexBilinearBlocks); + SAFE_RELEASE_TEX(ptexConv16to32); + SAFE_RELEASE_TEX(ptexConv32to16); + + vb[0].Destroy(); + vb[1].Destroy(); + + if( g_vboBuffers.size() > 0 ) { + glDeleteBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]); + g_vboBuffers.clear(); + } + g_nCurVBOIndex = 0; + + for(int i = 0; i < ARRAY_SIZE(pvs); ++i) { + SAFE_RELEASE_PROG(pvs[i]); + } + for(int i = 0; i < ARRAY_SIZE(ppsRegular); ++i) { + SAFE_RELEASE_PROG(ppsRegular[i].prog); + } + for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + } + + SAFE_RELEASE_PROG(pvsBitBlt.prog); + SAFE_RELEASE_PROG(ppsBitBlt[0].prog); SAFE_RELEASE_PROG(ppsBitBlt[1].prog); + SAFE_RELEASE_PROG(ppsBitBltDepth.prog); + SAFE_RELEASE_PROG(ppsCRTCTarg[0].prog); SAFE_RELEASE_PROG(ppsCRTCTarg[1].prog); + SAFE_RELEASE_PROG(ppsCRTC[0].prog); SAFE_RELEASE_PROG(ppsCRTC[1].prog); + SAFE_RELEASE_PROG(ppsCRTC24[0].prog); SAFE_RELEASE_PROG(ppsCRTC24[1].prog); + SAFE_RELEASE_PROG(ppsOne.prog); + + SAFE_DELETE(font_p); + +#ifdef _WIN32 + if (hRC) // Do We Have A Rendering Context? + { + if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts? + { + MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); + } + + if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? + { + MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); + } + hRC=NULL; // Set RC To NULL + } + + if (hDC && !ReleaseDC(GShwnd,hDC)) // Are We Able To Release The DC + { + MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); + hDC=NULL; // Set DC To NULL + } +#else // linux + if (GLWin.ctx) + { + if (!glXMakeCurrent(GLWin.dpy, None, NULL)) + { + ERROR_LOG("Could not release drawing context.\n"); + } + glXDestroyContext(GLWin.dpy, GLWin.ctx); + GLWin.ctx = NULL; + } + /* switch back to original desktop resolution if we were in fs */ + if( GLWin.dpy != NULL ) { + if (GLWin.fs) { + XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode); + XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); + } + } +#endif + + mapGLExtensions.clear(); +} + diff --git a/plugins/zzogl-pg/opengl/ZZoglFlush.cpp b/plugins/zzogl-pg/opengl/ZZoglFlush.cpp new file mode 100644 index 0000000000..28ec4a912f --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZZoglFlush.cpp @@ -0,0 +1,2627 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009 zeydlitz@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2006 + * + * 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 + */ + +// Realisation of Flush -- drawing function of GS + +//------------------ Includes +//#if defined(_WIN32) +//# include +//# include "resource.h" +//#endif + +#include + +#include "GS.h" +#include "Mem.h" +#include "zerogs.h" +#include "targets.h" + +using namespace ZeroGS; + +//------------------ Defines +#ifndef DEVBUILD + +#define INC_GENVARS() +#define INC_TEXVARS() +#define INC_ALPHAVARS() +#define INC_RESOLVE() + +#define g_bUpdateEffect 0 +#define g_bSaveTex 0 +bool g_bSaveTrans = 0; +#define g_bSaveResolved 0 + +#else // NOT RELEASE_TO_PUBLIC + +#define INC_GENVARS() ++g_nGenVars +#define INC_TEXVARS() ++g_nTexVars +#define INC_ALPHAVARS() ++g_nAlphaVars +#define INC_RESOLVE() ++g_nResolve + +bool g_bSaveTrans = 0; +bool g_bUpdateEffect = 0; +bool g_bSaveTex = 0; // saves the curent texture +bool g_bSaveResolved = 0; +#endif // RELEASE_TO_PUBLIC + +#define STENCIL_ALPHABIT 1 // if set, dest alpha >= 0x80 +#define STENCIL_PIXELWRITE 2 // if set, pixel just written (reset after every Flush) +#define STENCIL_FBA 4 // if set, just written pixel's alpha >= 0 (reset after every Flush) +#define STENCIL_SPECIAL 8 // if set, indicates that pixel passed its alpha test (reset after every Flush) +//#define STENCIL_PBE 16 +#define STENCIL_CLEAR (2|4|8|16) + +#define DRAW() glDrawArrays(primtype[curvb.curprim.prim], 0, curvb.nCount) + +#define GL_BLEND_RGB(src, dst) { \ + s_srcrgb = src; \ + s_dstrgb = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALPHA(src, dst) { \ + s_srcalpha = src; \ + s_dstalpha = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \ + s_srcrgb = srcrgb; \ + s_dstrgb = dstrgb; \ + s_srcalpha = srcalpha; \ + s_dstalpha = dstalpha; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_ZTEST(enable) { \ + if (enable) glEnable(GL_DEPTH_TEST); \ + else glDisable(GL_DEPTH_TEST); \ +} + +#define GL_ALPHATEST(enable) { \ + if( enable ) glEnable(GL_ALPHA_TEST); \ + else glDisable(GL_ALPHA_TEST); \ +} + +#define GL_BLENDEQ_RGB(eq) { \ + s_rgbeq = eq; \ + zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \ +} + +#define GL_BLENDEQ_ALPHA(eq) { \ + s_alphaeq = eq; \ + zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \ +} + +#define COLORMASK_RED 1 +#define COLORMASK_GREEN 2 +#define COLORMASK_BLUE 4 +#define COLORMASK_ALPHA 8 +#define GL_COLORMASK(mask) glColorMask(!!((mask)&COLORMASK_RED), !!((mask)&COLORMASK_GREEN), !!((mask)&COLORMASK_BLUE), !!((mask)&COLORMASK_ALPHA)) + +// ----------------- Types +//------------------ Dummies + +//------------------ variables + +extern bool g_bIsLost; +bool g_bUpdateStencil = 1; +u32 g_SaveFrameNum = 0; // ZZ + +int GPU_TEXWIDTH = 512; +float g_fiGPU_TEXWIDTH = 1/512.0f; + +extern CGprogram g_psprog; // 2 -- ZZ + +// local alpha blending settings +static GLenum s_rgbeq, s_alphaeq; // set by zgsBlendEquationSeparateEXT // ZZ + + +static const u32 blendalpha[3] = { GL_SRC_ALPHA, GL_DST_ALPHA, GL_CONSTANT_COLOR_EXT }; // ZZ +static const u32 blendinvalpha[3] = { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_CONSTANT_COLOR_EXT }; //ZZ +static const u32 g_dwAlphaCmp[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL }; // ZZ + +// used for afail case +static const u32 g_dwReverseAlphaCmp[] = { GL_ALWAYS, GL_NEVER, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_EQUAL }; +static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER }; + +///////////////////// +// graphics resources +#define s_bForceTexFlush 1 // ZZ +u32 s_ptexCurSet[2] = {0}; +static u32 s_ptexNextSet[2] = {0}; // ZZ + +vector s_vecTempTextures; // temporary textures, released at the end of every frame + +extern bool s_bTexFlush; +bool s_bWriteDepth = FALSE; +bool s_bDestAlphaTest = FALSE; +int s_ClutResolve = 0; // ZZ +int g_nDepthUsed = 0; // ffx2 pal movies +int s_nWriteDepthCount = 0; // ZZ +int s_nWriteDestAlphaTest = 0; // ZZ + +//////////////////// +// State parameters +static Vector vAlphaBlendColor; // used for GPU_COLOR + +static u8 bNeedBlendFactorInAlpha; // set if the output source alpha is different from the real source alpha (only when blend factor > 0x80) +static u32 s_dwColorWrite = 0xf; // the color write mask of the current target + +union { + struct { + u8 _bNeedAlphaColor; // set if vAlphaBlendColor needs to be set + u8 _b2XAlphaTest; // Only valid when bNeedAlphaColor is set. if 1st bit set set, double all alpha testing values + // otherwise alpha testing needs to be done separately. + u8 _bDestAlphaColor; // set to 1 if blending with dest color (process only one tri at a time). If 2, dest alpha is always 1. + u8 _bAlphaClamping; // if first bit is set, do min; if second bit, do max + }; + u32 _bAlphaState; +} g_vars; + +//#define bNeedAlphaColor g_vars._bNeedAlphaColor +#define b2XAlphaTest g_vars._b2XAlphaTest +#define bDestAlphaColor g_vars._bDestAlphaColor +#define bAlphaClamping g_vars._bAlphaClamping + +int g_PrevBitwiseTexX = -1, g_PrevBitwiseTexY = -1; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY // ZZ + +static alphaInfo s_alphaInfo; // ZZ + +extern u8* g_pbyGSClut; + +//------------------ Namespace + +namespace ZeroGS { + + VB vb[2]; + float fiTexWidth[2], fiTexHeight[2]; // current tex width and height + + u8 s_AAx = 0, s_AAy = 0; // if AAy is set, then AAx has to be set + u8 s_AAz = 0, s_AAw = 0; // if AAy is set, then AAx has to be set + + int icurctx = -1; + + extern CRangeManager s_RangeMngr; // manages overwritten memory // zz + void FlushTransferRanges(const tex0Info* ptex); //zz + + RenderFormatType GetRenderFormat() { return g_RenderFormatType; } //zz + + // use to update the state + void SetTexVariables(int context, FRAGMENTSHADER* pfragment); // zz + void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint); // zz + void SetAlphaVariables(const alphaInfo& ainfo); // zzz + void ResetAlphaVariables(); + + inline void SetAlphaTestInt(pixTest curtest); + + inline void RenderAlphaTest(const VB& curvb, CGparameter sOneColor); + inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting); + inline void ProcessStencil(const VB& curvb); + inline void RenderFBA(const VB& curvb, CGparameter sOneColor); + inline void ProcessFBA(const VB& curvb, CGparameter sOneColor); // zz + + +} +//------------------ Code + +inline float AlphaReferedValue(int aref) { + return b2XAlphaTest ? min (1.0f, (float)aref / 127.5f) : (float)aref /255.0f ; +} + +inline void SetAlphaTest(const pixTest& curtest) { + // if s_dwColorWrite is nontrivial, than we should not off alphatest. + // This fix GOW and Okami. + if( !curtest.ate && USEALPHATESTING && (s_dwColorWrite != 2 && s_dwColorWrite != 14 )) { + glDisable(GL_ALPHA_TEST); + } + else { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(g_dwAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref)); + } +} + +// Switch wireframe rendering off for first flush, so it's draw few solid primitives +inline void SwitchWireframeOff() { + if( conf.options & GSOPTION_WIREFRAME ) { + if( s_nWireframeCount > 0 ) { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } +} + +// Switch wireframe rendering on, look at previous function +inline void SwitchWireframeOn() { + if( conf.options & GSOPTION_WIREFRAME ) { + if( s_nWireframeCount > 0 ) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + --s_nWireframeCount; + } + } +} + +int GetTexFilter(const tex1Info& tex1) +{ + // always force + if( conf.bilinear == 2 ) + return 1; + + int texfilter = 0; + if( conf.bilinear && ptexBilinearBlocks != 0 ) { + if( tex1.mmin <= 1 ) + texfilter = tex1.mmin|tex1.mmag; + else + texfilter = tex1.mmag ? ((tex1.mmin+2)&5) : tex1.mmin; + + texfilter = texfilter == 1 || texfilter == 4 || texfilter == 5; + } + return texfilter; +} + +void ZeroGS::ReloadEffects() +{ +#ifndef RELEASE_TO_PUBLIC + for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + } + memset(ppsTexture, 0, sizeof(ppsTexture)); + LoadExtraEffects(); +#endif +} + +long BufferNumber = 0; + +// This is debug function. It's print all buffer info and save current texture into the file, than printf file name. +inline void +VisualBufferMessage(int context) { +#if defined(PRIM_LOG) && defined(_DEBUG) + BufferNumber++; + ZeroGS::VB& curvb = vb[context]; + static const char* patst[8] = { "NEVER", "ALWAYS", "LESS", "LEQUAL", "EQUAL", "GEQUAL", "GREATER", "NOTEQUAL"}; + static const char* pztst[4] = { "NEVER", "ALWAYS", "GEQUAL", "GREATER" }; + static const char* pafail[4] = { "KEEP", "FB_ONLY", "ZB_ONLY", "RGB_ONLY" }; + ERROR_LOG("**Drawing ctx %d, num %d, fbp: 0x%x, zbp: 0x%x, fpsm: %d, zpsm: %d, fbw: %d\n", context, vb[context].nCount, curvb.prndr->fbp, curvb.zbuf.zbp, curvb.prndr->psm, curvb.zbuf.psm, curvb.prndr->fbw); + ERROR_LOG("prim: prim=%x iip=%x tme=%x fge=%x abe=%x aa1=%x fst=%x ctxt=%x fix=%x\n", + curvb.curprim.prim, curvb.curprim.iip, curvb.curprim.tme, curvb.curprim.fge, curvb.curprim.abe, curvb.curprim.aa1, curvb.curprim.fst, curvb.curprim.ctxt, curvb.curprim.fix); + ERROR_LOG("test: ate:%d, atst: %s, aref: %d, afail: %s, date: %d, datm: %d, zte: %d, ztst: %s, fba: %d\n", + curvb.test.ate, patst[curvb.test.atst], curvb.test.aref, pafail[curvb.test.afail], curvb.test.date, curvb.test.datm, curvb.test.zte, pztst[curvb.test.ztst], curvb.fba.fba); + ERROR_LOG("alpha: A%d B%d C%d D%d FIX:%d pabe: %d; aem: %d, ta0: %d, ta1: %d\n", curvb.alpha.a, curvb.alpha.b, curvb.alpha.c, curvb.alpha.d, curvb.alpha.fix, gs.pabe, gs.texa.aem, gs.texa.ta[0], gs.texa.ta[1]); + ERROR_LOG("tex0: tbp0=0x%x, tbw=%d, psm=0x%x, tw=%d, th=%d, tcc=%d, tfx=%d, cbp=0x%x, cpsm=0x%x, csm=%d, csa=%d, cld=%d\n", + curvb.tex0.tbp0, curvb.tex0.tbw, curvb.tex0.psm, curvb.tex0.tw, + curvb.tex0.th, curvb.tex0.tcc, curvb.tex0.tfx, curvb.tex0.cbp, + curvb.tex0.cpsm, curvb.tex0.csm, curvb.tex0.csa, curvb.tex0.cld); + char* Name; +// if (g_bSaveTex) { +// if (g_bSaveTex == 1) + Name = NamedSaveTex(&curvb.tex0, 1); +// else +// Name = NamedSaveTex(&curvb.tex0, 0); + ERROR_LOG("TGA name %s\n", Name); + free(Name); +// } + ERROR_LOG("frame: %d, buffer %ld\n\n", g_SaveFrameNum, BufferNumber); +#endif +} + +inline void SaveRendererTarget(VB& curvb) { +#ifdef _DEBUG + if( g_bSaveFlushedFrame & 0x80000000 ) { + char str[255]; + sprintf(str, "rndr.tga", g_SaveFrameNum); + SaveRenderTarget(str, curvb.prndr->fbw, curvb.prndr->fbh, 0); + } +#endif +} + +// Stop effects in Developers mode +inline void FlushUpdateEffect() { +#ifdef DEVBUID + if( g_bUpdateEffect ) { + ReloadEffects(); + g_bUpdateEffect = 0; + } +#endif +} + +// Check, maybe we cold skip flush +inline bool IsFlushNoNeed(VB& curvb, const pixTest& curtest ) { + if (curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0) || g_bIsLost) { + curvb.nCount = 0; + return true; + } + return false; +} + +// Transfer targets, that are located in current texture. +inline void FlushTransferRangesHelper(VB& curvb) { + if( s_RangeMngr.ranges.size() > 0 ) { + // don't want infinite loop, so set nCount to 0. + u32 prevcount = curvb.nCount; + curvb.nCount = 0; + + FlushTransferRanges(curvb.curprim.tme ? &curvb.tex0 : NULL); + + curvb.nCount += prevcount; + } +} + +// If set bit for texture cheking, do it. Maybe it's all. +inline bool FushTexDataHelper(VB& curvb){ + if( curvb.bNeedFrameCheck || curvb.bNeedZCheck ) { + curvb.CheckFrame(curvb.curprim.tme ? curvb.tex0.tbp0 : 0); + } + + if( curvb.bNeedTexCheck ) { // Zeydlitz want to try this + curvb.FlushTexData(); + + if (curvb.nCount == 0) + return true; + } + return false; +} + +// Null target mean that we do something really bad. +inline bool FlushCheckForNULLTarget(VB& curvb, int context){ + if ((curvb.prndr == NULL) || (curvb.pdepth == NULL)) { + ERROR_LOG_SPAMA("Current render target NULL (ctx: %d)", context); + curvb.nCount = 0; + return true; + } + return false; +} + +// O.k. A set of resolutions, we do before real flush. We do RangeManager, FrameCheck and +// ZCheck before this. +inline bool FlushInitialTest(VB& curvb, const pixTest& curtest, int context) { + GL_REPORT_ERRORD(); + assert( context >= 0 && context <= 1 ); + + FlushUpdateEffect(); + + if (IsFlushNoNeed(curvb, curtest)) + return true; + + FlushTransferRangesHelper(curvb); + + if (FushTexDataHelper(curvb)) + return true; + + GL_REPORT_ERRORD(); + + if (FlushCheckForNULLTarget(curvb, context)) + return true; + + return false; +} + +// Try to different approach if texture target was not found +inline CRenderTarget* FlushReGetTarget(int& tbw, int& tbp0, int& tpsm, VB& curvb) { + // This was incorrect code + CRenderTarget* ptextarg = NULL; + + if (ptextarg == NULL && tpsm == PSMT8 && (g_GameSettings & GAME_REGETHACK) ) { + // check for targets with half the width. Break Valkyrie Chronicles + ptextarg = s_RTs.GetTarg(tbp0, tbw/2, curvb); + if( ptextarg == NULL ) { + tbp0 &= ~0x7ff; + ptextarg = s_RTs.GetTarg(tbp0, tbw/2, curvb); // mgs3 hack + + if( ptextarg == NULL ) { + // check the next level (mgs3) + tbp0 &= ~0xfff; + ptextarg = s_RTs.GetTarg(tbp0, tbw/2, curvb); // mgs3 hack + } + + if( ptextarg != NULL && ptextarg->start > tbp0*256 ) { + // target beyond range, so ignore + ptextarg = NULL; + } + } + } + + + if( PSMT_ISZTEX(tpsm) && (ptextarg == NULL) ) { + // try depth + ptextarg = s_DepthRTs.GetTarg(tbp0, tbw, curvb); + } + + if ((ptextarg == NULL) && (g_GameSettings & GAME_TEXTURETARGS) ) { + // check if any part of the texture intersects the current target + if( !PSMT_ISCLUT(tpsm) && (curvb.tex0.tbp0 >= curvb.frame.fbp) && ((curvb.tex0.tbp0 ) < curvb.prndr->end)) { + ptextarg = curvb.prndr; + } + } + +#ifdef DEBUG + if (tbp0 == 0x3600 && tbw == 0x100) { + if (ptextarg == NULL) { + printf ("Miss %x 0x%x %d\n", tbw, tbp0, tpsm); + + typedef map MAPTARGETS; + for(MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew) { + printf("\tRender %x 0x%x %x\n", itnew->second->fbw, itnew->second->fbp, itnew->second->psm); + } + for(MAPTARGETS::iterator itnew = s_DepthRTs.mapTargets.begin(); itnew != s_DepthRTs.mapTargets.end(); ++itnew) { + printf("\tDepth %x 0x%x %x\n", itnew->second->fbw, itnew->second->fbp, itnew->second->psm); + } + + printf ("\tCurvb 0x%x 0x%x 0x%x %x\n", curvb.frame.fbp, curvb.prndr->end, curvb.prndr->fbp, curvb.prndr->fbw); + } + else + printf ("Hit %x 0x%x %x\n", tbw, tbp0, tpsm); + } +#endif + + return ptextarg; +} + +// Find target to draw a texture, it's highly p +inline CRenderTarget* FlushGetTarget(VB& curvb) { + int tbw, tbp0, tpsm; + + CRenderTarget* ptextarg = NULL; + if (!curvb.curprim.tme) + return ptextarg; + + if (curvb.bNeedTexCheck) { + printf ("How it is possible?\n"); + // not yet initied, but still need to get correct target! (xeno3 ingame) + tbp0 = ZZOglGet_tbp0_TexBits(curvb.uNextTex0Data[0]); + tbw = ZZOglGet_tbw_TexBitsMult(curvb.uNextTex0Data[0]); + tpsm = ZZOglGet_psm_TexBitsFix(curvb.uNextTex0Data[0]); + } + else{ + tbw = curvb.tex0.tbw; + tbp0 = curvb.tex0.tbp0; + tpsm = curvb.tex0.psm; + } + + ptextarg = s_RTs.GetTarg(tbp0, tbw, curvb); + if (ptextarg == NULL) + ptextarg = FlushReGetTarget(tbw, tbp0, tpsm, curvb); + + if ((ptextarg != NULL) && !(ptextarg->status & CRenderTarget::TS_NeedUpdate)) { + if (PSMT_BITMODE(tpsm) == 4) { // handle 8h cluts + // don't support clut targets, read from mem + // 4hl - kh2 check - from dx version -- arcum42 + if ( tpsm == PSMT4 && s_ClutResolve <= 1 ) + { // xenosaga requires 2 resolves + u32 prevcount = curvb.nCount; + curvb.nCount = 0; + ptextarg->Resolve(); + s_ClutResolve++; + curvb.nCount += prevcount; + } + ptextarg = NULL; + } + else { + if (ptextarg == curvb.prndr) { + // need feedback + curvb.prndr->CreateFeedback(); + + if (s_bWriteDepth && (curvb.pdepth != NULL)) + curvb.pdepth->SetRenderTarget(1); + else + ResetRenderTarget(1); + } + } + } + else ptextarg = NULL; + + return ptextarg; +} + +// Set target for current context +inline void FlushSetContextTarget(VB& curvb, int context) { + if( !curvb.bVarsSetTarg ) + SetContextTarget(context); + else { + assert( curvb.pdepth != NULL ); + + if( curvb.pdepth->status & CRenderTarget::TS_Virtual) { + + if( !curvb.zbuf.zmsk ) { + CRenderTarget* ptemp = s_DepthRTs.Promote(GetFrameKey(curvb.pdepth)); + assert( ptemp == curvb.pdepth ); + } + else + curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate; + } + + if( (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate) || (curvb.prndr->status & CRenderTarget::TS_NeedUpdate) ) + SetContextTarget(context); + } + + assert( !(curvb.prndr->status&CRenderTarget::TS_NeedUpdate) ); + curvb.prndr->status = 0; + + if( curvb.pdepth != NULL ) { + assert( !(curvb.pdepth->status&CRenderTarget::TS_NeedUpdate) ); + if( !curvb.zbuf.zmsk ) { + assert( !(curvb.pdepth->status & CRenderTarget::TS_Virtual) ); + curvb.pdepth->status = 0; + } + } +} + +inline void FlushSetStream(VB& curvb) { + glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[g_nCurVBOIndex]); + g_nCurVBOIndex = (g_nCurVBOIndex + 1) % g_vboBuffers.size(); + glBufferData(GL_ARRAY_BUFFER, curvb.nCount * sizeof(VertexGPU), curvb.pBufferData, GL_STREAM_DRAW); +// void* pdata = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); +// memcpy_amd(pdata, curvb.pBufferData, curvb.nCount * sizeof(VertexGPU)); +// glUnmapBuffer(GL_ARRAY_BUFFER); + SET_STREAM(); +#ifdef _DEBUG + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); +#endif + +} + +int SetMaskR = 0x0; int SetMaskG = 0x0; int SetMaskB = 0x0; +// Set color mask. Really it's not as good as PS2 one. +inline void FlushSetColorMask(VB& curvb) { + s_dwColorWrite = (PSMT_BITMODE(curvb.prndr->psm) == 1) ? (COLORMASK_BLUE|COLORMASK_GREEN|COLORMASK_RED) : 0xf; + + int maskR = ZZOglGet_fbmRed_FrameBits(curvb.frame.fbm); + int maskG = ZZOglGet_fbmGreen_FrameBits(curvb.frame.fbm); + int maskB = ZZOglGet_fbmBlue_FrameBits(curvb.frame.fbm); + int maskA = ZZOglGet_fbmAlpha_FrameBits(curvb.frame.fbm); + + if (maskR == 0xff) + s_dwColorWrite &= ~COLORMASK_RED; + if (maskG == 0xff) + s_dwColorWrite &= ~COLORMASK_GREEN; + if (maskB == 0xff) + s_dwColorWrite &= ~COLORMASK_BLUE; + if ((maskA == 0xff) || (curvb.curprim.abe && (curvb.test.atst == 2 && curvb.test.aref == 128))) + s_dwColorWrite &= ~COLORMASK_ALPHA; + + GL_COLORMASK(s_dwColorWrite); +} + +// Set Scissors for scissor test. +inline void FlushSetScissorRect(VB& curvb) { + Rect& scissor = curvb.prndr->scissorrect; + glScissor(scissor.x, scissor.y, scissor.w, scissor.h); +} + +// Prior really doing something check context +inline void FlushDoContextJob(VB& curvb, int context) { + SaveRendererTarget(curvb); + + FlushSetContextTarget(curvb, context); + icurctx = context; + + FlushSetStream(curvb); + FlushSetColorMask(curvb); + FlushSetScissorRect(curvb); +} + +// Set 1 is Alpha test is EQUAL and alpha should be proceed with care. +inline int FlushGetExactcolor(const pixTest curtest) { + if (!(g_nPixelShaderVer&SHADER_REDUCED)) + // ffx2 breaks when ==7 + return ((curtest.ate && curtest.aref <= 128) && (curtest.atst==4));//||curtest.atst==7); + + return 0; +} + +// fill the buffer by decoding the clut +inline void FlushDecodeClut(VB& curvb, GLuint& ptexclut) { + glGenTextures(1, &ptexclut); + glBindTexture(GL_TEXTURE_2D, ptexclut); + vector data(PSMT_ISHALF_STORAGE(curvb.tex0) ? 512 : 1024); + + if( ptexclut != 0 ) { + + int nClutOffset = 0, clutsize; + int entries = PSMT_IS8CLUT(curvb.tex0.psm) ? 256 : 16; + + if (curvb.tex0.csm && curvb.tex0.csa ) + printf ("ERROR, csm1\n"); + + if (curvb.tex0.cpsm <= 1) { // 32 bit + nClutOffset = 64 * curvb.tex0.csa; + clutsize = min(entries, 256 - curvb.tex0.csa * 16) * 4; + } + else { + nClutOffset = 64 * (curvb.tex0.csa & 15) + (curvb.tex0.csa >= 16 ? 2 : 0); + clutsize = min(entries, 512 - curvb.tex0.csa * 16) * 2; + } + + if( curvb.tex0.cpsm <= 1 ) { // 32 bit + memcpy_amd(&data[0], g_pbyGSClut+nClutOffset, clutsize); + } + else { + u16* pClutBuffer = (u16*)(g_pbyGSClut + nClutOffset); + u16* pclut = (u16*)&data[0]; + int left = ((u32)nClutOffset & 2) ? 0 : ((nClutOffset&0x3ff)/2)+clutsize-512; + if( left > 0 ) clutsize -= left; + + while(clutsize > 0) { + pclut[0] = pClutBuffer[0]; + pclut++; + pClutBuffer+=2; + clutsize -= 2; + } + + if( left > 0) { + pClutBuffer = (u16*)(g_pbyGSClut + 2); + while(left > 0) { + pclut[0] = pClutBuffer[0]; + left -= 2; + pClutBuffer += 2; + pclut++; + } + } + } + + glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 1, 0, GL_RGBA, PSMT_ISHALF_STORAGE(curvb.tex0)?GL_UNSIGNED_SHORT_5_5_5_1:GL_UNSIGNED_BYTE, &data[0]); + s_vecTempTextures.push_back(ptexclut); + + if (g_bSaveTex) + SaveTexture("clut.tga", GL_TEXTURE_2D, ptexclut, 256, 1); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } +} + +inline int FlushGetShaderType(VB& curvb, CRenderTarget* ptextarg, GLuint& ptexclut) { + if( PSMT_ISCLUT(curvb.tex0.psm) && !(g_GameSettings&GAME_NOTARGETCLUT) ) { + FlushDecodeClut(curvb, ptexclut); + if( !(g_nPixelShaderVer&SHADER_REDUCED) && PSMT_ISHALF(ptextarg->psm) ) { + return 4; + } + else { + // Valkyrie + return 2; + } + } + + if (PSMT_ISHALF_STORAGE(curvb.tex0) != PSMT_ISHALF(ptextarg->psm) && (!(g_nPixelShaderVer&SHADER_REDUCED) || !curvb.curprim.fge) ) { + if (PSMT_ISHALF_STORAGE(curvb.tex0)) { + // converting from 32->16 + // Radiata Chronicles + return 3; + } + else { + // converting from 16->32 + // Star Ward: Force + return 0; + } + } + return 1; +} + + +//Set page offsets depends omn shader type. +inline Vector FlushSetPageOffset(FRAGMENTSHADER* pfragment, int shadertype, CRenderTarget* ptextarg) { + SetShaderCaller("FlushSetPageOffset"); + + Vector vpageoffset; + vpageoffset.w = 0; + + switch (shadertype) { + case 3: + vpageoffset.x = -0.1f / 256.0f; + vpageoffset.y = -0.001f / 256.0f; + vpageoffset.z = -0.1f / (ptextarg->fbh); + vpageoffset.w = 0.0f; + break; + case 4: + vpageoffset.x = 2; + vpageoffset.y = 1; + vpageoffset.z = 0; + vpageoffset.w = 0.0001f; + break; + } + // zoe2 + if (PSMT_ISZTEX(ptextarg->psm)) + vpageoffset.w = -1.0f; + + ZZcgSetParameter4fv(pfragment->fPageOffset, vpageoffset, "g_fPageOffset"); + return vpageoffset; +} + +//Set texture offsets depends omn shader type. +inline Vector FlushSetTexOffset(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg) { + SetShaderCaller("FlushSetTexOffset"); + Vector v; + if( shadertype == 3 ) { + Vector v; + v.x = 16.0f / (float)curvb.tex0.tw; + v.y = 16.0f / (float)curvb.tex0.th; + v.z = 0.5f * v.x; + v.w = 0.5f * v.y; + ZZcgSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset"); + } + else if( shadertype == 4 ) { + Vector v; + v.x = 16.0f / (float)ptextarg->fbw; + v.y = 16.0f / (float)ptextarg->fbh; + v.z = -1; + v.w = 8.0f / (float)ptextarg->fbh; + ZZcgSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset"); + } + return v; +} + +// Set dimension (Real!) of texture. z and w +inline Vector FlushTextureDims(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg) { + SetShaderCaller("FlushTextureDims"); + Vector vTexDims; + vTexDims.x = (float)RW(curvb.tex0.tw) ; + vTexDims.y = (float)RH(curvb.tex0.th) ; + + // look at the offset of tbp0 from fbp + if( curvb.tex0.tbp0 <= ptextarg->fbp ) { + vTexDims.z = 0;//-0.5f/(float)ptextarg->fbw; + vTexDims.w = 0;//0.2f/(float)ptextarg->fbh; + } + else { + u32 tbp0 = curvb.tex0.tbp0 >> 5; // align to a page + int blockheight = PSMT_ISHALF(ptextarg->psm) ? 64 : 32; + int ycoord = ((curvb.tex0.tbp0 - ptextarg->fbp) / (32 * (ptextarg->fbw >> 6))) * blockheight; + int xcoord = (((curvb.tex0.tbp0 - ptextarg->fbp) % (32 * (ptextarg -> fbw >> 6)))) * 2; + vTexDims.z = (float)xcoord; + vTexDims.w = (float)ycoord; + } + + if (shadertype == 4) + vTexDims.z += 8.0f; + + ZZcgSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims"); + return vTexDims; +} + +// Apply TEX1 mmag and mmin -- filter for expanding/reducing texture +// We ignore all settings, only NEAREST (0) is used +inline void FlushApplyResizeFilter(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int context) { + u32 ptexset = (ptextarg == curvb.prndr) ? ptextarg->ptexFeedback : ptextarg->ptex; + s_ptexCurSet[context] = ptexset; + + if ((!curvb.tex1.mmag) || (!curvb.tex1.mmin)) + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexset); + + if( !curvb.tex1.mmag ) { + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dwFilterOpts |= 1; + } + + if( !curvb.tex1.mmin ) { + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dwFilterOpts |= 2; + } +} + + +// Usage existing targets depends on several tricks, 32-16 conversion and CLUTing, so we need handle it. +inline FRAGMENTSHADER* FlushUseExistRenderTaget(VB& curvb, CRenderTarget* ptextarg, u32& dwFilterOpts, int exactcolor, int context) { + if (ptextarg->IsDepth()) + SetWriteDepth(); + + GLuint ptexclut = 0; + int psm = GetTexCPSM(curvb.tex0); + int shadertype = FlushGetShaderType(curvb, ptextarg, ptexclut); + + FRAGMENTSHADER* pfragment = LoadShadeEffect(shadertype, 0, curvb.curprim.fge, + IsAlphaTestExpansion(curvb), exactcolor, curvb.clamp, context, NULL); + + Vector vpageoffset = FlushSetPageOffset(pfragment, shadertype, ptextarg); + Vector v = FlushSetTexOffset(pfragment, shadertype, curvb, ptextarg); + Vector vTexDims = FlushTextureDims(pfragment, shadertype, curvb, ptextarg); + + if( pfragment->sCLUT != NULL && ptexclut != 0 ) { + cgGLSetTextureParameter(pfragment->sCLUT, ptexclut); + cgGLEnableTextureParameter(pfragment->sCLUT); + } + + FlushApplyResizeFilter(curvb, dwFilterOpts, ptextarg, context); + + if( g_bSaveTex ) + SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_NV, + ptextarg == curvb.prndr ? ptextarg->ptexFeedback : ptextarg->ptex, RW(ptextarg->fbw), RH(ptextarg->fbh)); + + return pfragment; +} + +// Usage most major shader. +inline FRAGMENTSHADER* FlushMadeNewTarget(VB& curvb, int exactcolor, int context) { + // save the texture + if( g_bSaveTex ) { + if( g_bSaveTex == 1 ) { + SaveTex(&curvb.tex0, 1); + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(curvb.tex0, 0); + } + else SaveTex(&curvb.tex0, 0); + } + + FRAGMENTSHADER* pfragment = LoadShadeEffect(0, GetTexFilter(curvb.tex1), curvb.curprim.fge, + IsAlphaTestExpansion(curvb), exactcolor, curvb.clamp, context, NULL); + + if (pfragment == NULL) + ERROR_LOG("Could not find memory target shader\n"); + + return pfragment; +} + +// We made an shader, so now need to put all common variables. +inline void FlushSetTexture(VB& curvb, FRAGMENTSHADER* pfragment, CRenderTarget* ptextarg, int context) { + SetTexVariables(context, pfragment); + SetTexInt(context, pfragment, ptextarg == NULL); + + // have to enable the texture parameters(curtest.atst= + if( curvb.ptexClamp[0] != 0 ) { + cgGLSetTextureParameter(pfragment->sBitwiseANDX, curvb.ptexClamp[0]); + cgGLEnableTextureParameter(pfragment->sBitwiseANDX); + } + if( curvb.ptexClamp[1] != 0 ) { + cgGLSetTextureParameter(pfragment->sBitwiseANDY, curvb.ptexClamp[1]); + cgGLEnableTextureParameter(pfragment->sBitwiseANDY); + } + if( pfragment->sMemory != NULL && s_ptexCurSet[context] != 0) { + cgGLSetTextureParameter(pfragment->sMemory, s_ptexCurSet[context]); + cgGLEnableTextureParameter(pfragment->sMemory); + } +} + +// Reset programm and texture variables; +inline void FlushBindProgramm( FRAGMENTSHADER* pfragment, int context) { + vb[context].bTexConstsSync = 0; + vb[context].bVarsTexSync = 0; + + cgGLBindProgram(pfragment->prog); + g_psprog = pfragment->prog; +} + +inline FRAGMENTSHADER* FlushRendererStage(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int exactcolor, int context) { + + FRAGMENTSHADER* pfragment = NULL; + + // set the correct pixel shaders + if (curvb.curprim.tme) { + if (ptextarg != NULL) + pfragment = FlushUseExistRenderTaget(curvb, ptextarg, dwFilterOpts, exactcolor, context); + else + pfragment = FlushMadeNewTarget(curvb, exactcolor, context); + + if (pfragment == NULL) { + ERROR_LOG("Shader does not found\n"); +// return NULL; + } + FlushSetTexture(curvb, pfragment, ptextarg, context); + } + else { + pfragment = &ppsRegular[curvb.curprim.fge + 2 * s_bWriteDepth]; + } + + GL_REPORT_ERRORD(); + + // set the shaders + SetShaderCaller("FlushRendererStage") ; + SETVERTEXSHADER(pvs[2 * ((curvb.curprim._val >> 1) & 3) + 8 * s_bWriteDepth + context] ); + FlushBindProgramm(pfragment, context); + + GL_REPORT_ERRORD(); + return pfragment; +} + +inline bool AlphaCanRenderStencil(VB& curvb) { + return g_bUpdateStencil && (PSMT_BITMODE(curvb.prndr->psm) != 1) && + !ZZOglGet_fbmHighByte(curvb.frame.fbm) && !(g_GameSettings & GAME_NOSTENCIL); +} + +inline void AlphaSetStencil (bool DoIt) { + if (DoIt) { + glEnable(GL_STENCIL_TEST); + GL_STENCILFUNC(GL_ALWAYS, 0, 0); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + } + else glDisable(GL_STENCIL_TEST); +} + +inline void AlphaSetDepthTest(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment) { + glDepthMask(!curvb.zbuf.zmsk && curtest.zte); + // && curtest.zte && (curtest.ztst > 1) ); + + if (curtest.zte) { + if (curtest.ztst > 1) g_nDepthUsed = 2; + if ((curtest.ztst == 2) ^ (g_nDepthBias != 0) ) { + g_nDepthBias = (curtest.ztst == 2); + //SETRS(D3DRS_DEPTHBIAS, g_nDepthBias?FtoDW(0.0003f):FtoDW(0.000015f)); + } + glDepthFunc(g_dwZCmp[curtest.ztst]); + } + GL_ZTEST(curtest.zte); + +// glEnable (GL_POLYGON_OFFSET_FILL); +// glPolygonOffset (-1., -1.); + + if (s_bWriteDepth) { + if(!curvb.zbuf.zmsk) + curvb.pdepth->SetRenderTarget(1); + else + ResetRenderTarget(1); + } +} + +inline u32 AlphaSetupBlendTest(VB& curvb) { + if (curvb.curprim.abe) + SetAlphaVariables(curvb.alpha); + else + glDisable(GL_BLEND); + + u32 oldabe = curvb.curprim.abe; + if (gs.pabe) { + //ERROR_LOG("PBE!\n"); + curvb.curprim.abe = 1; + glEnable(GL_BLEND); + } + return oldabe; +} + +inline void AlphaRenderFBA(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil) { + // needs to be before RenderAlphaTest + if ((gs.pabe) || (curvb.fba.fba && !ZZOglGet_fbmHighByte(curvb.frame.fbm)) || (s_bDestAlphaTest && bCanRenderStencil)) { + RenderFBA(curvb, pfragment->sOneColor); + } + +} + +inline u32 AlphaRenderAlpha(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor) { + SetShaderCaller("AlphaRenderAlpha"); + u32 dwUsingSpecialTesting = 0; + if (curvb.curprim.abe) { + if ((bNeedBlendFactorInAlpha || ((curtest.ate && curtest.atst > 1) && (curtest.aref > 0x80)))) { + // need special stencil processing for the alpha + RenderAlphaTest(curvb, pfragment->sOneColor); + dwUsingSpecialTesting = 1; + } + + // harvest fishing + Vector v = vAlphaBlendColor; + if (exactcolor) { + v.y *= 255; + v.w *= 255; + } + ZZcgSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + } + else { + // not using blending so set to defaults + Vector v = exactcolor ? Vector(1, 510*255.0f/256.0f, 0, 0) : Vector(1,2*255.0f/256.0f,0,0); + ZZcgSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + + } + return dwUsingSpecialTesting; +} + +inline void AlphaRenderStencil(VB& curvb, bool s_bDestAlphaTest, bool bCanRenderStencil, u32 dwUsingSpecialTesting) { + if (s_bDestAlphaTest && bCanRenderStencil) { + // if not 24bit and can write to high alpha bit + RenderStencil(curvb, dwUsingSpecialTesting); + } + else { + s_stencilref = STENCIL_SPECIAL; + s_stencilmask = STENCIL_SPECIAL; + + // setup the stencil to only accept the test pixels + if (dwUsingSpecialTesting) { + glEnable(GL_STENCIL_TEST); + glStencilMask(STENCIL_PIXELWRITE); + GL_STENCILFUNC(GL_EQUAL, STENCIL_SPECIAL|STENCIL_PIXELWRITE, STENCIL_SPECIAL); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } + } + +#ifdef _DEBUG + if (bDestAlphaColor == 1) { + WARN_LOG("dest alpha blending! manipulate alpha here\n"); + } +#endif + + if( bCanRenderStencil && gs.pabe ) { + // only render the pixels with alpha values >= 0x80 + GL_STENCILFUNC(GL_EQUAL, s_stencilref|STENCIL_FBA, s_stencilmask|STENCIL_FBA); + } + + GL_REPORT_ERRORD(); +} + +inline void AlphaTest(VB& curvb) { +// printf ("%d %d %d %d %d\n", curvb.test.date, curvb.test.datm, gs.texa.aem, curvb.test.ate, curvb.test.atst ); + +// return; + // Zeydlitz change this with a reason! It's "Alpha more than 1 hack." + if (curvb.test.ate == 1 && curvb.test.atst == 1 && curvb.test.date == 1) { + if (curvb.test.datm == 1) + glAlphaFunc(GL_GREATER, 1.0f); + else { + glAlphaFunc(GL_LESS, 1.0f); + printf ("%d %d %d\n", curvb.test.date, curvb.test.datm, gs.texa.aem); + } + } + + if (!curvb.test.ate || curvb.test.atst > 0) { + DRAW(); + } + + GL_REPORT_ERRORD(); +} + +inline void AlphaPabe(VB& curvb, FRAGMENTSHADER* pfragment, int exactcolor) { + if( gs.pabe ) { + SetShaderCaller("AlphaPabe"); + // only render the pixels with alpha values < 0x80 + glDisable(GL_BLEND); + GL_STENCILFUNC_SET(); + + Vector v; + v.x = 1; v.y = 2; v.z = 0; v.w = 0; + if( exactcolor ) v.y *= 255; + ZZcgSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + + DRAW(); + + // reset + if (!s_stencilmask) + s_stencilfunc = GL_ALWAYS; + GL_STENCILFUNC_SET(); + } + + GL_REPORT_ERRORD(); +} + +// Alfa Failure does not work properly on this cases. True means that no failure job should be done +// First three cases are trivail manual +inline bool AlphaFailureIgnore(const pixTest curtest) { + if (!curtest.ate) + return true; + if (curtest.atst == 1) + return true; + if (curtest.afail == 0) + return true; + if (g_GameSettings & GAME_NOALPHAFAIL && ((s_dwColorWrite < 8) || (s_dwColorWrite == 15 && curtest.atst == 5 && (curtest.aref == 64)))) + return true; + +// old and seemingly incorrect code. +// if ((s_dwColorWrite < 8 && s_dwColorWrite !=8) && curtest.afail == 1) +// return true; +// if ((s_dwColorWrite == 0xf) && curtest.atst == 5 && curtest.afail == 1 && !(g_GameSettings & GAME_REGETHACK)) +// return true; + return false; +} + +// more work on alpha failure case +inline void AlphaFailureTestJob(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor, bool bCanRenderStencil, int oldabe) { + // Note, case when ate == 1, atst == 0 and afail > 0 in documentation wrote as failure case. But it seems that + // either doc's are incorrect nor this case have some issues. + if (AlphaFailureIgnore(curtest)) { + return; + } + +#ifdef NOALFAFAIL + ERROR_LOG("Alpha job here %d %d %d %d %d %d\n", s_dwColorWrite, curtest.atst, curtest.afail, curtest.aref, gs.pabe, s_bWriteDepth); +// return; +#endif + + SetShaderCaller("AlphaFailureTestJob"); + + // need to reverse the test and disable some targets + glAlphaFunc(g_dwReverseAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref)); + + if (curtest.afail & 1) { // front buffer update only + + if( curtest.afail == 3 ) // disable alpha + glColorMask(1,1,1,0); + + glDepthMask(0); + + if (s_bWriteDepth) + ResetRenderTarget(1); + } + else { + // zbuffer update only + glColorMask(0,0,0,0); + } + + if( gs.pabe && bCanRenderStencil ) { + // only render the pixels with alpha values >= 0x80 + Vector v = vAlphaBlendColor; + if( exactcolor ) { v.y *= 255; v.w *= 255; } + ZZcgSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + glEnable(GL_BLEND); + GL_STENCILFUNC(GL_EQUAL, s_stencilref|STENCIL_FBA, s_stencilmask|STENCIL_FBA); + } + + DRAW(); + GL_REPORT_ERRORD(); + + if (gs.pabe) { + // only render the pixels with alpha values < 0x80 + glDisable(GL_BLEND); + GL_STENCILFUNC_SET(); + + Vector v; + v.x = 1; v.y = 2; v.z = 0; v.w = 0; + if (exactcolor) v.y *= 255; + ZZcgSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + + DRAW(); + + // reset + if (oldabe) + glEnable(GL_BLEND); + if (!s_stencilmask) + s_stencilfunc = GL_ALWAYS; + GL_STENCILFUNC_SET(); + } + + // restore + if ((curtest.afail & 1) && !curvb.zbuf.zmsk ) { + glDepthMask(1); + + if( s_bWriteDepth ) { + assert( curvb.pdepth != NULL); + curvb.pdepth->SetRenderTarget(1); + } + } + + GL_COLORMASK(s_dwColorWrite); + // not needed anymore since rest of ops concentrate on image processing + + GL_REPORT_ERRORD(); +} + +inline void AlphaSpecialTesting(VB& curvb, FRAGMENTSHADER* pfragment, u32 dwUsingSpecialTesting, int exactcolor) { + if (dwUsingSpecialTesting) { + SetShaderCaller("AlphaSpecialTesting"); + + // render the real alpha + glDisable(GL_ALPHA_TEST); + glColorMask(0,0,0,1); + + if (s_bWriteDepth) { + ResetRenderTarget(1); + } + + glDepthMask(0); + + glStencilFunc(GL_EQUAL, STENCIL_SPECIAL|STENCIL_PIXELWRITE, STENCIL_SPECIAL|STENCIL_PIXELWRITE); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + Vector v = Vector(0,exactcolor ? 510.0f : 2.0f,0,0); + ZZcgSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + DRAW(); + + // don't need to restore + } + + GL_REPORT_ERRORD(); +} + +inline void AlphaDestinationTest(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil) { + if (s_bDestAlphaTest) { + if( (s_dwColorWrite & COLORMASK_ALPHA) ) { + if( curvb.fba.fba ) + ProcessFBA(curvb, pfragment->sOneColor); + else if (bCanRenderStencil) + // finally make sure all entries are 1 when the dest alpha >= 0x80 (if fba is 1, this is already the case) + ProcessStencil(curvb); + } + } + else if ((s_dwColorWrite & COLORMASK_ALPHA) && curvb.fba.fba) + ProcessFBA(curvb, pfragment->sOneColor); + + if( bDestAlphaColor == 1 ) { + // need to reset the dest colors to their original counter parts + //WARN_LOG("Need to reset dest alpha color\n"); + } +} + +inline void AlphaSaveTarget(VB& curvb) { +#ifdef _DEBUG + return; // Do nothing + + if( g_bSaveFlushedFrame & 0xf ) { +#ifdef _WIN32 + CreateDirectory("frames", NULL); +#else + char* strdir=""; + sprintf(strdir, "mkdir %s", "frames"); + system(strdir); +#endif + char str[255]; + sprintf(str, "frames/frame%.4d.tga", g_SaveFrameNum++); + if( (g_bSaveFlushedFrame & 2) ) { + //glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer + //glFlush(); + //SaveTexture("tex.jpg", GL_TEXTURE_RECTANGLE_NV, curvb.prndr->ptex, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh)); + SaveRenderTarget(str, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh), 0); + } + } +#endif +} + +inline void AlphaColorClamping (VB& curvb, const pixTest curtest) { + // clamp the final colors, when enabled ffx2 credits mess up + if (curvb.curprim.abe && bAlphaClamping && GetRenderFormat() != RFT_byte8 && !(g_GameSettings&GAME_NOCOLORCLAMP)) { // if !colclamp, skip + + ResetAlphaVariables(); + + // if processing the clamping case, make sure can write to the front buffer + glDisable(GL_STENCIL_TEST); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(1,1,1,0); + + if( s_bWriteDepth ) { + ResetRenderTarget(1); + } + SetShaderCaller("AlphaColorClamping"); + + SETPIXELSHADER(ppsOne.prog); + GL_BLEND_RGB(GL_ONE, GL_ONE); + + float f; + if( bAlphaClamping & 1 ) { // min + f = 0; + ZZcgSetParameter4fv(ppsOne.sOneColor, &f, "g_fOneColor"); + GL_BLENDEQ_RGB(GL_MAX_EXT); + DRAW(); + } + + // bios shows white screen + if( bAlphaClamping & 2 ) { // max + f = 1; + ZZcgSetParameter4fv(ppsOne.sOneColor, &f, "g_fOneColor"); + GL_BLENDEQ_RGB(GL_MIN_EXT); + DRAW(); + } + + if( !curvb.zbuf.zmsk ) { + glDepthMask(1); + + if( s_bWriteDepth ) { + assert( curvb.pdepth != NULL ); + curvb.pdepth->SetRenderTarget(1); + } + } + + if( curvb.test.ate && USEALPHATESTING ) + glEnable(GL_ALPHA_TEST); + + GL_ZTEST(curtest.zte); + } +} + +inline void FlushUndoFiter(u32 dwFilterOpts) { + if( dwFilterOpts ) { + // undo filter changes (binding didn't change) + if( dwFilterOpts & 1 ) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if( dwFilterOpts & 2 ) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } +} + +// This is the most important function! it's draw all collected info oncscreen. +void +ZeroGS::Flush(int context) +{ + FUNCLOG + VB& curvb = vb[context]; + const pixTest curtest = curvb.test; + + if (FlushInitialTest(curvb, curtest, context)) + return; + + VisualBufferMessage(context); + + GL_REPORT_ERRORD(); + CRenderTarget* ptextarg = FlushGetTarget(curvb); + + SwitchWireframeOff(); + FlushDoContextJob(curvb, context); + + u32 dwUsingSpecialTesting = 0; + u32 dwFilterOpts = 0; + int exactcolor = FlushGetExactcolor(curtest); + FRAGMENTSHADER* pfragment = FlushRendererStage(curvb, dwFilterOpts, ptextarg, exactcolor, context); + + bool bCanRenderStencil = AlphaCanRenderStencil(curvb); + if (curtest.date || gs.pabe) + SetDestAlphaTest(); + + AlphaSetStencil(s_bDestAlphaTest && bCanRenderStencil); + AlphaSetDepthTest(curvb, curtest, pfragment); // Error! + SetAlphaTest(curtest); + u32 oldabe = AlphaSetupBlendTest(curvb); // Unavoidable + + // needs to be before RenderAlphaTest + AlphaRenderFBA(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil); + dwUsingSpecialTesting = AlphaRenderAlpha(curvb, curtest, pfragment, exactcolor); // Unavoidable + AlphaRenderStencil(curvb, s_bDestAlphaTest, bCanRenderStencil, dwUsingSpecialTesting); + AlphaTest(curvb); // Unavoidable + AlphaPabe(curvb, pfragment, exactcolor); + AlphaFailureTestJob(curvb, curtest, pfragment, exactcolor, bCanRenderStencil, oldabe); + AlphaSpecialTesting(curvb, pfragment, dwUsingSpecialTesting, exactcolor); + AlphaDestinationTest(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil); + AlphaSaveTarget(curvb); + + GL_REPORT_ERRORD(); + + AlphaColorClamping (curvb, curtest); + FlushUndoFiter(dwFilterOpts); + ppf += curvb.nCount+0x100000; + + curvb.nCount = 0; + curvb.curprim.abe = oldabe; + SwitchWireframeOn(); + GL_REPORT_ERRORD(); +} + +inline void ZeroGS::RenderFBA(const VB& curvb, CGparameter sOneColor) +{ + // add fba to all pixels + GL_STENCILFUNC(GL_ALWAYS, STENCIL_FBA, 0xff); + glStencilMask(STENCIL_CLEAR); + glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE); + + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(0,0,0,0); + + if( s_bWriteDepth ) + ResetRenderTarget(1); + + SetShaderCaller("RenderFBA"); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GEQUAL, 1); + + Vector v; + v.x = 1; v.y = 2; v.z = 0; v.w = 0; + ZZcgSetParameter4fv(sOneColor, v, "g_fOneColor"); + + DRAW(); + + SetAlphaTest(curvb.test); + + // reset (not necessary) + GL_COLORMASK(s_dwColorWrite); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + if( !curvb.zbuf.zmsk ) + { + glDepthMask(1); + + assert( curvb.pdepth != NULL ); + if( s_bWriteDepth ) + curvb.pdepth->SetRenderTarget(1); + } + GL_ZTEST(curvb.test.zte); +} + +__forceinline void ZeroGS::RenderAlphaTest(const VB& curvb, CGparameter sOneColor) +{ + if( !g_bUpdateStencil ) return; + + if( (curvb.test.ate) && (curvb.test.afail == 1)) + glDisable(GL_ALPHA_TEST); + + glDepthMask(0); + glColorMask(0,0,0,0); + + if (s_bWriteDepth) + ResetRenderTarget(1); + + SetShaderCaller("RenderAlphaTest"); + + Vector v; + v.x = 1; v.y = 2; v.z = 0; v.w = 0; + ZZcgSetParameter4fv(sOneColor, v, "g_fOneColor"); + + // or a 1 to the stencil buffer wherever alpha passes + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + s_stencilfunc = GL_ALWAYS; + + glEnable(GL_STENCIL_TEST); + + if( !s_bDestAlphaTest ) + { + // clear everything + s_stencilref = 0; + glStencilMask(STENCIL_CLEAR); + glDisable(GL_ALPHA_TEST); + GL_STENCILFUNC_SET(); + DRAW(); + + if( curvb.test.ate && curvb.test.afail != 1 && USEALPHATESTING ) + glEnable(GL_ALPHA_TEST); + } + + if( curvb.test.ate && curvb.test.atst>1 && curvb.test.aref > 0x80) + { + v.x = 1; v.y = 1; v.z = 0; v.w = 0; + ZZcgSetParameter4fv(sOneColor, v, "g_fOneColor"); + glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref)); + } + + s_stencilref = STENCIL_SPECIAL; + glStencilMask(STENCIL_SPECIAL); + GL_STENCILFUNC_SET(); + glDisable(GL_DEPTH_TEST); + + DRAW(); + + if( curvb.test.zte ) + glEnable(GL_DEPTH_TEST); + GL_ALPHATEST(0); + GL_COLORMASK(s_dwColorWrite); + + if( !curvb.zbuf.zmsk ) + { + glDepthMask(1); + + // set rt next level + if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1); + } +} + +inline void ZeroGS::RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting) +{ + //NOTE: This stencil hack for dest alpha testing ONLY works when + // the geometry in one DrawPrimitive call does not overlap + + // mark the stencil buffer for the new data's bits (mark 4 if alpha is >= 0xff) + // mark 4 if a pixel was written (so that the stencil buf can be changed with new values) + glStencilMask(STENCIL_PIXELWRITE); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + s_stencilmask = (curvb.test.date?STENCIL_ALPHABIT:0)|(dwUsingSpecialTesting?STENCIL_SPECIAL:0); + s_stencilfunc = s_stencilmask ? GL_EQUAL : GL_ALWAYS; + + s_stencilref = curvb.test.date*curvb.test.datm|STENCIL_PIXELWRITE|(dwUsingSpecialTesting?STENCIL_SPECIAL:0); + GL_STENCILFUNC_SET(); +} + +inline void ZeroGS::ProcessStencil(const VB& curvb) +{ + assert( !curvb.fba.fba ); + + // set new alpha bit + glStencilMask(STENCIL_ALPHABIT); + GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE, STENCIL_PIXELWRITE|STENCIL_FBA); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(0,0,0,0); + + if (s_bWriteDepth) ResetRenderTarget(1); + + GL_ALPHATEST(0); + SetShaderCaller("ProcessStencil"); + + SETPIXELSHADER(ppsOne.prog); + DRAW(); + + // process when alpha >= 0xff + GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE|STENCIL_FBA|STENCIL_ALPHABIT, STENCIL_PIXELWRITE|STENCIL_FBA); + DRAW(); + + // clear STENCIL_PIXELWRITE bit + glStencilMask(STENCIL_CLEAR); + GL_STENCILFUNC(GL_ALWAYS, 0, STENCIL_PIXELWRITE|STENCIL_FBA); + + DRAW(); + + // restore state + GL_COLORMASK(s_dwColorWrite); + + if( curvb.test.ate && USEALPHATESTING) + glEnable(GL_ALPHA_TEST); + + if( !curvb.zbuf.zmsk ) { + glDepthMask(1); + + if( s_bWriteDepth ) { + assert( curvb.pdepth != NULL ); + curvb.pdepth->SetRenderTarget(1); + } + } + + GL_ZTEST(curvb.test.zte); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); +} + +__forceinline void ZeroGS::ProcessFBA(const VB& curvb, CGparameter sOneColor) +{ + if( (curvb.frame.fbm&0x80000000) ) return; + + // add fba to all pixels that were written and alpha was less than 0xff + glStencilMask(STENCIL_ALPHABIT); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + GL_STENCILFUNC(GL_EQUAL, STENCIL_FBA|STENCIL_PIXELWRITE|STENCIL_ALPHABIT, STENCIL_PIXELWRITE|STENCIL_FBA); + + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(0,0,0,1); + + if( s_bWriteDepth ) { + ResetRenderTarget(1); + } + SetShaderCaller("ProcessFBA"); + + // processes the pixels with ALPHA < 0x80*2 + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_LEQUAL, 1); + + // add 1 to dest + GL_BLEND_ALPHA(GL_ONE, GL_ONE); + GL_BLENDEQ_ALPHA(GL_FUNC_ADD); + + float f = 1; + ZZcgSetParameter4fv(sOneColor, &f, "g_fOneColor"); + SETPIXELSHADER(ppsOne.prog); + + DRAW(); + + glDisable(GL_ALPHA_TEST); + + // reset bits + glStencilMask(STENCIL_CLEAR); + GL_STENCILFUNC(GL_GREATER, 0, STENCIL_PIXELWRITE|STENCIL_FBA); + glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); + + DRAW(); + + if( curvb.test.atst && USEALPHATESTING) { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref)); + } + + // restore (SetAlphaVariables) + GL_BLEND_ALPHA(GL_ONE, GL_ZERO); + if(vAlphaBlendColor.y<0) GL_BLENDEQ_ALPHA(GL_FUNC_REVERSE_SUBTRACT); + + // reset (not necessary) + GL_COLORMASK(s_dwColorWrite); + + if( !curvb.zbuf.zmsk ) { + glDepthMask(1); + + if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1); + } + GL_ZTEST(curvb.test.zte); +} + +void ZeroGS::SetContextTarget(int context) +{ + FUNCLOG + VB& curvb = vb[context]; + GL_REPORT_ERRORD(); + + if( curvb.prndr == NULL ) + curvb.prndr = s_RTs.GetTarg(curvb.frame, 0, get_maxheight(curvb.gsfb.fbp, curvb.gsfb.fbw, curvb.gsfb.psm)); + + // make sure targets are valid + if( curvb.pdepth == NULL ) { + frameInfo f; + f.fbp = curvb.zbuf.zbp; + f.fbw = curvb.frame.fbw; + f.fbh = curvb.prndr->fbh; + f.psm = curvb.zbuf.psm; + f.fbm = 0; + curvb.pdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer|CRenderTargetMngr::TO_StrictHeight| + (curvb.zbuf.zmsk?CRenderTargetMngr::TO_Virtual:0), get_maxheight(curvb.zbuf.zbp, curvb.gsfb.fbw, 0)); + } + + assert( curvb.prndr != NULL && curvb.pdepth != NULL ); + assert( curvb.pdepth->fbh == curvb.prndr->fbh ); + + if( curvb.pdepth->status & CRenderTarget::TS_Virtual) { + + if( !curvb.zbuf.zmsk ) { + CRenderTarget* ptemp = s_DepthRTs.Promote(curvb.pdepth->fbp|(curvb.pdepth->fbw<<16)); + assert( ptemp == curvb.pdepth ); + } + else + curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate; + } + + bool bSetTarg = 1; + + if( curvb.pdepth->status & CRenderTarget::TS_NeedUpdate ) { + assert( !(curvb.pdepth->status & CRenderTarget::TS_Virtual) ); + + // don't update if virtual + curvb.pdepth->Update(context, curvb.prndr); + bSetTarg = 0; + } + + GL_REPORT_ERRORD(); + if( curvb.prndr->status & CRenderTarget::TS_NeedUpdate ) { +/* if(bSetTarg) { +* printf ( " Here\n "); +* if(s_bWriteDepth) { +* curvb.pdepth->SetRenderTarget(1); +* curvb.pdepth->SetDepthStencilSurface(); +* } +* else +* curvb.pdepth->SetDepthStencilSurface(); +* }*/ + curvb.prndr->Update(context, curvb.pdepth); + } + else { + + //if( (vb[0].prndr != vb[1].prndr && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg ) + curvb.prndr->SetRenderTarget(0); + //if( bSetTarg && ((vb[0].pdepth != vb[1].pdepth && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg) ) + curvb.pdepth->SetDepthStencilSurface(); + + if (conf.mrtdepth && ZeroGS::IsWriteDepth()) curvb.pdepth->SetRenderTarget(1); + + if (s_ptexCurSet[0] == curvb.prndr->ptex) s_ptexCurSet[0] = 0; + if (s_ptexCurSet[1] == curvb.prndr->ptex) s_ptexCurSet[1] = 0; + + curvb.prndr->SetViewport(); + } + + curvb.prndr->SetTarget(curvb.frame.fbp, curvb.scissor, context); + + if( (curvb.zbuf.zbp-curvb.pdepth->fbp) != (curvb.frame.fbp - curvb.prndr->fbp) && curvb.test.zte ) + WARN_LOG("frame and zbuf not aligned\n"); + + curvb.bVarsSetTarg = TRUE; + if( vb[!context].prndr != curvb.prndr ) vb[!context].bVarsSetTarg = FALSE; + + assert( !(curvb.prndr->status&CRenderTarget::TS_NeedUpdate) ); + assert( curvb.pdepth == NULL || !(curvb.pdepth->status&CRenderTarget::TS_NeedUpdate) ); + GL_REPORT_ERRORD(); +} + + +void ZeroGS::SetTexInt (int context, FRAGMENTSHADER* pfragment, int settexint ) { + FUNCLOG + if (settexint) { + tex0Info& tex0 = vb[context].tex0; + + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(tex0, 1); + if (vb[context].bVarsTexSync) { + if (vb[context].pmemtarg != pmemtarg) { + SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, pmemtarg, pfragment, s_bForceTexFlush); + vb[context].bVarsTexSync = TRUE; + } + } + else { + SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, pmemtarg, pfragment, s_bForceTexFlush); + vb[context].bVarsTexSync = TRUE; + + INC_TEXVARS(); + } + } + else { + vb[context].bVarsTexSync = FALSE; + } +} + +// clamp relies on texture width +void ZeroGS::SetTexClamping(int context, FRAGMENTSHADER* pfragment ) { + FUNCLOG + SetShaderCaller("SetTexClamping"); + clampInfo* pclamp = &ZeroGS::vb[context].clamp; + Vector v, v2; + v.x = v.y = 0; + u32* ptex = ZeroGS::vb[context].ptexClamp; + ptex[0] = ptex[1] = 0; + + float fw = ZeroGS::vb[context].tex0.tw ; + float fh = ZeroGS::vb[context].tex0.th ; + + switch(pclamp->wms) { + case 0: + v2.x = -1e10; v2.z = 1e10; + break; + case 1: // pclamp + // suikoden5 movie text + v2.x = 0; v2.z = 1-0.5f/fw; + break; + case 2: // reg pclamp + v2.x = (pclamp->minu+0.5f)/fw; v2.z = (pclamp->maxu-0.5f)/fw; + break; + + case 3: // region rep x + v.x = 0.9999f; + v.z = fw; + v2.x = (float)GPU_TEXMASKWIDTH / fw; + v2.z = pclamp->maxu / fw; + int correctMinu = pclamp->minu & (~pclamp->maxu); // (A && B) || C == (A && (B && !C)) + C + + if( correctMinu != g_PrevBitwiseTexX ) { + g_PrevBitwiseTexX = correctMinu; + ptex[0] = ZeroGS::s_BitwiseTextures.GetTex(correctMinu, 0); + } + break; + } + + switch(pclamp->wmt) { + case 0: + v2.y = -1e10; v2.w = 1e10; + break; + case 1: // pclamp + // suikoden5 movie text + v2.y = 0; v2.w = 1-0.5f/fh; + break; + case 2: // reg pclamp + v2.y = (pclamp->minv+0.5f)/fh; v2.w = (pclamp->maxv-0.5f)/fh; + break; + + case 3: // region rep y + v.y = 0.9999f; + v.w = fh; + v2.y = (float)GPU_TEXMASKWIDTH / fh; + v2.w = pclamp->maxv / fh; + int correctMinv = pclamp->minv & (~pclamp->maxv); // (A && B) || C == (A && (B && !C)) + C + + if( correctMinv != g_PrevBitwiseTexY ) { + g_PrevBitwiseTexY = correctMinv; + ptex[1] = ZeroGS::s_BitwiseTextures.GetTex(correctMinv, ptex[0]); + } + break; + } + + if( pfragment->fTexWrapMode != 0 ) + ZZcgSetParameter4fv(pfragment->fTexWrapMode, v, "g_fTexWrapMode"); + if( pfragment->fClampExts != 0 ) + ZZcgSetParameter4fv(pfragment->fClampExts, v2, "g_fClampExts"); + + +} + +// Fixme should be in Vector lib +inline bool equal_vectors( Vector a, Vector b){ + if ( abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z) + abs(a.w - b.w) < 0.01 ) + return true; + else + return false; +} + +int CheckTexArray[4][2][2][2] = {{{{0,}}}}; +void ZeroGS::SetTexVariables(int context, FRAGMENTSHADER* pfragment ) { + FUNCLOG + if (!vb[context].curprim.tme) return; + assert( !vb[context].bNeedTexCheck ); + + Vector v, v2; + tex0Info& tex0 = vb[context].tex0; + + float fw = (float)tex0.tw; + float fh = (float)tex0.th; + + if( !vb[context].bTexConstsSync ) { + SetShaderCaller("SetTexVariables"); + + // alpha and texture highlighting + Vector valpha, valpha2 ; + + // if clut, use the frame format + int psm = GetTexCPSM(tex0); + +// printf ( "A %d psm, is-clut %d. cpsm %d | %d %d\n", psm, PSMT_ISCLUT(psm), tex0.cpsm, tex0.tfx, tex0.tcc ); + + Vector vblack; + vblack.x = vblack.y = vblack.z = vblack.w = 10; + +/* tcc -- Tecture Color Component 0=RGB, 1=RGBA + use Alpha from TEXA reg when not in PSM + * tfx -- Texture Function (0=modulate, 1=decal, 2=hilight, 3=hilight2) + * + * valpha2 = 0 0 2 1 0 0 2 1 + * 1 0 0 0 1 1 0 0 + * 0 0 2 0 0 1 2 0 + * 0 0 2 0 0 1 2 0 + * + * 0 1,!nNeed 1, psm=2, 10 1, psm=1 + * valpha = 0 0 0 1 0 2 0 0 2ta0 2ta1-2ta0 0 0 2ta0 0 0 0 + * 0 0 0 1 0 1 0 0 ta0 ta1-ta0 0 0 ta0 0 0 0 + * 0 0 1 1 0 1 1 1 1 1 ta0 0 1 1 + * 0 0 1 1 0 1 1 0 1 0 ta0 0 1 0 +*/ + + valpha2.x = ( tex0.tfx == 1 ) ; + valpha2.y = ( tex0.tcc == 1 ) && ( tex0.tfx != 0 ) ; + valpha2.z = ( tex0.tfx != 1 ) * 2 ; + valpha2.w = ( tex0.tfx == 0 ) ; + + if ( tex0.tcc == 0 || !nNeedAlpha(psm) ) { + valpha.x = 0 ; + valpha.y = ( !!tex0.tcc ) * ( 1 + ( tex0.tfx == 0) ) ; } + else { + valpha.x = ( gs.texa.fta[0] ) * ( 1 + ( tex0.tfx == 0) ) ; + valpha.y = ( gs.texa.fta[psm!=1] - gs.texa.fta[0] ) * ( 1 + ( tex0.tfx == 0) ) ; + } + + valpha.z = ( tex0.tfx >= 3 ) ; + valpha.w = ( tex0.tcc == 0 ) || ( tex0.tcc == 1 && tex0.tfx == 2 ) ; + + if( tex0.tcc && gs.texa.aem && psm == PSMCT24 ) + vblack.w = 0; +/* +// Test, old code. + Vector valpha3, valpha4; + switch(tex0.tfx) { + case 0: + valpha3.z = 0; valpha3.w = 0; + valpha4.x = 0; valpha4.y = 0; + valpha4.z = 2; valpha4.w = 1; + + break; + case 1: + valpha3.z = 0; valpha3.w = 1; + valpha4.x = 1; valpha4.y = 0; + valpha4.z = 0; valpha4.w = 0; + + break; + case 2: + valpha3.z = 1; valpha3.w = 1.0f; + valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f; + valpha4.z = 2; valpha4.w = 0; + + break; + + case 3: + valpha3.z = 1; valpha3.w = tex0.tcc ? 0.0f : 1.0f; + valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f; + valpha4.z = 2; valpha4.w = 0; + + break; + } + if( tex0.tcc ) { + + if( tex0.tfx == 1 ) { + //mode.x = 10; + valpha3.z = 0; valpha3.w = 0; + valpha4.x = 1; valpha4.y = 1; + valpha4.z = 0; valpha4.w = 0; + } + + if( nNeedAlpha(psm) ) { + + if( tex0.tfx == 0 ) { + // make sure alpha is mult by two when the output is Cv = Ct*Cf + valpha3.x = 2*gs.texa.fta[0]; + // if 24bit, always choose ta[0] + valpha3.y = 2*gs.texa.fta[psm != 1]; + valpha3.y -= valpha.x; + } + else { + valpha3.x = gs.texa.fta[0]; + // if 24bit, always choose ta[0] + valpha3.y = gs.texa.fta[psm != 1]; + valpha3.y -= valpha.x; + } + } + else { + if( tex0.tfx == 0 ) { + valpha3.x = 0; + valpha3.y = 2; + } + else { + valpha3.x = 0; + valpha3.y = 1; + } + } + } + else { + + // reset alpha to color + valpha3.x = valpha3.y = 0; + valpha3.w = 1; + } + + if ( equal_vectors(valpha, valpha3) && equal_vectors(valpha2, valpha4) ) { + if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][nNeedAlpha(psm)] == 0) { + printf ( "Good issue %d %d %d %d\n", tex0.tfx, tex0.tcc, psm, nNeedAlpha(psm) ); + CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][nNeedAlpha(psm) ] = 1; + } + } + else if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][nNeedAlpha(psm)] == -1) { + printf ("Bad array, %d %d %d %d\n\tolf valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n\tnew valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n", + tex0.tfx, tex0.tcc, psm, nNeedAlpha(psm), + valpha3.x, valpha3.y, valpha3.z, valpha3.w, valpha4.x, valpha4.y, valpha4.z, valpha4.w, + valpha.x, valpha.y, valpha.z, valpha.w, valpha2.x, valpha2.y, valpha2.z, valpha2.w); + CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][nNeedAlpha(psm)] = -1 ; + } + +// Test;*/ + + ZZcgSetParameter4fv(pfragment->fTexAlpha, valpha, "g_fTexAlpha"); + ZZcgSetParameter4fv(pfragment->fTexAlpha2, valpha2, "g_fTexAlpha2"); + if(tex0.tcc && gs.texa.aem && nNeedAlpha(psm)) + ZZcgSetParameter4fv(pfragment->fTestBlack, vblack, "g_fTestBlack"); + + SetTexClamping(context, pfragment); + vb[context].bTexConstsSync = TRUE; + } + + if(s_bTexFlush ) { + if( PSMT_ISCLUT(tex0.psm) ) + texClutWrite(context); + else + s_bTexFlush = FALSE; + } +} + +void ZeroGS::SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, CMemoryTarget* pmemtarg, FRAGMENTSHADER* pfragment, int force) { + FUNCLOG + Vector v; + assert( pmemtarg != NULL && pfragment != NULL && pmemtarg->ptex != NULL); + + if (pmemtarg == NULL || pfragment == NULL || pmemtarg->ptex == NULL ) + { + printf ("SetTexVariablesInt error\n"); + return; + } + + SetShaderCaller("SetTexVariablesInt"); + + float fw = (float)tex0.tw; + float fh = (float)tex0.th; + + bool bUseBilinear = bilinear > 1 || (bilinear && conf.bilinear); + if( bUseBilinear ) { + v.x = (float)fw; + v.y = (float)fh; + v.z = 1.0f / (float)fw; + v.w = 1.0f / (float)fh; + if (pfragment->fRealTexDims) + ZZcgSetParameter4fv(pfragment->fRealTexDims, v, "g_fRealTexDims"); + else + ZZcgSetParameter4fv(cgGetNamedParameter(pfragment->prog,"g_fRealTexDims"),v, "g_fRealTexDims"); + } + + if( m_Blocks[tex0.psm].bpp == 0 ) { + ERROR_LOG("Undefined tex psm 0x%x!\n", tex0.psm); + return; + } + + const BLOCK& b = m_Blocks[tex0.psm]; + + float fbw = (float)tex0.tbw; + + Vector vTexDims; + vTexDims.x = b.vTexDims.x * (fw); + vTexDims.y = b.vTexDims.y * (fh); + vTexDims.z = (float)BLOCK_TEXWIDTH * (0.002f / 64.0f + 0.01f / 128.0f); + vTexDims.w = (float)BLOCK_TEXHEIGHT * 0.1f / 512.0f; + + if (bUseBilinear) { + vTexDims.x *= 1/128.0f; + vTexDims.y *= 1/512.0f; + vTexDims.z *= 1/128.0f; + vTexDims.w *= 1/512.0f; + } + + float g_fitexwidth = g_fiGPU_TEXWIDTH/(float)pmemtarg->widthmult; + float g_texwidth = GPU_TEXWIDTH*(float)pmemtarg->widthmult; + + float fpage = tex0.tbp0*(64.0f*g_fitexwidth);// + 0.05f * g_fitexwidth; + float fpageint = floorf(fpage); + int starttbp = (int)fpage; + + // 2048 is number of words to span one page + //float fblockstride = (2048.0f /(float)(g_texwidth*BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw; + + float fblockstride = (2048.0f /(float)(GPU_TEXWIDTH*(float)pmemtarg->widthmult*BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw; + + assert( fblockstride >= 1.0f ); + + v.x = (float)(2048 * g_fitexwidth); + v.y = fblockstride; + v.z = g_fBlockMult/(float)pmemtarg->widthmult; + v.w = fpage-fpageint ; + + if( g_fBlockMult > 1 ) { + // make sure to divide by mult (since the G16R16 texture loses info) + v.z *= b.bpp * (1/32.0f); + } + + ZZcgSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims"); +// ZZcgSetParameter4fv(pfragment->fTexBlock, b.vTexBlock, "g_fTexBlock"); // I change it, and it's working. Seems casting from Vector to float[4] is ok. + ZZcgSetParameter4fv(pfragment->fTexBlock, &b.vTexBlock.x, "g_fTexBlock"); + ZZcgSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset"); + + // get hardware texture dims + int texheight = (pmemtarg->realheight+pmemtarg->widthmult-1)/pmemtarg->widthmult; + int texwidth = GPU_TEXWIDTH*pmemtarg->widthmult*pmemtarg->channels; + + v.y = 1.0f; + v.x = (fpageint-(float)pmemtarg->realy/(float)pmemtarg->widthmult+0.5f);//*v.y; + v.z = (float)texwidth; + +/* if( !(g_nPixelShaderVer & SHADER_ACCURATE) || bUseBilinear ) { + if (tex0.psm == PSMT4 ) + v.w = 0.0f; + else + v.w = 0.25f; + } + else + v.w = 0.5f;*/ + v.w = 0.5f; + + ZZcgSetParameter4fv(pfragment->fPageOffset, v, "g_fPageOffset"); + + if( force ) + s_ptexCurSet[context] = pmemtarg->ptex->tex; + else + s_ptexNextSet[context] = pmemtarg->ptex->tex; + + vb[context].pmemtarg = pmemtarg; + vb[context].bVarsTexSync = FALSE; +} + +#define SET_ALPHA_COLOR_FACTOR(sign) \ +{ \ + switch(a.c) \ + { \ + case 0: \ + vAlphaBlendColor.y = (sign) ? 2.0f*255.0f/256.0f : -2.0f*255.0f/256.0f; \ + s_srcalpha = GL_ONE; \ + s_alphaeq = (sign) ? GL_FUNC_ADD : GL_FUNC_REVERSE_SUBTRACT; \ + break; \ + \ + case 1: \ + /* if in 24 bit mode, dest alpha should be one */ \ + switch(PSMT_BITMODE(vb[icurctx].prndr->psm)) \ + { \ + case 0: \ + bDestAlphaColor = (a.d!=2)&&((a.a==a.d)||(a.b==a.d)); \ + break; \ + \ + case 1: \ + /* dest alpha should be one */ \ + bDestAlphaColor = 2; \ + break; \ + /* default: 16bit surface, so returned alpha is ok */ \ + } \ + break; \ + \ + case 2: \ + bNeedBlendFactorInAlpha = 1; /* should disable alpha channel writing */ \ + vAlphaBlendColor.y = 0; \ + vAlphaBlendColor.w = (sign) ? (float)a.fix * (2.0f/255.0f) : (float)a.fix * (-2.0f/255.0f); \ + usec = 0; /* change so that alpha comes from source*/ \ + break; \ + } \ +} \ + +//if( a.fix <= 0x80 ) { \ +// dwTemp = (a.fix*2)>255?255:(a.fix*2); \ +// dwTemp = dwTemp|(dwTemp<<8)|(dwTemp<<16)|0x80000000; \ +// printf("bfactor: %8.8x\n", dwTemp); \ +// glBlendColorEXT(dwTemp); \ +// } \ +// else { \ + +void ZeroGS::ResetAlphaVariables() { + FUNCLOG +} + +inline void ZeroGS::NeedFactor( int w ) { + if (bDestAlphaColor == 2){ + bNeedBlendFactorInAlpha = (w+1) ? 1 : 0; + vAlphaBlendColor.y = 0; + vAlphaBlendColor.w = (float)w; + } +} + +static int CheckArray[48][2] = {{0,}}; + +void ZeroGS::SetAlphaVariables(const alphaInfo& a) +{ + FUNCLOG + bool alphaenable = true; + + // TODO: negative color when not clamping turns to positive??? + g_vars._bAlphaState = 0; // set all to zero + bNeedBlendFactorInAlpha = 0; + b2XAlphaTest = 1; + u32 dwTemp = 0xffffffff; + bDestAlphaColor = 0; + + // default + s_srcalpha = GL_ONE; + s_dstalpha = GL_ZERO; + s_alphaeq = GL_FUNC_ADD; + s_rgbeq = 1; + + s_alphaInfo = a; + vAlphaBlendColor = Vector(1,2*255.0f/256.0f,0,0); + u32 usec = a.c; + + +/* + * Alpha table + * a + b + d + * S D + * 0 a -a 1 | 0 0 0 + * 1 0 0 0 | a -a 1 + * 2 0 0 0 | 0 0 0 + * + * d = 0 Cs + * a b 0 Cs 1 Cd 2 0 + * | | + * 0 000: a+-a+ 1 | 0+ 0+ 0 = 1 | 010: a+ 0+ 1 | 0+-a+ 0 = 1-(-a)(+)(-a) | 020: a+ 0+ 1 | 0+ 0+ 0 = 1-(-a) (+) 0 + * 1 100: 0+-a+ 1 | a+ 0+ 0 = 1-a (+) a | 110: 0+ 0+ 1 | a+-a+ 0 = 1 | 120: 0+ 0+ 1 | a+ 0+ 0 = 1 (+) a + * 2 200: 0+-a+ 1 | 0+ 0+ 0 = 1-a (+) 0 | 210: 0+ 0+ 1 | 0+-a+ 0 = 1 (-) a | 220: 0+ 0+ 1 | 0+ 0+ 0 = 1 + * + * d = 1 Cd + * 0 | 1 | 2 + * 0 001: a+-a+ 0 | 0+ 0+ 1 = 0 (+) 1 | 011: a+ 0+ 0 | 0+-a+ 1 = a (+) 1-a | 021: a+ 0+ 0 | 0+ 0+ 1 = a (+) 1 + * 1 101: 0+-a+ 0 | a+ 0+ 1 = (-a)(+) 1-(-a) | 111: 0+ 0+ 0 | a+-a+ 1 = 0 (+) 1 | 121: 0+ 0+ 0 | a+ 0+ 1 = 0 (+) 1-(-a) + * 2 201: 0+-a+ 0 | 0+ 0+ 1 = a (R-)1 | 211: 0+ 0+ 0 | 0+-a+ 1 = 0 (+) 1-a | 221: 0+ 0+ 0 | 0+ 0+ 1 = 0 (+) 1 + * + * d = 2 0 + * 0 | 1 | 2 + * 0 002: a+-a+ 0 | 0+ 0+ 0 = 0 | 012: a+ 0+ 0 | 0+-a+ 0 = a (-) a | 022: a+ 0+ 0 | 0+ 0+ 0 = a (+) 0 + * 1 102: 0+-a+ 0 | a+ 0+ 0 = a (R-) a | 112: 0+ 0+ 0 | a+-a+ 0 = 0 | 122: 0+ 0+ 0 | a+ 0+ 0 = 0 (+) a + * 2 202: 0+-a+ 0 | 0+ 0+ 0 = a (R-) 0 | 212: 0+ 0+ 0 | 0+-a+ 0 = 0 (-) a | 222: 0+ 0+ 0 | 0+ 0+ 0 = 0 + * + * Formulae is: (a-b) * (c /32) + d + * 0 1 2 + * a Cs Cd 0 + * b Cs Cd 0 + * c As Ad ALPHA.FIX + * d Cs Cd 0 + * + * We want to emulate Cs * F1(alpha) + Cd * F2(alpha) by OpenGl blending: (Cs * Ss (+,-,R-) Cd * Sd) + * SET_ALPHA_COLOR_FACTOR(sign) set Set A (as As>>7, Ad>>7 or FIX>>7) with sign. + * So we could use 1+a as one_minus_alpha and -a as alpha. + * + */ + int code = ( a.a * 16 ) + ( a.b * 4 ) + a.d ; + +#define one_minus_alpha (bDestAlphaColor == 2) ? GL_ONE_MINUS_SRC_ALPHA : blendinvalpha[usec] +#define alpha (bDestAlphaColor == 2) ? GL_SRC_ALPHA : blendalpha[usec] +#define one (bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec] +#define zero (bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec] + + switch (code) + { + case 0: // 000 // Cs -- nothing changed + case 20: // 110 = 16+4=20 // Cs + case 40: { // 220 = 32+8=40 // Cs + alphaenable = false; + break; + } + case 2: //002 // 0 -- should be zero + case 22: //112 // 0 + case 42: { //222 = 32+8+2 =42 // 0 + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = GL_ZERO; + break; + } + case 1: //001 // Cd -- Should be destination alpha + case 21: //111, // Cd -- 0*Source + 1*Desrinarion + case 41: { //221 = 32+8+1=41 // Cd -- + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = GL_ONE; + break; + } + case 4: { // 010 // (Cs-Cd)*A+Cs = Cs * (A + 1) - Cd * A + bAlphaClamping = 3; + SET_ALPHA_COLOR_FACTOR(0); // a = -A + + s_rgbeq = GL_FUNC_ADD; // Cs*(1-a)+Cd*a + s_srcrgb = one_minus_alpha ; + s_dstrgb = alpha; + + NeedFactor(-1); + break; + } + case 5: { // 011 // (Cs-Cd)*A+Cs = Cs * A + Cd * (1-A) + bAlphaClamping = 3; // all testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = alpha; + s_dstrgb = one_minus_alpha; + + NeedFactor(1); + break; + } + case 6: { //012 // (Cs-Cd)*FIX + bAlphaClamping = 3; + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_SUBTRACT; + s_srcrgb = alpha; + s_dstrgb = alpha; + + break; + } + case 8: { //020 // Cs*A+Cs = Cs * (1+A) + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(0); // Zeyflitz change this! a = -A + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = one_minus_alpha; // Cs*(1-a). + s_dstrgb = GL_ZERO; + +// NeedFactor(1); + break; + } + case 9: { //021 // Cs*A+Cd + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = alpha; // ZZ change it to. + s_dstrgb = GL_ONE; + break; + } + case 10: { //022 // Cs*A + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = alpha; + s_dstrgb = GL_ZERO; + break; + } + case 16: { //100 + bAlphaClamping = 3; + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = one_minus_alpha; + s_dstrgb = alpha; + + NeedFactor(1); + break; + } + case 17: { //101 + bAlphaClamping = 3; // all testing + SET_ALPHA_COLOR_FACTOR(0); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = alpha; + s_dstrgb = one_minus_alpha; + + NeedFactor(-1); + break; + } + case 18: { //102 + bAlphaClamping = 3; + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_REVERSE_SUBTRACT; + s_srcrgb = alpha; + s_dstrgb = alpha; + + break; + } + case 24: { //120 = 16+8 + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ONE; + s_dstrgb = alpha; + break; + } + case 25: { //121 // Cd*(1+A) + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(0); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = one_minus_alpha; + +// NeedFactor(-1); + break; + } + case 26: { //122 + bAlphaClamping = 2; + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = alpha; + break; + } + case 32: {// 200 = 32 + bAlphaClamping = 1; // min testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = one_minus_alpha; + s_dstrgb = GL_ZERO; + break; + } + case 33: {//201 // -Cs*A + Cd + bAlphaClamping = 1; // min testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_REVERSE_SUBTRACT; + s_srcrgb = alpha; + s_dstrgb = GL_ONE; + break; + } + case 34: //202 + case 38: {//212 + bAlphaClamping = 1; // min testing -- negative values + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = GL_ZERO; + break; + } + case 36: {//210 + bAlphaClamping = 1; // min testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_SUBTRACT; + s_srcrgb = GL_ONE; + s_dstrgb = alpha; + break; + } + case 37: {//211 + bAlphaClamping = 1; // min testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = one_minus_alpha; + break; + } + default: { + ERROR_LOG ( "Bad alpha code %d | %d %d %d\n", code, a.a, a.b, a.d ); + } + } +/* + int t_rgbeq = GL_FUNC_ADD; + int t_srcrgb = GL_ONE; + int t_dstrgb = GL_ZERO; + int tAlphaClamping = 0; + + if( a.a == a.b ) + { // just d remains + if( a.d == 0 ) {} + else + { + t_dstrgb = a.d == 1 ? GL_ONE : GL_ZERO; + t_srcrgb = GL_ZERO; + t_rgbeq = GL_FUNC_ADD; //a) (001) (111) (221) b) (002) (112) (222) + } + goto EndSetAlpha; + } + else if( a.d == 2 ) + { // zero + if( a.a == 2 ) + { + // zero all color + t_srcrgb = GL_ZERO; + t_dstrgb = GL_ZERO; + goto EndSetAlpha; // (202) (212) + } + else if( a.b == 2 ) + { + //b2XAlphaTest = 1; // a) (022) // b) (122) + SET_ALPHA_COLOR_FACTOR(1); + + if( bDestAlphaColor == 2 ) + { + t_rgbeq = GL_FUNC_ADD; + t_srcrgb = a.a == 0 ? GL_ONE : GL_ZERO; + t_dstrgb = a.a == 0 ? GL_ZERO : GL_ONE; + } + else + { + tAlphaClamping = 2; + t_rgbeq = GL_FUNC_ADD; + t_srcrgb = a.a == 0 ? blendalpha[usec] : GL_ZERO; + t_dstrgb = a.a == 0 ? GL_ZERO : blendalpha[usec]; + } + + goto EndSetAlpha; + } + + // nothing is zero, so must do some real blending //b2XAlphaTest = 1; //a) (012) //b) (102) + tAlphaClamping = 3; + + SET_ALPHA_COLOR_FACTOR(1); + + t_rgbeq = a.a == 0 ? GL_FUNC_SUBTRACT : GL_FUNC_REVERSE_SUBTRACT; + t_srcrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec]; + t_dstrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec]; + } + else if( a.a == 2 ) + { // zero + + //b2XAlphaTest = 1; + tAlphaClamping = 1; // min testing + + SET_ALPHA_COLOR_FACTOR(1); + + if( a.b == a.d ) + { + // can get away with 1-A + // a.a == a.d == 2!! (200) (211) + t_rgbeq = GL_FUNC_ADD; + t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendinvalpha[usec] : GL_ZERO; + t_dstrgb = (a.b == 0 || bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec]; + } + else + { + // a) (201) b)(210) + t_rgbeq = a.b==0 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_SUBTRACT; + t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE; + t_dstrgb = (a.b == 0 || bDestAlphaColor == 2 ) ? GL_ONE : blendalpha[usec]; + } + } + else if( a.b == 2 ) + { + tAlphaClamping = 2; // max testing + + SET_ALPHA_COLOR_FACTOR(a.a!=a.d); + + if( a.a == a.d ) + { + // can get away with 1+A, but need to set alpha to negative + // a)(020) + // b)(121) + t_rgbeq = GL_FUNC_ADD; + + if( bDestAlphaColor == 2 ) + { + t_srcrgb = (a.a == 0) ? GL_ONE_MINUS_SRC_ALPHA : GL_ZERO; + t_dstrgb = (a.a == 0) ? GL_ZERO : GL_ONE_MINUS_SRC_ALPHA; + } + else + { + t_srcrgb = a.a == 0 ? blendinvalpha[usec] : GL_ZERO; + t_dstrgb = a.a == 0 ? GL_ZERO : blendinvalpha[usec]; + } + } + else + { + //a)(021) //b)(120) //b2XAlphaTest = 1; + t_rgbeq = GL_FUNC_ADD; + t_srcrgb = (a.a == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE; + t_dstrgb = (a.a == 0 || bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec]; + } + } + else + { + // all 3 components are valid! + tAlphaClamping = 3; // all testing + SET_ALPHA_COLOR_FACTOR(a.a!=a.d); + + if( a.a == a.d ) + { + // can get away with 1+A, but need to set alpha to negative // a) 010, // b) 101 + t_rgbeq = GL_FUNC_ADD; + + if( bDestAlphaColor == 2 ) + { + // all ones + t_srcrgb = a.a == 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA; + t_dstrgb = a.a == 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA; + } + else + { + t_srcrgb = a.a == 0 ? blendinvalpha[usec] : blendalpha[usec]; + t_dstrgb = a.a == 0 ? blendalpha[usec] : blendinvalpha[usec]; + } + } + else + { + t_rgbeq = GL_FUNC_ADD; // a) 011 // b) 100 // + if( bDestAlphaColor == 2 ) + { + // all ones + t_srcrgb = a.a != 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA; + t_dstrgb = a.a != 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA; + } + else + { + //b2XAlphaTest = 1; + t_srcrgb = a.a != 0 ? blendinvalpha[usec] : blendalpha[usec]; + t_dstrgb = a.a != 0 ? blendalpha[usec] : blendinvalpha[usec]; + } + } + } + EndSetAlpha: + + + if ( alphaenable && (t_rgbeq != s_rgbeq || s_srcrgb != t_srcrgb || t_dstrgb != s_dstrgb || tAlphaClamping != bAlphaClamping)) { + if (CheckArray[code][(bDestAlphaColor==2)] != -1) { + printf ( "A code %d, 0x%x, 0x%x, 0x%x, 0x%x %d\n", code, alpha, one_minus_alpha, one, zero, bDestAlphaColor ); + printf ( " Difference %d %d %d %d | 0x%x 0x%x | 0x%x 0x%x | 0x%x 0x%x | %d %d\n", + code, a.a, a.b, a.d, + t_rgbeq, s_rgbeq, t_srcrgb, s_srcrgb, t_dstrgb, s_dstrgb, tAlphaClamping, bAlphaClamping); + CheckArray[code][(bDestAlphaColor==2)] = -1; + } + } + else + if (CheckArray[code][(bDestAlphaColor==2)] == 0){ + printf ( "Add good code %d %d, psm %d destA %d\n", code, a.c, vb[icurctx].prndr->psm, bDestAlphaColor); + CheckArray[code][(bDestAlphaColor==2)] = 1; + }*/ + + + if( alphaenable ) { + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); + zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); + glEnable(GL_BLEND); // always set + } + else + glDisable(GL_BLEND); + + INC_ALPHAVARS(); +} + +void ZeroGS::SetWriteDepth() { + FUNCLOG + if( conf.mrtdepth ) { + s_bWriteDepth = TRUE; + s_nWriteDepthCount = 4; + } +} + +bool ZeroGS::IsWriteDepth() { + FUNCLOG + return s_bWriteDepth; +} + +bool ZeroGS::IsWriteDestAlphaTest() { + FUNCLOG + return s_bDestAlphaTest; +} + +void ZeroGS::SetDestAlphaTest() { + FUNCLOG + s_bDestAlphaTest = TRUE; + s_nWriteDestAlphaTest = 4; +} + +void ZeroGS::SetTexFlush() { + FUNCLOG + s_bTexFlush = TRUE; + +// if( PSMT_ISCLUT(vb[0].tex0.psm) ) +// texClutWrite(0); +// if( PSMT_ISCLUT(vb[1].tex0.psm) ) +// texClutWrite(1); + + if( !s_bForceTexFlush ) + { + if (s_ptexCurSet[0] != s_ptexNextSet[0]) s_ptexCurSet[0] = s_ptexNextSet[0]; + if (s_ptexCurSet[1] != s_ptexNextSet[1]) s_ptexCurSet[1] = s_ptexNextSet[1]; + } +} + diff --git a/plugins/zzogl-pg/opengl/ZZoglSave.cpp b/plugins/zzogl-pg/opengl/ZZoglSave.cpp new file mode 100644 index 0000000000..565436ac94 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZZoglSave.cpp @@ -0,0 +1,152 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009 zeydlitz@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2006 + * + * 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 + */ + +// Save and Load. + +//------------------ Includes +#include "zerogs.h" +#include "targets.h" + +//----------------------- Defines + +#define VBSAVELIMIT ((u32)((u8*)&vb[0].nNextFrameHeight-(u8*)&vb[0])) +#define ZEROGS_SAVEVER 0xaa000005 + +//------------------ Variables + +// Hack for save game compatible! +#ifdef _DEBUG +char *libraryNameX = "ZeroGS-Pg OpenGL (Debug) "; +#elif defined(RELEASE_TO_PUBLIC) +char *libraryNameX = "ZeroGS Playground OpenGL "; +#else +char *libraryNameX = "ZeroGS-Pg OpenGL (Dev) "; +#endif + +//------------------ Code + +extern char *libraryName; +extern u32 s_uTex1Data[2][2], s_uClampData[2]; + +int ZeroGS::Save(s8* pbydata) +{ + if( pbydata == NULL ) + return 40 + 0x00400000 + sizeof(gs) + 2*VBSAVELIMIT + 2*sizeof(frameInfo) + 4 + 256*4; + + s_RTs.ResolveAll(); + s_DepthRTs.ResolveAll(); + + strcpy((char*)pbydata, libraryNameX); + *(u32*)(pbydata+16) = ZEROGS_SAVEVER; + pbydata += 32; + + *(int*)pbydata = icurctx; pbydata += 4; + *(int*)pbydata = VBSAVELIMIT; pbydata += 4; + + memcpy(pbydata, g_pbyGSMemory, 0x00400000); + pbydata += 0x00400000; + + memcpy(pbydata, g_pbyGSClut, 256*4); + pbydata += 256*4; + + *(int*)pbydata = sizeof(gs); + pbydata += 4; + memcpy(pbydata, &gs, sizeof(gs)); + pbydata += sizeof(gs); + + for(int i = 0; i < 2; ++i) { + memcpy(pbydata, &vb[i], VBSAVELIMIT); + pbydata += VBSAVELIMIT; + } + + return 0; +} + +bool ZeroGS::Load(s8* pbydata) +{ + memset(s_uTex1Data, 0, sizeof(s_uTex1Data)); + memset(s_uClampData, 0, sizeof(s_uClampData)); + + g_nCurVBOIndex = 0; + + // first 32 bytes are the id + u32 savever = *(u32*)(pbydata+16); + + if( strncmp((char*)pbydata, libraryNameX, 6) == 0 && (savever == ZEROGS_SAVEVER || savever == 0xaa000004) ) { + + g_MemTargs.Destroy(); + + GSStateReset(); + pbydata += 32; + + int context = *(int*)pbydata; pbydata += 4; + u32 savelimit = VBSAVELIMIT; + + savelimit = *(u32*)pbydata; pbydata += 4; + + memcpy(g_pbyGSMemory, pbydata, 0x00400000); + pbydata += 0x00400000; + + memcpy(g_pbyGSClut, pbydata, 256*4); + pbydata += 256*4; + + memset(&gs, 0, sizeof(gs)); + + int savedgssize; + if( savever == 0xaa000004 ) + savedgssize = 0x1d0; + else { + savedgssize = *(int*)pbydata; + pbydata += 4; + } + + memcpy(&gs, pbydata, savedgssize); + pbydata += savedgssize; + prim = &gs._prim[gs.prac]; + + vb[0].Destroy(); + memcpy(&vb[0], pbydata, min(savelimit, VBSAVELIMIT)); + pbydata += savelimit; + vb[0].pBufferData = NULL; + + vb[1].Destroy(); + memcpy(&vb[1], pbydata, min(savelimit, VBSAVELIMIT)); + pbydata += savelimit; + vb[1].pBufferData = NULL; + + for(int i = 0; i < 2; ++i) { + vb[i].Init(VB_BUFFERSIZE); + vb[i].bNeedZCheck = vb[i].bNeedFrameCheck = 1; + + vb[i].bSyncVars = 0; vb[i].bNeedTexCheck = 1; + memset(vb[i].uCurTex0Data, 0, sizeof(vb[i].uCurTex0Data)); + } + + icurctx = -1; + + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); // switch to the backbuffer + SetFogColor(gs.fogcol); + + GL_REPORT_ERRORD(); + return true; + } + + return false; +} + diff --git a/plugins/zzogl-pg/opengl/ZZoglShaders.cpp b/plugins/zzogl-pg/opengl/ZZoglShaders.cpp new file mode 100644 index 0000000000..9e20627a19 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZZoglShaders.cpp @@ -0,0 +1,627 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009 zeydlitz@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2006 + * + * 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 + */ + +// ZZogl Shader manipulation functions. + +//------------------- Includes +#include "zerogs.h" +#include "ZeroGSShaders/zerogsshaders.h" +#include "zpipe.h" + +// ----------------- Defines + +using namespace ZeroGS; +//------------------ Constants + +// ----------------- Global Variables +namespace ZeroGS { + FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne; + FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16; +} + +// Debug variable, store name of the function that call the shader. +const char* ShaderCallerName = ""; +const char* ShaderHandleName = ""; + +//------------------ Code + +// Error handler. Setup in ZZogl_Create once. +void HandleCgError(CGcontext ctx, CGerror err, void* appdata) +{ + ERROR_LOG("%s->%s: %s\n", ShaderCallerName, ShaderHandleName, cgGetErrorString(err)); + const char* listing = cgGetLastListing(g_cgcontext); + if (listing != NULL) + DEBUG_LOG(" last listing: %s\n", listing); +} + +// This is helper of cgGLSetParameter4fv, made for debug purpose. +// Name could be any string. We must use it on compilation time, because erroneus handler does not +// return name +void ZZcgSetParameter4fv(CGparameter param, const float* v, const char* name) { + ShaderHandleName = name; + cgGLSetParameter4fv(param, v); +} + +#define SET_UNIFORMPARAM(var, name) { \ + p = cgGetNamedParameter(pf->prog, name); \ + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) \ + pf->var = p; \ +} \ + +void SetupFragmentProgramParameters(FRAGMENTSHADER* pf, int context, int type) +{ + // uniform parameters + CGparameter p; + + p = cgGetNamedParameter(pf->prog, "g_fFogColor"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgConnectParameter(g_fparamFogColor, p); + } + + SET_UNIFORMPARAM(sOneColor, "g_fOneColor"); + SET_UNIFORMPARAM(sBitBltZ, "g_fBitBltZ"); + SET_UNIFORMPARAM(sInvTexDims, "g_fInvTexDims"); + SET_UNIFORMPARAM(fTexAlpha2, "fTexAlpha2"); + SET_UNIFORMPARAM(fTexOffset, "g_fTexOffset"); + SET_UNIFORMPARAM(fTexDims, "g_fTexDims"); + SET_UNIFORMPARAM(fTexBlock, "g_fTexBlock"); + SET_UNIFORMPARAM(fClampExts, "g_fClampExts"); + SET_UNIFORMPARAM(fTexWrapMode, "TexWrapMode"); + SET_UNIFORMPARAM(fRealTexDims, "g_fRealTexDims"); + SET_UNIFORMPARAM(fTestBlack, "g_fTestBlack"); + SET_UNIFORMPARAM(fPageOffset, "g_fPageOffset"); + SET_UNIFORMPARAM(fTexAlpha, "fTexAlpha"); + + // textures + p = cgGetNamedParameter(pf->prog, "g_sBlocks"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexBlocks); + cgGLEnableTextureParameter(p); + } + + // cg parameter usage is wrong, so do it manually + if( type == 3 ) { + p = cgGetNamedParameter(pf->prog, "g_sConv16to32"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexConv16to32); + cgGLEnableTextureParameter(p); + } + } + else if( type == 4 ) { + p = cgGetNamedParameter(pf->prog, "g_sConv32to16"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexConv32to16); + cgGLEnableTextureParameter(p); + } + } + else { + p = cgGetNamedParameter(pf->prog, "g_sBilinearBlocks"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexBilinearBlocks); + cgGLEnableTextureParameter(p); + } + } + + p = cgGetNamedParameter(pf->prog, "g_sMemory"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sMemory = p; + } + p = cgGetNamedParameter(pf->prog, "g_sSrcFinal"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sFinal = p; + } + p = cgGetNamedParameter(pf->prog, "g_sBitwiseANDX"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sBitwiseANDX = p; + } + p = cgGetNamedParameter(pf->prog, "g_sBitwiseANDY"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sBitwiseANDY = p; + } + p = cgGetNamedParameter(pf->prog, "g_sCLUT"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sCLUT = p; + } + p = cgGetNamedParameter(pf->prog, "g_sInterlace"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sInterlace = p; + } + + // set global shader constants + p = cgGetNamedParameter(pf->prog, "g_fExactColor"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetParameter4fv(p, Vector(0.5f, (g_GameSettings&GAME_EXACTCOLOR)?0.9f/256.0f:0.5f/256.0f, 0,1/255.0f)); + } + + p = cgGetNamedParameter(pf->prog, "g_fBilinear"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f )); + + p = cgGetNamedParameter(pf->prog, "g_fZBias"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(1.0f/256.0f, 1.0004f, 1, 0.5f)); + + p = cgGetNamedParameter(pf->prog, "g_fc0"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(0,1, 0.001f, 0.5f)); + + p = cgGetNamedParameter(pf->prog, "g_fMult"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(1/1024.0f, 0.2f/1024.0f, 1/128.0f, 1/512.0f)); +} + +void SetupVertexProgramParameters(CGprogram prog, int context) +{ + CGparameter p; + + p = cgGetNamedParameter(prog, "g_fPosXY"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgConnectParameter(g_vparamPosXY[context], p); + + // Set Z-test, log or no log; + if (g_GameSettings&GAME_NOLOGZ) { + g_vdepth = Vector( 255.0 /256.0f, 255.0/65536.0f, 255.0f/(65535.0f*256.0f), 1.0f/(65536.0f*65536.0f)); + vlogz = Vector( 1.0f, 0.0f, 0.0f, 0.0f); + } + else { + g_vdepth = Vector( 256.0f*65536.0f, 65536.0f, 256.0f, 65536.0f*65536.0f); + vlogz = Vector( 0.0f, 1.0f, 0.0f, 0.0f); + } + + p = cgGetNamedParameter(prog, "g_fZ"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) { + cgGLSetParameter4fv(p, g_vdepth); + + p = cgGetNamedParameter(prog, "g_fZMin"); // Switch to flat-z when needed + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) { + //ERROR_LOG ("Use flat-z\n"); + cgGLSetParameter4fv(p, vlogz); + } + else + ERROR_LOG ("Shader file version is outdated! Only is log-Z possible\n"); + } + + Vector vnorm = Vector(g_filog32, 0, 0,0); + p = cgGetNamedParameter(prog, "g_fZNorm"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, vnorm); + + p = cgGetNamedParameter(prog, "g_fBilinear"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f )); + + p = cgGetNamedParameter(prog, "g_fZBias"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(1.0f/256.0f, 1.0004f, 1, 0.5f)); + + p = cgGetNamedParameter(prog, "g_fc0"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(0,1, 0.001f, 0.5f)); +} + +#ifndef DEVBUILD + +#define LOAD_VS(Index, prog) { \ + assert( mapShaderResources.find(Index) != mapShaderResources.end() ); \ + header = mapShaderResources[Index]; \ + assert( (header) != NULL && (header)->index == (Index) ); \ + prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgvProf, NULL, NULL); \ + if( !cgIsProgram(prog) ) { \ + ERROR_LOG("Failed to load vs %d: \n%s\n", Index, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(prog); \ + if( cgGetError() != CG_NO_ERROR ) ERROR_LOG("failed to load program %d\n", Index); \ + SetupVertexProgramParameters(prog, !!(Index&SH_CONTEXT1)); \ +} \ + +#define LOAD_PS(Index, fragment) { \ + bLoadSuccess = true; \ + assert( mapShaderResources.find(Index) != mapShaderResources.end() ); \ + header = mapShaderResources[Index]; \ + fragment.prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgfProf, NULL, NULL); \ + if( !cgIsProgram(fragment.prog) ) { \ + ERROR_LOG("Failed to load ps %d: \n%s\n", Index, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(fragment.prog); \ + if( cgGetError() != CG_NO_ERROR ) { \ + ERROR_LOG("failed to load program %d\n", Index); \ + bLoadSuccess = false; \ + } \ + SetupFragmentProgramParameters(&fragment, !!(Index&SH_CONTEXT1), 0); \ +} \ + +bool ZeroGS::LoadEffects() +{ + assert( s_lpShaderResources != NULL ); + + // process the header + u32 num = *(u32*)s_lpShaderResources; + int compressed_size = *(int*)(s_lpShaderResources+4); + int real_size = *(int*)(s_lpShaderResources+8); + int out; + + char* pbuffer = (char*)malloc(real_size); + inf((char*)s_lpShaderResources+12, &pbuffer[0], compressed_size, real_size, &out); + assert(out == real_size); + + s_lpShaderResources = (u8*)pbuffer; + SHADERHEADER* header = (SHADERHEADER*)s_lpShaderResources; + + mapShaderResources.clear(); + while(num-- > 0 ) { + mapShaderResources[header->index] = header; + ++header; + } + + // clear the textures + for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + ppsTexture[i].prog = NULL; + } +#ifndef _DEBUG + memset(ppsTexture, 0, sizeof(ppsTexture)); +#endif + + return true; +} + +// called +bool ZeroGS::LoadExtraEffects() +{ + SHADERHEADER* header; + bool bLoadSuccess = true; + + const int vsshaders[4] = { SH_REGULARVS, SH_TEXTUREVS, SH_REGULARFOGVS, SH_TEXTUREFOGVS }; + + for(int i = 0; i < 4; ++i) { + LOAD_VS(vsshaders[i], pvs[2*i]); + LOAD_VS((vsshaders[i] | SH_CONTEXT1), pvs[2*i+1]); + //if( conf.mrtdepth ) { + LOAD_VS((vsshaders[i] | SH_WRITEDEPTH), pvs[2*i+8]); + LOAD_VS((vsshaders[i] | SH_WRITEDEPTH | SH_CONTEXT1), pvs[2*i+8+1]); +// } +// else { +// pvs[2*i+8] = pvs[2*i+8+1] = NULL; +// } + } + + LOAD_VS(SH_BITBLTVS, pvsBitBlt.prog); + pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos"); + pvsBitBlt.sBitBltTex = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTex"); + pvsBitBlt.fBitBltTrans = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTrans"); + + LOAD_PS(SH_REGULARPS, ppsRegular[0]); + LOAD_PS(SH_REGULARFOGPS, ppsRegular[1]); + + if( conf.mrtdepth ) { + LOAD_PS(SH_REGULARPS, ppsRegular[2]); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + LOAD_PS(SH_REGULARFOGPS, ppsRegular[3]); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + } + + LOAD_PS(SH_BITBLTPS, ppsBitBlt[0]); + LOAD_PS(SH_BITBLTAAPS, ppsBitBlt[1]); + if( !bLoadSuccess ) { + ERROR_LOG("Failed to load BitBltAAPS, using BitBltPS\n"); + LOAD_PS(SH_BITBLTPS, ppsBitBlt[1]); + } + LOAD_PS(SH_BITBLTDEPTHPS, ppsBitBltDepth); + LOAD_PS(SH_CRTCTARGPS, ppsCRTCTarg[0]); + LOAD_PS(SH_CRTCTARGINTERPS, ppsCRTCTarg[1]); + + g_bCRTCBilinear = TRUE; + LOAD_PS(SH_CRTCPS, ppsCRTC[0]); + if( !bLoadSuccess ) { + // switch to simpler + g_bCRTCBilinear = FALSE; + LOAD_PS(SH_CRTC_NEARESTPS, ppsCRTC[0]); + LOAD_PS(SH_CRTCINTER_NEARESTPS, ppsCRTC[0]); + } + else { + LOAD_PS(SH_CRTCINTERPS, ppsCRTC[1]); + } + + if( !bLoadSuccess ) + ERROR_LOG("Failed to create CRTC shaders\n"); + + LOAD_PS(SH_CRTC24PS, ppsCRTC24[0]); + LOAD_PS(SH_CRTC24INTERPS, ppsCRTC24[1]); + LOAD_PS(SH_ZEROPS, ppsOne); + LOAD_PS(SH_BASETEXTUREPS, ppsBaseTexture); + LOAD_PS(SH_CONVERT16TO32PS, ppsConvert16to32); + LOAD_PS(SH_CONVERT32TO16PS, ppsConvert32to16); + + return true; +} + +FRAGMENTSHADER* ZeroGS::LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed) +{ + int texwrap; + assert( texfilter < NUM_FILTERS ); + + if(g_nPixelShaderVer&SHADER_REDUCED) + texfilter = 0; + assert(!(g_nPixelShaderVer&SHADER_REDUCED) || !exactcolor); + + if( clamp.wms == clamp.wmt ) { + switch( clamp.wms ) { + case 0: texwrap = TEXWRAP_REPEAT; break; + case 1: texwrap = TEXWRAP_CLAMP; break; + case 2: texwrap = TEXWRAP_CLAMP; break; + default: texwrap = TEXWRAP_REGION_REPEAT; break; + } + } + else if( clamp.wms==3||clamp.wmt==3) + texwrap = TEXWRAP_REGION_REPEAT; + else + texwrap = TEXWRAP_REPEAT_CLAMP; + + int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0); + + assert( index < ARRAY_SIZE(ppsTexture) ); + FRAGMENTSHADER* pf = ppsTexture+index; + + if( pbFailed != NULL ) *pbFailed = false; + + if( pf->prog != NULL ) + return pf; + + if( (g_nPixelShaderVer & SHADER_ACCURATE) && mapShaderResources.find(index+NUM_SHADERS*SHADER_ACCURATE) != mapShaderResources.end() ) + index += NUM_SHADERS*SHADER_ACCURATE; + + assert( mapShaderResources.find(index) != mapShaderResources.end() ); + SHADERHEADER* header = mapShaderResources[index]; + if( header == NULL ) + ERROR_LOG("%d %d\n", index, g_nPixelShaderVer); + assert( header != NULL ); + + //DEBUG_LOG("shader:\n%s\n", (char*)(s_lpShaderResources + (header)->offset)); + pf->prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgfProf, NULL, NULL); + if( pf->prog != NULL && cgIsProgram(pf->prog) && cgGetError() == CG_NO_ERROR ) { + SetupFragmentProgramParameters(pf, context, type); + cgGLLoadProgram(pf->prog); + if( cgGetError() != CG_NO_ERROR ) { +// cgGLLoadProgram(pf->prog); +// if( cgGetError() != CG_NO_ERROR ) { + ERROR_LOG("Failed to load shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + return pf; +// } + } + return pf; + } + + ERROR_LOG("Failed to create shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + + return NULL; +} + +#else // not RELEASE_TO_PUBLIC + +#define LOAD_VS(name, prog, shaderver) { \ + prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, EFFECT_NAME, shaderver, name, args); \ + if( !cgIsProgram(prog) ) { \ + ERROR_LOG("Failed to load vs %s: \n%s\n", name, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(prog); \ + if( cgGetError() != CG_NO_ERROR ) ERROR_LOG("failed to load program %s\n", name); \ + SetupVertexProgramParameters(prog, args[0]==context1); \ +} \ + +#ifdef _DEBUG +#define SET_PSFILENAME(frag, name) frag.filename = name +#else +#define SET_PSFILENAME(frag, name) +#endif + +#define LOAD_PS(name, fragment, shaderver) { \ + bLoadSuccess = true; \ + fragment.prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, EFFECT_NAME, shaderver, name, args); \ + if( !cgIsProgram(fragment.prog) ) { \ + ERROR_LOG("Failed to load ps %s: \n%s\n", name, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(fragment.prog); \ + if( cgGetError() != CG_NO_ERROR ) { \ + ERROR_LOG("failed to load program %s\n", name); \ + bLoadSuccess = false; \ + } \ + SetupFragmentProgramParameters(&fragment, args[0]==context1, 0); \ + SET_PSFILENAME(fragment, name); \ +} \ + +bool ZeroGS::LoadEffects() +{ + // clear the textures + for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + } + +#ifndef _DEBUG + memset(ppsTexture, 0, sizeof(ppsTexture)); +#endif + + return true; +} + +bool ZeroGS::LoadExtraEffects() +{ + const char* args[] = { NULL , NULL, NULL, NULL }; + char context0[255], context1[255]; + sprintf(context0, "-I%sctx0", EFFECT_DIR); + sprintf(context1, "-I%sctx1", EFFECT_DIR); + char* write_depth = "-DWRITE_DEPTH"; + bool bLoadSuccess = true; + + const char* pvsshaders[4] = { "RegularVS", "TextureVS", "RegularFogVS", "TextureFogVS" }; + + for(int i = 0; i < 4; ++i) { + args[0] = context0; + args[1] = NULL; + LOAD_VS(pvsshaders[i], pvs[2*i], cgvProf); + args[0] = context1; + LOAD_VS(pvsshaders[i], pvs[2*i+1], cgvProf); + + //if( conf.mrtdepth ) { + args[0] = context0; + args[1] = write_depth; + LOAD_VS(pvsshaders[i], pvs[2*i+8], cgvProf); + args[0] = context1; + LOAD_VS(pvsshaders[i], pvs[2*i+8+1], cgvProf); +// } +// else { +// pvs[2*i+8] = pvs[2*i+8+1] = NULL; +// } + } + + args[0] = context0; + args[1] = NULL; + LOAD_VS("BitBltVS", pvsBitBlt.prog, cgvProf); + pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos"); + pvsBitBlt.sBitBltTex = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTex"); + pvsBitBlt.fBitBltTrans = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTrans"); + + LOAD_PS("RegularPS", ppsRegular[0], cgfProf); + LOAD_PS("RegularFogPS", ppsRegular[1], cgfProf); + + if( conf.mrtdepth ) { + args[0] = context0; + args[1] = write_depth; + LOAD_PS("RegularPS", ppsRegular[2], cgfProf); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + LOAD_PS("RegularFogPS", ppsRegular[3], cgfProf); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + } + + LOAD_PS("BitBltPS", ppsBitBlt[0], cgfProf); + LOAD_PS("BitBltAAPS", ppsBitBlt[1], cgfProf); + if( !bLoadSuccess ) { + ERROR_LOG("Failed to load BitBltAAPS, using BitBltPS\n"); + LOAD_PS("BitBltPS", ppsBitBlt[1], cgfProf); + } + + LOAD_PS("BitBltDepthPS", ppsBitBltDepth, cgfProf); + LOAD_PS("CRTCTargPS", ppsCRTCTarg[0], cgfProf); + LOAD_PS("CRTCTargInterPS", ppsCRTCTarg[1], cgfProf); + + g_bCRTCBilinear = TRUE; + LOAD_PS("CRTCPS", ppsCRTC[0], cgfProf); + if( !bLoadSuccess ) { + // switch to simpler + g_bCRTCBilinear = FALSE; + LOAD_PS("CRTCPS_Nearest", ppsCRTC[0], cgfProf); + LOAD_PS("CRTCInterPS_Nearest", ppsCRTC[0], cgfProf); + } + else { + LOAD_PS("CRTCInterPS", ppsCRTC[1], cgfProf); + } + + if( !bLoadSuccess ) + ERROR_LOG("Failed to create CRTC shaders\n"); + + LOAD_PS("CRTC24PS", ppsCRTC24[0], cgfProf); LOAD_PS("CRTC24InterPS", ppsCRTC24[1], cgfProf); + LOAD_PS("ZeroPS", ppsOne, cgfProf); + LOAD_PS("BaseTexturePS", ppsBaseTexture, cgfProf); + LOAD_PS("Convert16to32PS", ppsConvert16to32, cgfProf); + LOAD_PS("Convert32to16PS", ppsConvert32to16, cgfProf); + +// if( !conf.mrtdepth ) { +// ERROR_LOG("Disabling MRT depth writing\n"); +// s_bWriteDepth = FALSE; +// } + + return true; +} + +FRAGMENTSHADER* ZeroGS::LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed) +{ + int texwrap; + + assert( texfilter < NUM_FILTERS ); + //assert( g_nPixelShaderVer == SHADER_30 ); + if( clamp.wms == clamp.wmt ) { + switch( clamp.wms ) { + case 0: texwrap = TEXWRAP_REPEAT; break; + case 1: texwrap = TEXWRAP_CLAMP; break; + case 2: texwrap = TEXWRAP_CLAMP; break; + default: + texwrap = TEXWRAP_REGION_REPEAT; break; + } + } + else if( clamp.wms==3||clamp.wmt==3) + texwrap = TEXWRAP_REGION_REPEAT; + else + texwrap = TEXWRAP_REPEAT_CLAMP; + + int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0); + + if( pbFailed != NULL ) *pbFailed = false; + + FRAGMENTSHADER* pf = ppsTexture+index; + + if( pf->prog != NULL ) + return pf; + + pf->prog = LoadShaderFromType(EFFECT_DIR, EFFECT_NAME, type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, g_nPixelShaderVer, context); + + if( pf->prog != NULL ) { +#ifdef _DEBUG + char str[255]; + sprintf(str, "Texture%s%d_%sPS", fog?"Fog":"", texfilter, g_pTexTypes[type]); + pf->filename = str; +#endif + SetupFragmentProgramParameters(pf, context, type); + cgGLLoadProgram(pf->prog); + if( cgGetError() != CG_NO_ERROR ) { + // try again +// cgGLLoadProgram(pf->prog); +// if( cgGetError() != CG_NO_ERROR ) { + ERROR_LOG("Failed to load shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + //assert(0); + // NULL makes things crash + return pf; +// } + } + return pf; + } + + ERROR_LOG("Failed to create shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + + return NULL; +} + +#endif // RELEASE_TO_PUBLIC + diff --git a/plugins/zzogl-pg/opengl/ZZoglShoots.cpp b/plugins/zzogl-pg/opengl/ZZoglShoots.cpp new file mode 100644 index 0000000000..19e1dcc80c --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZZoglShoots.cpp @@ -0,0 +1,552 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009 zeydlitz@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2006 + * + * 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 + */ + +// Texture and avi saving to file functions + +//------------------ Includes +#if defined(_WIN32) +# include +# include +# include "resource.h" +#endif +#include + +#include "zerogs.h" +#include "targets.h" +#include "Mem.h" + + +extern "C" { +#ifdef _WIN32 +# define XMD_H +# undef FAR +#define HAVE_BOOLEAN +#endif + +#include "jpeglib.h" // This library want to be after zerogs.h +} + +//------------------ Defines +#define TGA_FILE_NAME_MAX_LENGTH 20 +#define MAX_NUMBER_SAVED_TGA 200 + +//Windows have no snprintf +#if defined(_WIN32) +# define snprintf sprintf_s +#endif +//------------------ Constants + +//------------------ Global Variables +int TexNumber = 0; +int s_aviinit = 0; + +//------------------ Code + +// Set variables need to made a snapshoot when it's possible +void +ZeroGS::SaveSnapshot(const char* filename) +{ + g_bMakeSnapshot = 1; + strSnapshot = filename; +} + +// Save curent renderer in jpeg or TGA format +bool +ZeroGS::SaveRenderTarget(const char* filename, int width, int height, int jpeg) +{ + bool bflip = height < 0; + height = abs(height); + vector data(width*height); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + if (glGetError() != GL_NO_ERROR) + return false; + + if (bflip) { + // swap scanlines + vector scanline(width); + for (int i = 0; i < height/2; ++i) { + memcpy(&scanline[0], &data[i * width], width * 4); + memcpy(&data[i * width], &data[(height - i - 1) * width], width * 4); + memcpy(&data[(height - i - 1) * width], &scanline[0], width * 4); + } + } + + if (jpeg) + return SaveJPEG(filename, width, height, &data[0], 70); + + return SaveTGA(filename, width, height, &data[0]); +} + +// Save selected texture as TGA +bool +ZeroGS::SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height) +{ + vector data(width*height); + glBindTexture(textarget, tex); + glGetTexImage(textarget, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + if (glGetError() != GL_NO_ERROR) + return false; + + return SaveTGA(filename, width, height, &data[0]); +} + +// save image as JPEG +bool +ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const void* pdata, int quality) +{ + u8* image_buffer = new u8[image_width * image_height * 3]; + u8* psrc = (u8*)pdata; + + // input data is rgba format, so convert to rgb + u8* p = image_buffer; + for(int i = 0; i < image_height; ++i) { + for(int j = 0; j < image_width; ++j) { + p[0] = psrc[0]; + p[1] = psrc[1]; + p[2] = psrc[2]; + p += 3; + psrc += 4; + } + } + + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple + * compression/decompression processes, in existence at once. We refer + * to any one struct (and its associated working data) as a "JPEG object". + */ + struct jpeg_compress_struct cinfo; + /* This struct represents a JPEG error handler. It is declared separately + * because applications often want to supply a specialized error handler + * (see the second half of this file for an example). But here we just + * take the easy way out and use the standard error handler, which will + * print a message on stderr and call exit() if compression fails. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct jpeg_error_mgr jerr; + /* More stuff */ + FILE * outfile; /* target file */ + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + int row_stride; /* physical row width in image buffer */ + + /* Step 1: allocate and initialize JPEG compression object */ + + /* We have to set up the error handler first, in case the initialization + * step fails. (Unlikely, but it could happen if you are out of memory.) + * This routine fills in the contents of struct jerr, and returns jerr's + * address which we place into the link field in cinfo. + */ + cinfo.err = jpeg_std_error(&jerr); + /* Now we can initialize the JPEG compression object. */ + jpeg_create_compress(&cinfo); + + /* Step 2: specify data destination (eg, a file) */ + /* Note: steps 2 and 3 can be done in either order. */ + + /* Here we use the library-supplied code to send compressed data to a + * stdio stream. You can also write your own code to do something else. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to write binary files. + */ + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + + /* Step 3: set parameters for compression */ + + /* First we supply a description of the input image. + * Four fields of the cinfo struct must be filled in: + */ + cinfo.image_width = image_width; /* image width and height, in pixels */ + cinfo.image_height = image_height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + /* Now use the library's routine to set default compression parameters. + * (You must set at least cinfo.in_color_space before calling this, + * since the defaults depend on the source color space.) + */ + jpeg_set_defaults(&cinfo); + /* Now you can set any non-default parameters you wish to. + * Here we just illustrate the use of quality (quantization table) scaling: + */ + jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); + + /* Step 4: Start compressor */ + + /* TRUE ensures that we will write a complete interchange-JPEG file. + * Pass TRUE unless you are very sure of what you're doing. + */ + jpeg_start_compress(&cinfo, TRUE); + + /* Step 5: while (scan lines remain to be written) */ + /* jpeg_write_scanlines(...); */ + + /* Here we use the library's state variable cinfo.next_scanline as the + * loop counter, so that we don't have to keep track ourselves. + * To keep things simple, we pass one scanline per call; you can pass + * more if you wish, though. + */ + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + /* jpeg_write_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could pass + * more than one scanline at a time if that's more convenient. + */ + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + + /* Step 6: Finish compression */ + + jpeg_finish_compress(&cinfo); + /* After finish_compress, we can close the output file. */ + fclose(outfile); + + /* Step 7: release JPEG compression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_compress(&cinfo); + + delete image_buffer; + /* And we're done! */ + return true; +} + +#if defined(_MSC_VER) +# pragma pack(push, 1) +#endif + +// This is the defenition of TGA header. We need it to function bellow +struct TGA_HEADER +{ + u8 identsize; // size of ID field that follows 18 u8 header (0 usually) + u8 colourmaptype; // type of colour map 0=none, 1=has palette + u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed + + s16 colourmapstart; // first colour map entry in palette + s16 colourmaplength; // number of colours in palette + u8 colourmapbits; // number of bits per palette entry 15,16,24,32 + + s16 xstart; // image x origin + s16 ystart; // image y origin + s16 width; // image width in pixels + s16 height; // image height in pixels + u8 bits; // image bits per pixel 8,16,24,32 + u8 descriptor; // image descriptor bits (vh flip bits) + + // pixel data follows header +#if defined(_MSC_VER) +}; +# pragma pack(pop) +# else +} __attribute__((packed)); +#endif + +// Save image as TGA +bool +ZeroGS::SaveTGA(const char* filename, int width, int height, void* pdata) +{ + TGA_HEADER hdr; + FILE* f = fopen(filename, "wb"); + if (f == NULL) + return false; + + assert( sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18 ); + + memset(&hdr, 0, sizeof(hdr)); + hdr.imagetype = 2; + hdr.bits = 32; + hdr.width = width; + hdr.height = height; + hdr.descriptor |= 8|(1<<5); // 8bit alpha, flip vertical + + fwrite(&hdr, sizeof(hdr), 1, f); + fwrite(pdata, width * height * 4, 1, f); + fclose(f); + return true; +} + +// AVI capture stuff +// AVI start -- set needed glabal variables +void ZeroGS::StartCapture() +{ + if( !s_aviinit ) { + +#ifdef _WIN32 + START_AVI("zerogs.avi"); +#else // linux + //TODO +#endif + s_aviinit = 1; + } + else { + ERROR_LOG("Continuing from previous capture"); + } + + s_avicapturing = 1; +} + +// Stop. +void ZeroGS::StopCapture() +{ + s_avicapturing = 0; +} + +// And capture frame +// Does not work on linux +void ZeroGS::CaptureFrame() +{ + assert( s_avicapturing && s_aviinit ); + + vector data(nBackbufferWidth*nBackbufferHeight); + glReadPixels(0, 0, nBackbufferWidth, nBackbufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + if (glGetError() != GL_NO_ERROR) + return; + + int fps = SMODE1->CMOD == 3 ? 50 : 60; + +#ifdef _WIN32 + bool bSuccess = ADD_FRAME_FROM_DIB_TO_AVI("AAAA", fps, nBackbufferWidth, nBackbufferHeight, 32, &data[0]); + + if( !bSuccess ) { + s_avicapturing = 0; + STOP_AVI(); + ZeroGS::AddMessage("Failed to create avi"); + return; + } +#else // linux + //TODO +#endif // _WIN32 +} + +// It's nearly the same as save texture +void +ZeroGS::SaveTex(tex0Info* ptex, int usevid) +{ + vector data(ptex->tw*ptex->th); + vector srcdata; + + u32* dst = &data[0]; + u8* psrc = g_pbyGSMemory; + + CMemoryTarget* pmemtarg = NULL; + + if (usevid) { + + pmemtarg = g_MemTargs.GetMemoryTarget(*ptex, 0); + assert( pmemtarg != NULL ); + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, pmemtarg->ptex->tex); + srcdata.resize(pmemtarg->realheight * GPU_TEXWIDTH * pmemtarg->widthmult * 4 * 8); // max of 8 cannels + + glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, pmemtarg->fmt, &srcdata[0]); + + u32 offset = pmemtarg->realy * 4 * GPU_TEXWIDTH; + if (ptex->psm == PSMT8) + offset *= ptex->cpsm <= 1 ? 4 : 2; + else if (ptex->psm == PSMT4) + offset *= ptex->cpsm <= 1 ? 8 : 4; + + psrc = &srcdata[0] - offset; + } + + for (int i = 0; i < ptex->th; ++i) { + for (int j = 0; j < ptex->tw; ++j) { + u32 u = 0; + u32 addr; + switch (ptex->psm) { + case PSMCT32: + addr = getPixelAddress32(j, i, ptex->tbp0, ptex->tbw); + if (addr * 4 < 0x00400000) + u = readPixel32(psrc, j, i, ptex->tbp0, ptex->tbw); + else + u = 0; + break; + case PSMCT24: + addr = getPixelAddress24(j, i, ptex->tbp0, ptex->tbw); + if (addr * 4 < 0x00400000) + u = readPixel24(psrc, j, i, ptex->tbp0, ptex->tbw); + else + u = 0; + break; + case PSMCT16: + addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw); + if (addr * 2 < 0x00400000) { + u = readPixel16(psrc, j, i, ptex->tbp0, ptex->tbw); + u = RGBA16to32(u); + } + else + u = 0; + break; + case PSMCT16S: + addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw); + if (addr * 2 < 0x00400000) { + u = readPixel16S(psrc, j, i, ptex->tbp0, ptex->tbw); + u = RGBA16to32(u); + } + else u = 0; + break; + + case PSMT8: + addr = getPixelAddress8(j, i, ptex->tbp0, ptex->tbw); + if (addr < 0x00400000) { + if (usevid) { + if (ptex->cpsm <= 1) + u = *(u32*)(psrc+4*addr); + else + u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel8(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else + u = 0; + break; + + case PSMT4: + addr = getPixelAddress4(j, i, ptex->tbp0, ptex->tbw); + + if( addr < 2*0x00400000 ) { + if( usevid ) { + if( ptex->cpsm <= 1 ) u = *(u32*)(psrc+4*addr); + else u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel4(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else u = 0; + break; + + case PSMT8H: + addr = getPixelAddress8H(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) { + if( usevid ) { + if( ptex->cpsm <= 1 ) u = *(u32*)(psrc+4*addr); + else u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel8H(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else u = 0; + + break; + + case PSMT4HL: + addr = getPixelAddress4HL(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) { + if( usevid ) { + if( ptex->cpsm <= 1 ) u = *(u32*)(psrc+4*addr); + else u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel4HL(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else u = 0; + break; + + case PSMT4HH: + addr = getPixelAddress4HH(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) { + if( usevid ) { + if( ptex->cpsm <= 1 ) u = *(u32*)(psrc+4*addr); + else u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel4HH(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else u = 0; + break; + + case PSMT32Z: + addr = getPixelAddress32Z(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) + u = readPixel32Z(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + break; + + case PSMT24Z: + addr = getPixelAddress24Z(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) + u = readPixel24Z(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + break; + + case PSMT16Z: + addr = getPixelAddress16Z(j, i, ptex->tbp0, ptex->tbw); + + if( 2*addr < 0x00400000 ) + u = readPixel16Z(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + break; + + case PSMT16SZ: + addr = getPixelAddress16SZ(j, i, ptex->tbp0, ptex->tbw); + + if( 2*addr < 0x00400000 ) + u = readPixel16SZ(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + break; + + default: + assert(0); + } + + *dst++ = u; + } + } + + char Name[TGA_FILE_NAME_MAX_LENGTH]; + snprintf( Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber ); + SaveTGA(Name, ptex->tw, ptex->th, &data[0]); +} + + +// Do the save texture and return file name of it +// Do not forget to call free(), other wise there would be memory leak! +char* +ZeroGS::NamedSaveTex(tex0Info* ptex, int usevid){ + SaveTex(ptex, usevid); + char* Name = (char*)malloc(TGA_FILE_NAME_MAX_LENGTH); + snprintf( Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber ); + + TexNumber++; + if (TexNumber > MAX_NUMBER_SAVED_TGA) + TexNumber = 0; + + return Name; +} + +// Special function, wich is safe to call from any other file, without aviutils problems. +void +ZeroGS::Stop_Avi(){ +#ifdef _WIN32 + STOP_AVI(); +#else +// Does not support yet +#endif +} diff --git a/plugins/zzogl-pg/opengl/ZZoglVB.cpp b/plugins/zzogl-pg/opengl/ZZoglVB.cpp new file mode 100644 index 0000000000..d46daf08cc --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZZoglVB.cpp @@ -0,0 +1,450 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009 zeydlitz@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2006 + * + * 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 + */ + +// Zerogs:VB implementation. +// VB stands for Visual Buffer, as I think + +//------------------- Includes +#include "zerogs.h" +#include "targets.h" +#include "GS.h" +#include "Mem.h" + +using namespace ZeroGS; +// ----------------- Defines +#define MINMAX_SHIFT 3 + +//------------------ Constants + +// ----------------- Global Variables +int maxmin = 608; +// ----------------- Code + +// Constructor. Set width and height to 1 +ZeroGS::VB::VB() +{ + memset(this, 0, sizeof(ZeroGS::VB)); + tex0.tw = 1; + tex0.th = 1; +} + +// Destructor +ZeroGS::VB::~VB() +{ + Destroy(); +} + +void ZeroGS::VB::Destroy() +{ + _aligned_free(pBufferData); pBufferData = NULL; nNumVertices = 0; + + prndr = NULL; + pdepth = NULL; +} + +int ConstraintReson; + +// Return number of 64-pixels block, that guaranted could be hold in memory +// from gsfb.fbp and tbp (textrure pase), zbuf.zbp (Z-buffer), frame.fbp +// (previous frame). +inline int +ZeroGS::VB::FindMinimalMemoryConstrain(int tbp, int maxpos) { + int MinConstraint = maxpos; + + // make sure texture is far away from tbp + { + int Constraint = tbp - gsfb.fbp; + if ((0 < Constraint) && (Constraint < MinConstraint)) { + MinConstraint = Constraint; + ConstraintReson = 1; + } + } + + // offroad uses 0x80 fbp which messes up targets + // special case when double buffering (hamsterball) + // Suikoden 3 require e00 have this issue too. P3 - 0x1000. + if (prndr != NULL) { + int Constraint = frame.fbp - gsfb.fbp; + if ((0x0 < Constraint) && (Constraint < MinConstraint)) { + MinConstraint = Constraint; + ConstraintReson = 2; + } + } + + // old caching method + // zmsk necessary for KH movie + if (!zbuf.zmsk){ + int Constraint = zbuf.zbp - gsfb.fbp; + if ((0 < Constraint) && (Constraint < MinConstraint)) { + MinConstraint = Constraint; + ConstraintReson = 3; + } + } + + // In 16Bit mode in one Word freame stored 2 pixels + if (PSMT_ISHALF(gsfb.psm)) + MinConstraint *= 2; + + return MinConstraint ; +} + +// Return number of 64 pizel words that could be placed in Z-Buffer +// If no Z-buffer present return old constraint +inline int +ZeroGS::VB::FindZbufferMemoryConstrain(int tbp, int maxpos) { + int MinConstraint = maxpos; + + // Check tbp / zbuffer constraint + if (!zbuf.zmsk) { + int Constraint = (tbp - zbuf.zbp) * (PSMT_ISHALF(zbuf.psm) ? 2 : 1 ); + if ((0 < Constraint) && (Constraint < MinConstraint)) { + MinConstraint = Constraint; + ConstraintReson = 4; + } + } + + return MinConstraint; +} + +// Return heights limiter form scissor. . +inline int +GetScissorY(int y) { + int fbh = (y >> MINMAX_SHIFT) + 1; + if ( fbh > 2 && ( fbh & 1 ) ) fbh -= 1; + return fbh; +} + +//There is several reason to limit a height of frame: maximum buffer size, calculated size +//from fbw and fbh and scissoring. +inline int +ZeroGS::VB::FindMinimalHeightConstrain(int maxpos) { + int MinConstraint = maxpos; + + if (maxmin < MinConstraint) { + MinConstraint = maxmin; + ConstraintReson = 5; + } + + if (gsfb.fbh < MinConstraint) { + MinConstraint = gsfb.fbh; + ConstraintReson = 6; + } + + int ScissorConstraint = GetScissorY(scissor.y1) ; + if (ScissorConstraint < MinConstraint) { + MinConstraint = ScissorConstraint; + ConstraintReson = 7; + } + + return MinConstraint; +} + +// 32 bit frames have additional constraints to frame +// maxpos was maximum length of frame at normal constraints +inline void +ZeroGS::VB::CheckFrame32bitRes(int maxpos) +{ + int fbh = frame.fbh; + + if ( frame.fbh >= 512 ) { + // neopets hack + maxmin = min(maxmin, frame.fbh); + frame.fbh = maxmin; + ConstraintReson = 8; + } + + // ffxii hack to stop resolving + if( frame.fbp >= 0x3000 && fbh >= 0x1a0 ) { + int endfbp = frame.fbp + frame.fbw * fbh / (PSMT_ISHALF(gsfb.psm) ? 128 : 64); + + // see if there is a previous render target in the way, reduce + for (CRenderTargetMngr::MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew) { + if ( itnew->second->fbp > frame.fbp && endfbp > itnew->second->fbp ) { + endfbp = itnew->second->fbp; + } + } + + frame.fbh = (endfbp - frame.fbp) * ( PSMT_ISHALF(gsfb.psm) ? 128: 64 ) / frame.fbw; + if (frame.fbh < fbh) + ConstraintReson = 9; + } + +} + +// This is the main code of frame resising. +// It's check several reasons for resize and resize if it needs. +// 4Mb memory in 64 bit (4 bytes) words. +// |------------------------|---------------------|----------|----------|---------------------| +// 0 gsfb.fbp zbuff.zpb tbp frame.fbp 2^20/64 +inline int +ZeroGS::VB::CheckFrameAddConstraints(int tbp) +{ + if ( gsfb.fbw <= 0 ) { + ERROR_LOG_SPAM("render target null, no constraints. Ignoring\n"); + return -1; + } + + // Memory region after fbp + int maxmemorypos = 0x4000 - gsfb.fbp; + ConstraintReson = 0; + + maxmemorypos = FindMinimalMemoryConstrain(tbp, maxmemorypos); + maxmemorypos = FindZbufferMemoryConstrain(tbp, maxmemorypos); + + int maxpos = 64 * maxmemorypos ; + maxpos /= gsfb.fbw; + //? atelier iris crashes without it + if( maxpos > 256 ) + maxpos &= ~0x1f; + + int noscissorpos = maxpos; + int ConstrainR1 = ConstraintReson; + maxpos = FindMinimalHeightConstrain(maxpos); + + frame = gsfb; + frame.fbh = maxpos; + + if( !PSMT_ISHALF(frame.psm) || !(g_GameSettings&GAME_FULL16BITRES) ) + CheckFrame32bitRes( maxpos ) ; + +#ifdef DEVBUILD + if (frame.fbh == 0xe2) + ERROR_LOG ("Const: %x %x %d| %x %d %x %x\n", frame.fbh, frame.fbw, ConstraintReson, noscissorpos, ConstrainR1, tbp, frame.fbp); +#endif + +// Fixme: Reserved psm for framebuffers +// gsfb.psm &= 0xf; // shadow tower + + return 0 ; +} + +// Check if after resising new depth target is need to be used. +// it return 2 if new deapth target used. bool Chose is used to proprely check +// renderer target status +inline int +ZeroGS::VB::CheckFrameResolveDepth(int tbp) +{ + int result = 0 ; + CDepthTarget* pprevdepth = pdepth; + pdepth = NULL; + + // just z changed + frameInfo f = CreateFrame(zbuf.zbp, prndr->fbw, prndr->fbh, zbuf.psm, (zbuf.psm == 0x31) ? 0xff000000 : 0); + + CDepthTarget* pnewdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer|CRenderTargetMngr::TO_StrictHeight| + (zbuf.zmsk?CRenderTargetMngr::TO_Virtual:0), get_maxheight(zbuf.zbp, gsfb.fbw, 0)); + + assert( pnewdepth != NULL && prndr != NULL ); + assert( pnewdepth->fbh == prndr->fbh ); + + if( (pprevdepth != pnewdepth) || (pprevdepth != NULL && (pprevdepth->status & CRenderTarget::TS_NeedUpdate)) ) + result = 2; + + pdepth = pnewdepth; + + return result ; +} + +// Check if after resings new render target is need to be used. Also perform deptaget check +// Return 1 if only render target is changed and 3 -- if both. +inline int +ZeroGS::VB::CheckFrameResolveRender(int tbp) { + int result = 0 ; + + CRenderTarget* pprevrndr = prndr; + prndr = NULL; + CDepthTarget* pprevdepth = pdepth; + pdepth = NULL; + // Set renderes to NULL to prevent Flushing. + + CRenderTarget* pnewtarg = s_RTs.GetTarg(frame, 0, maxmin); + assert( pnewtarg != NULL ); + + // pnewtarg->fbh >= 0x1c0 needed for ffx + if( (pnewtarg->fbh >= 0x1c0) && pnewtarg->fbh > frame.fbh && zbuf.zbp < tbp && !zbuf.zmsk ) { + // check if zbuf is in the way of the texture (suikoden5) + int maxallowedfbh = (tbp-zbuf.zbp)*(PSMT_ISHALF(zbuf.psm)?128:64) / gsfb.fbw; + if (PSMT_ISHALF(gsfb.psm)) maxallowedfbh *= 2; + + if (pnewtarg->fbh > maxallowedfbh + 32) { // +32 needed for ffx2 + // destroy and recreate + s_RTs.DestroyAllTargs(0, 0x100, pnewtarg->fbw); + pnewtarg = s_RTs.GetTarg(frame, 0, maxmin); + assert( pnewtarg != NULL ); + } + } + + PRIM_LOG("frame_%d: fbp=0x%x fbw=%d fbh=%d(%d) psm=0x%x fbm=0x%x\n", ictx, gsfb.fbp, gsfb.fbw, gsfb.fbh, pnewtarg->fbh, gsfb.psm, gsfb.fbm); + + if( (pprevrndr != pnewtarg) || (pprevrndr != NULL && (pprevrndr->status & CRenderTarget::TS_NeedUpdate)) ) + result = 1; + + prndr = pnewtarg; + pdepth = pprevdepth ; + + result |= CheckFrameResolveDepth(tbp) ; + return result ; +} + +// After frame resetting it is possible that 16 to 32 or 32 to 16 (color bits) conversion should be made. +inline void +ZeroGS::VB::CheckFrame16vs32Convesion() +{ + if( prndr->status & CRenderTarget::TS_NeedConvert32) { + if( pdepth->pdepth != 0 ) + pdepth->SetDepthStencilSurface(); + prndr->fbh *= 2; + prndr->ConvertTo32(); + prndr->status &= ~CRenderTarget::TS_NeedConvert32; + } + else if( prndr->status & CRenderTarget::TS_NeedConvert16 ) { + if( pdepth->pdepth != 0 ) + pdepth->SetDepthStencilSurface(); + prndr->fbh /= 2; + prndr->ConvertTo16(); + prndr->status &= ~CRenderTarget::TS_NeedConvert16; + } +} + +// a lot of times, target is too big and overwrites the texture using, +// if tbp != 0, use it to bound +void ZeroGS::VB::CheckFrame(int tbp) +{ + static int bChanged; + if( bNeedZCheck ) { + PRIM_LOG("zbuf_%d: zbp=0x%x psm=0x%x, zmsk=%d\n", ictx, zbuf.zbp, zbuf.psm, zbuf.zmsk); + //zbuf = *zb; + } + + if( m_Blocks[gsfb.psm].bpp == 0 ) { + ERROR_LOG("CheckFrame invalid bpp %d\n", gsfb.psm); + return; + } + + bChanged = 0; + + if( bNeedFrameCheck ) { + + // important to set before calling GetTarg + bNeedFrameCheck = 0; + bNeedZCheck = 0; + if ( CheckFrameAddConstraints(tbp) == -1 ) return ; + + if ( ( prndr != NULL ) && ( prndr->psm != gsfb.psm ) ) { + // behavior for dest alpha varies + ResetAlphaVariables(); + } + + bChanged = CheckFrameResolveRender(tbp) ; + CheckFrame16vs32Convesion(); + } + else if (bNeedZCheck) { + bNeedZCheck = 0; + if (prndr != NULL && gsfb.fbw > 0 ) + CheckFrameResolveDepth(tbp); + } + + if( prndr != NULL ) SetContextTarget(ictx); +} + +// This is the case, most easy to perform, when nothinh was changed +inline void ZeroGS::VB::FlushTexUnchangedClutDontUpdate() { + if (ZZOglGet_cld_TexBits(uNextTex0Data[1])) { + ZeroGS::texClutWrite(ictx); + // invalidate to make sure target didn't change! + bVarsTexSync = FALSE; + } +} + +// The second of easy branch. We does not change storage model, so we don't need to +// update anything except texture itself +inline void ZeroGS::VB::FlushTexClutDontUpdate() { + if (!ZZOglClutStorageUnchanged(uCurTex0Data, uNextTex0Data)) + ZeroGS::Flush(ictx); + + // clut memory isn't going to be loaded so can ignore, but at least update CSA and CPSM! + uCurTex0Data[1] = (uCurTex0Data[1] & CPSM_CSA_NOTMASK) | (uNextTex0Data[1] & CPSM_CSA_BITMASK); + + tex0.csa = ZZOglGet_csa_TexBits(uNextTex0Data[1]); + tex0.cpsm = ZZOglGet_cpsm_TexBits(uNextTex0Data[1]); + + ZeroGS::texClutWrite(ictx); + bVarsTexSync = FALSE; +} + + +// Set texture variables after big change +inline void ZeroGS::VB::FlushTexSetNewVars(u32 psm) { + tex0.tbp0 = ZZOglGet_tbp0_TexBits(uNextTex0Data[0]); + tex0.tbw = ZZOglGet_tbw_TexBitsMult(uNextTex0Data[0]); + tex0.psm = psm; + tex0.tw = ZZOglGet_tw_TexBitsExp(uNextTex0Data[0]); + tex0.th = ZZOglGet_th_TexBitsExp(uNextTex0Data[0], uNextTex0Data[1]); + + tex0.tcc = ZZOglGet_tcc_TexBits(uNextTex0Data[1]); + tex0.tfx = ZZOglGet_tfx_TexBits(uNextTex0Data[1]); + + ZeroGS::fiTexWidth[ictx] = (1/16.0f)/ tex0.tw; + ZeroGS::fiTexHeight[ictx] = (1/16.0f) / tex0.th; +} + +// Flush == draw on screen +// This function made VB state consistant before real Flush. +void ZeroGS::VB::FlushTexData() +{ + assert( bNeedTexCheck ); + + bNeedTexCheck = 0; + + u32 psm = ZZOglGet_psm_TexBitsFix(uNextTex0Data[0]); + + // don't update unless necessary + if (ZZOglAllExceptClutIsSame(uCurTex0Data, uNextTex0Data)) { + // Don't need to do anything if there is no clutting and VB tex data was not changed + if( !PSMT_ISCLUT(psm) ) + return ; + + // have to write the CLUT again if only CLD was changed + if( ZZOglClutMinusCLDunchanged(uCurTex0Data, uNextTex0Data) ) { + FlushTexUnchangedClutDontUpdate(); + return; + } + + // Cld bit is 0 means that clut buffer stay unchanged + if( ZZOglGet_cld_TexBits(uNextTex0Data[1]) == 0 ) { + FlushTexClutDontUpdate(); + return; + } + } + + // Made the full update + ZeroGS::Flush(ictx); + bVarsTexSync = FALSE; + bTexConstsSync = FALSE; + + uCurTex0Data[0] = uNextTex0Data[0]; + uCurTex0Data[1] = uNextTex0Data[1]; + + FlushTexSetNewVars(psm); + + if( PSMT_ISCLUT(psm) ) + ZeroGS::CluttingForFlushedTex(&tex0, uNextTex0Data[1], ictx ) ; +} + + diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile b/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile new file mode 100644 index 0000000000..0df153aa07 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile @@ -0,0 +1,428 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# ZeroGSShaders/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + +pkgdatadir = $(datadir)/ZZOgl-pg +pkgincludedir = $(includedir)/ZZOgl-pg +pkglibdir = $(libdir)/ZZOgl-pg +pkglibexecdir = $(libexecdir)/ZZOgl-pg +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +noinst_PROGRAMS = zgsbuild$(EXEEXT) +subdir = ZeroGSShaders +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_zgsbuild_OBJECTS = zpipe.$(OBJEXT) zerogsshaders.$(OBJEXT) +zgsbuild_OBJECTS = $(am_zgsbuild_OBJECTS) +zgsbuild_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I. +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(zgsbuild_SOURCES) +DIST_SOURCES = $(zgsbuild_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run aclocal-1.11 +AMTAR = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run tar +AUTOCONF = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run autoconf +AUTOHEADER = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run autoheader +AUTOMAKE = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run automake-1.11 +AWK = gawk +CC = gcc +CCAS = gcc +CCASDEPMODE = depmode=gcc3 +CCASFLAGS = -g -O2 +CCDEPMODE = depmode=gcc3 +CFLAGS = -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused -O2 -msse2 +CPP = gcc -E +CPPFLAGS = -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused -O2 -msse2 +CXX = gcc +CXXDEPMODE = depmode=gcc3 +CXXFLAGS = -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused -O2 -msse2 -fno-regmove +CYGPATH_W = echo +DEFS = -DPACKAGE_NAME=\"ZZOgl-pg\" -DPACKAGE_TARNAME=\"zzogl-pg\" -DPACKAGE_VERSION=\"0.1.0\" -DPACKAGE_STRING=\"ZZOgl-pg\ 0.1.0\" -DPACKAGE_BUGREPORT=\"arcum42@gmail.com\" -DPACKAGE_URL=\"\" -DPACKAGE=\"ZZOgl-pg\" -DVERSION=\"0.1.0\" -DNDEBUG=1 -DRELEASE_TO_PUBLIC=1 -DZEROGS_SSE2=1 -DHAVE_GL_GL_H=1 -DHAVE_GL_GLU_H=1 -DHAVE_GL_GLEXT_H=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_CG_CG_H=1 -DHAVE_CG_CGGL_H=1 -DHAVE_JPEGLIB_H=1 +DEPDIR = .deps +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /bin/grep -E +EXEEXT = +GREP = /bin/grep +GTK_CONFIG = pkg-config +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +LDFLAGS = +LIBOBJS = +LIBS = -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 -lGL -lGLU -lGLEW -ljpeg -lpthread -lstdc++ -lz -ldl -lXxf86vm -lCg -lCgGL +LTLIBOBJS = +MAKEINFO = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/missing --run makeinfo +MKDIR_P = /bin/mkdir -p +OBJEXT = o +PACKAGE = ZZOgl-pg +PACKAGE_BUGREPORT = arcum42@gmail.com +PACKAGE_NAME = ZZOgl-pg +PACKAGE_STRING = ZZOgl-pg 0.1.0 +PACKAGE_TARNAME = zzogl-pg +PACKAGE_URL = +PACKAGE_VERSION = 0.1.0 +PATH_SEPARATOR = : +RANLIB = ranlib +SET_MAKE = +SHARED_LDFLAGS = -shared +SHELL = /bin/sh +STRIP = +VERSION = 0.1.0 +ZEROGS_AGE = 0 +ZEROGS_CURRENT = 0 +ZEROGS_RELEASE = 0.1.0 +ZEROGS_REVISION = 1 +ZEROGS_SONAME = libzzoglpg.so.0.1.0 +abs_builddir = /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/ZeroGSShaders +abs_srcdir = /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/ZeroGSShaders +abs_top_builddir = /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl +abs_top_srcdir = /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl +ac_ct_CC = gcc +ac_ct_CXX = gcc +am__include = include +am__leading_dot = . +am__quote = +am__tar = ${AMTAR} chof - "$$tardir" +am__untar = ${AMTAR} xf - +bindir = ${exec_prefix}/bin +build_alias = +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +host_alias = +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /usr/local/src/pcsx2-2/plugins/zzogl-pg/opengl/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = /bin/mkdir -p +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = +program_transform_name = s,x,x, +psdir = ${docdir} +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +so_ext = .so.0.1.0 +srcdir = . +sysconfdir = ${prefix}/etc +target_alias = +top_build_prefix = ../ +top_builddir = .. +top_srcdir = .. +zgsbuild_SOURCES = zpipe.cpp zerogsshaders.cpp +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu ZeroGSShaders/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu ZeroGSShaders/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) +zgsbuild$(EXEEXT): $(zgsbuild_OBJECTS) $(zgsbuild_DEPENDENCIES) + @rm -f zgsbuild$(EXEEXT) + $(CXXLINK) $(zgsbuild_OBJECTS) $(zgsbuild_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/zerogsshaders.Po +include ./$(DEPDIR)/zpipe.Po + +.cpp.o: + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstPROGRAMS ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.am b/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.am new file mode 100644 index 0000000000..6d409c54d0 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.am @@ -0,0 +1,2 @@ +noinst_PROGRAMS = zgsbuild +zgsbuild_SOURCES = zpipe.cpp zerogsshaders.cpp diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.in b/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.in new file mode 100644 index 0000000000..4a04a1bdea --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.in @@ -0,0 +1,428 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +noinst_PROGRAMS = zgsbuild$(EXEEXT) +subdir = ZeroGSShaders +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_zgsbuild_OBJECTS = zpipe.$(OBJEXT) zerogsshaders.$(OBJEXT) +zgsbuild_OBJECTS = $(am_zgsbuild_OBJECTS) +zgsbuild_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(zgsbuild_SOURCES) +DIST_SOURCES = $(zgsbuild_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +GTK_CONFIG = @GTK_CONFIG@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHARED_LDFLAGS = @SHARED_LDFLAGS@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ZEROGS_AGE = @ZEROGS_AGE@ +ZEROGS_CURRENT = @ZEROGS_CURRENT@ +ZEROGS_RELEASE = @ZEROGS_RELEASE@ +ZEROGS_REVISION = @ZEROGS_REVISION@ +ZEROGS_SONAME = @ZEROGS_SONAME@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +so_ext = @so_ext@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +zgsbuild_SOURCES = zpipe.cpp zerogsshaders.cpp +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu ZeroGSShaders/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu ZeroGSShaders/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) +zgsbuild$(EXEEXT): $(zgsbuild_OBJECTS) $(zgsbuild_DEPENDENCIES) + @rm -f zgsbuild$(EXEEXT) + $(CXXLINK) $(zgsbuild_OBJECTS) $(zgsbuild_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zerogsshaders.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zpipe.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstPROGRAMS ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/ZLib.lib b/plugins/zzogl-pg/opengl/ZeroGSShaders/ZLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..7f4cf9ba6ed5cffb6d54b7d1cac4876a65cda678 GIT binary patch literal 101154 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%0A2!I2ly#qCEz6BGQhV03jx0a+yMAFU=!doz!>CU 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

sSdPO@+xFslc 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln b/plugins/zzogl-pg/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln new file mode 100644 index 0000000000..45a5aa122b --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroGSShaders", "ZeroGSShaders_2005.vcproj", "{811D47CC-E5F0-456A-918E-5908005E8FC0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release (to Public)|Win32 = Release (to Public)|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Debug|Win32.ActiveCfg = Debug|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Debug|Win32.Build.0 = Debug|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release (to Public)|Win32.ActiveCfg = Release (to Public)|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release (to Public)|Win32.Build.0 = Release (to Public)|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release|Win32.ActiveCfg = Release|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj b/plugins/zzogl-pg/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj new file mode 100644 index 0000000000..0dfc9ad0c1 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/copytozerogs.bat b/plugins/zzogl-pg/opengl/ZeroGSShaders/copytozerogs.bat new file mode 100644 index 0000000000..32c9820600 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/copytozerogs.bat @@ -0,0 +1 @@ +copy .\Release\ZeroGSShaders.exe ..\ \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.cpp b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.cpp new file mode 100644 index 0000000000..f073da1a8a --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.cpp @@ -0,0 +1,344 @@ +#define _CRT_SECURE_NO_DEPRECATE + +// Builds all possible shader files from ps2hw.fx and stores them in +// a preprocessed database +#include +#include +#include +#include + +#ifdef _WIN32 +# include +#else +# include +#endif + +#include "zpipe.h" + +#include +#include + +#define SAFE_RELEASE(x) { if( (x) != NULL ) { (x)->Release(); x = NULL; } } + +#include +#include + +using namespace std; + +#include "zerogsshaders.h" + +char* srcfilename = "ps2hw.fx"; +char* dstfilename = "ps2hw.dat"; + +#ifndef ArraySize +#define ArraySize(x) (sizeof(x) / sizeof((x)[0])) +#endif + +struct SHADERINFO +{ + int type; + vector buf; +}; + +map mapShaders; +CGcontext g_cgcontext; + +void LoadShader(int index, const char* pshader, CGprofile prof, vector& vargs, int context) +{ + vector realargs; + realargs.reserve(16); + realargs.resize(vargs.size()); + if( vargs.size() > 0 ) + memcpy(&realargs[0], &vargs[0], realargs.size() * sizeof(realargs[0])); + realargs.push_back(context ? "-Ictx1" : "-Ictx0"); + realargs.push_back(NULL); + + CGprogram prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, srcfilename, prof, pshader, &realargs[0]); + if( !cgIsProgram(prog) ) { + printf("Failed to load shader %s: \n%s\n", pshader, cgGetLastListing(g_cgcontext)); + return; + } + + if( mapShaders.find(index) != mapShaders.end() ) { + printf("error: two shaders share the same index %d\n", index); + exit(0); + } + + if( !cgIsProgramCompiled(prog) ) + cgCompileProgram(prog); + + const char* pstr = cgGetProgramString(prog, CG_COMPILED_PROGRAM); + + const char* pprog = strstr(pstr, "#program"); + if( pprog == NULL ) { + printf("program field not found!\n"); + return; + } + pprog += 9; + const char* progend = strchr(pprog, '\r'); + if( progend == NULL ) progend = strchr(pprog, '\n'); + + if( progend == NULL ) { + printf("prog end not found!\n"); + return; + } + + const char* defname = "main"; + + SHADERINFO info; + info.type = 0; + info.buf.resize(strlen(pstr)+1); + + // change the program name to main + memset(&info.buf[0], 0, info.buf.size()); + memcpy(&info.buf[0], pstr, pprog-pstr); + memcpy(&info.buf[pprog-pstr], defname, 4); + memcpy(&info.buf[pprog-pstr+4], progend, strlen(pstr)-(progend-pstr)); + + if( mapShaders.find(index) != mapShaders.end() ) + printf("same shader\n"); + assert( mapShaders.find(index) == mapShaders.end() ); + mapShaders[index] = info; + + cgDestroyProgram(prog); +} + +int main(int argc, char** argv) +{ + printf("usage: [src] [dst] [opts]\n"); + + if( argc >= 2 ) srcfilename = argv[1]; + if( argc >= 3 ) dstfilename = argv[2]; + + FILE* fsrc = fopen(srcfilename, "r"); + if( fsrc == NULL ) { + printf("cannot open %s\n", srcfilename); + return 0; + } + fclose(fsrc); + + g_cgcontext = cgCreateContext(); + if( !cgIsContext(g_cgcontext) ) { + printf("failed to create cg context\n"); + return -1; + } + + CGprofile cgvProf = CG_PROFILE_ARBVP1; + CGprofile cgfProf = CG_PROFILE_ARBFP1; + if( !cgGLIsProfileSupported(cgvProf) != CG_TRUE ) { + printf("arbvp1 not supported\n"); + return 0; + } + if( !cgGLIsProfileSupported(cgfProf) != CG_TRUE ) { + printf("arbfp1 not supported\n"); + return 0; + } + + cgGLEnableProfile(cgvProf); + cgGLEnableProfile(cgfProf); + cgGLSetOptimalOptions(cgvProf); + cgGLSetOptimalOptions(cgfProf); + + vector vmacros; + + LoadShader(SH_BITBLTVS, "BitBltVS", cgvProf, vmacros, 0); + LoadShader(SH_BITBLTPS, "BitBltPS", cgfProf, vmacros, 0); + LoadShader(SH_BITBLTDEPTHPS, "BitBltDepthPS", cgfProf, vmacros, 0); + LoadShader(SH_BITBLTDEPTHMRTPS, "BitBltDepthMRTPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCTARGPS, "CRTCTargPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCPS, "CRTCPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTC_NEARESTPS, "CRTCPS_Nearest", cgfProf, vmacros, 0); + LoadShader(SH_CRTC24PS, "CRTC24PS", cgfProf, vmacros, 0); + LoadShader(SH_ZEROPS, "ZeroPS", cgfProf, vmacros, 0); + LoadShader(SH_BASETEXTUREPS, "BaseTexturePS", cgfProf, vmacros, 0); + LoadShader(SH_BITBLTAAPS, "BitBltPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCTARGINTERPS, "CRTCTargInterPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCINTERPS, "CRTCInterPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCINTER_NEARESTPS, "CRTCInterPS_Nearest", cgfProf, vmacros, 0); + LoadShader(SH_CRTC24INTERPS, "CRTC24InterPS", cgfProf, vmacros, 0); + LoadShader(SH_CONVERT16TO32PS, "Convert16to32PS", cgfProf, vmacros, 0); + LoadShader(SH_CONVERT32TO16PS, "Convert32to16PS", cgfProf, vmacros, 0); + + const int vsshaders[4] = { SH_REGULARVS, SH_TEXTUREVS, SH_REGULARFOGVS, SH_TEXTUREFOGVS }; + const char* pvsshaders[4] = { "RegularVS", "TextureVS", "RegularFogVS", "TextureFogVS" }; + + // load the texture shaders + char str[255], strdir[255]; + + strcpy(strdir, srcfilename); + int i = (int)strlen(strdir); + while(i > 0) { + if( strdir[i-1] == '/' || strdir[i-1] == '\\' ) + break; + --i; + } + + strdir[i] = 0; + + for(i = 0; i < ArraySize(vsshaders); ++i) { + for(int writedepth = 0; writedepth < 2; ++writedepth ) { + + if( writedepth ) vmacros.push_back("-DWRITE_DEPTH"); + LoadShader(vsshaders[i]|(writedepth?SH_WRITEDEPTH:0), pvsshaders[i], cgvProf, vmacros, 0); + LoadShader(vsshaders[i]|(writedepth?SH_WRITEDEPTH:0)|SH_CONTEXT1, pvsshaders[i], cgvProf, vmacros, 1); + if( writedepth ) vmacros.pop_back(); + } + } + + const int psshaders[2] = { SH_REGULARPS, SH_REGULARFOGPS }; + const char* ppsshaders[2] = { "RegularPS", "RegularFogPS" }; + + for(i = 0; i < ArraySize(psshaders); ++i) { + for(int writedepth = 0; writedepth < 2; ++writedepth ) { + if( writedepth ) vmacros.push_back("-DWRITE_DEPTH"); + LoadShader(psshaders[i]|(writedepth?SH_WRITEDEPTH:0), ppsshaders[i], cgfProf, vmacros, 0); + if( writedepth ) vmacros.pop_back(); + } + } + + printf("creating shaders, note that ctx0/ps2hw_ctx.fx, and ctx1/ps2hw_ctx.fx are required\n"); + vmacros.resize(0); + + for(int texwrap = 0; texwrap < NUM_TEXWRAPS; ++texwrap ) { + + if( g_pPsTexWrap[texwrap] != NULL ) + vmacros.push_back(g_pPsTexWrap[texwrap]); + + for(int context = 0; context < 2; ++context) { + + for(int texfilter = 0; texfilter < NUM_FILTERS; ++texfilter) { + for(int fog = 0; fog < 2; ++fog ) { + for(int writedepth = 0; writedepth < 2; ++writedepth ) { + + if( writedepth ) + vmacros.push_back("-DWRITE_DEPTH"); + + for(int testaem = 0; testaem < 2; ++testaem ) { + + if( testaem ) + vmacros.push_back("-DTEST_AEM"); + + for(int exactcolor = 0; exactcolor < 2; ++exactcolor ) { + + if( exactcolor ) + vmacros.push_back("-DEXACT_COLOR"); + + // 32 + sprintf(str, "Texture%s%d_32PS", fog?"Fog":"", texfilter); + + vmacros.push_back("-DACCURATE_DECOMPRESSION"); + LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); + vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + if( texfilter == 0 ) { + // tex32 + sprintf(str, "Texture%s%d_tex32PS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + // clut32 + sprintf(str, "Texture%s%d_clut32PS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + // tex32to16 + sprintf(str, "Texture%s%d_tex32to16PS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + // tex16to8h + sprintf(str, "Texture%s%d_tex16to8hPS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(4, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(4, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + } + + if( exactcolor ) + vmacros.pop_back(); + } + + if( testaem ) + vmacros.pop_back(); + } + + if( writedepth ) + vmacros.pop_back(); + } + } + } + } + + if( g_pPsTexWrap[texwrap] != NULL ) + vmacros.pop_back(); + } + + if( vmacros.size() != 0 ) + printf("error with macros!\n"); + + // create the database + + int num = (int)mapShaders.size(); + + // first compress + vector buffer; + buffer.reserve(10000000); // 10mb + buffer.resize(sizeof(SHADERHEADER)*num); + + i = 0; + for(map::iterator it = mapShaders.begin(); it != mapShaders.end(); ++it, ++i) { + SHADERHEADER h; + h.index = it->first | it->second.type; + h.offset = (int)buffer.size(); + h.size = (int)it->second.buf.size(); + + memcpy(&buffer[0] + i*sizeof(SHADERHEADER), &h, sizeof(SHADERHEADER)); + + size_t cur = buffer.size(); + buffer.resize(cur + it->second.buf.size()); + memcpy(&buffer[cur], &it->second.buf[0], it->second.buf.size()); + } + + int compressed_size; + int real_size = (int)buffer.size(); + vector dst; + dst.resize(buffer.size()); + def(&buffer[0], &dst[0], (int)buffer.size(), &compressed_size); + + // write to file + // fmt: num shaders, size of compressed, compressed data + FILE* fdst = fopen(dstfilename, "wb"); + if( fdst == NULL ) { + printf("failed to open %s\n", dstfilename); + return 0; + } + + fwrite(&num, 4, 1, fdst); + fwrite(&compressed_size, 4, 1, fdst); + fwrite(&real_size, 4, 1, fdst); + fwrite(&dst[0], compressed_size, 1, fdst); + + fclose(fdst); + + printf("wrote %s\n", dstfilename); + + cgDestroyContext(g_cgcontext); + + return 0; +} diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h new file mode 100644 index 0000000000..2ff504cc4e --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h @@ -0,0 +1,94 @@ +#ifndef __ZEROGS_SHADERS_H__ +#define __ZEROGS_SHADERS_H__ + +#include +#include + +#define NUM_FILTERS 2 // texture filtering +#define NUM_TYPES 5 // types of texture read modes +#define NUM_TEXWRAPS 4 // texture wrapping + +#define SHADER_REDUCED 1 // equivalent to ps2.0 +#define SHADER_ACCURATE 2 // for older cards with less accurate math (ps2.x+) + +#define NUM_SHADERS (NUM_FILTERS*NUM_TYPES*NUM_TEXWRAPS*32) // # shaders for a given ps + +const static char* g_pShaders[] = { "full", "reduced", "accurate", "accurate-reduced" }; +const static char* g_pPsTexWrap[] = { "-DREPEAT", "-DCLAMP", "-DREGION_REPEAT", NULL }; +const static char* g_pTexTypes[] = { "32", "tex32", "clut32", "tex32to16", "tex16to8h" }; + +#define TEXWRAP_REPEAT 0 +#define TEXWRAP_CLAMP 1 +#define TEXWRAP_REGION_REPEAT 2 +#define TEXWRAP_REPEAT_CLAMP 3 + +inline int GET_SHADER_INDEX(int type, int texfilter, int texwrap, int fog, int writedepth, int testaem, int exactcolor, int context, int ps) +{ + return type + texfilter*NUM_TYPES + NUM_FILTERS*NUM_TYPES*texwrap + NUM_TEXWRAPS*NUM_FILTERS*NUM_TYPES*(fog+2*writedepth+4*testaem+8*exactcolor+16*context+32*ps); +} + +extern CGcontext g_cgcontext; + +static CGprogram LoadShaderFromType(const char* srcdir, const char* srcfile, int type, int texfilter, int texwrap, int fog, int writedepth, int testaem, int exactcolor, int ps, int context) +{ + assert( texwrap < NUM_TEXWRAPS); + assert( type < NUM_TYPES ); + + char str[255], strctx[255]; + sprintf(str, "Texture%s%d_%sPS", fog?"Fog":"", texfilter, g_pTexTypes[type]); + sprintf(strctx, "-I%s%s", srcdir, context?"ctx1":"ctx0"); + + vector macros; + macros.push_back(strctx); +#ifdef _DEBUG + macros.push_back("-bestprecision"); +#endif + if( g_pPsTexWrap[texwrap] != NULL ) macros.push_back(g_pPsTexWrap[texwrap]); + if( writedepth ) macros.push_back("-DWRITE_DEPTH"); + if( testaem ) macros.push_back("-DTEST_AEM"); + if( exactcolor ) macros.push_back("-DEXACT_COLOR"); + if( ps & SHADER_ACCURATE ) macros.push_back("-DACCURATE_DECOMPRESSION"); + macros.push_back(NULL); + + CGprogram prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, srcfile, CG_PROFILE_ARBFP1, str, ¯os[0]); + if( !cgIsProgram(prog) ) { + printf("Failed to load shader %s: \n%s\n", str, cgGetLastListing(g_cgcontext)); + return NULL; + } + + return prog; +} + +struct SHADERHEADER +{ + unsigned int index, offset, size; // if highest bit of index is set, pixel shader +}; + +#define SH_WRITEDEPTH 0x2000 // depth is written +#define SH_CONTEXT1 0x1000 // context1 is used + +#define SH_REGULARVS 0x8000 +#define SH_TEXTUREVS 0x8001 +#define SH_REGULARFOGVS 0x8002 +#define SH_TEXTUREFOGVS 0x8003 +#define SH_REGULARPS 0x8004 +#define SH_REGULARFOGPS 0x8005 +#define SH_BITBLTVS 0x8006 +#define SH_BITBLTPS 0x8007 +#define SH_BITBLTDEPTHPS 0x8009 +#define SH_CRTCTARGPS 0x800a +#define SH_CRTCPS 0x800b +#define SH_CRTC24PS 0x800c +#define SH_ZEROPS 0x800e +#define SH_BASETEXTUREPS 0x800f +#define SH_BITBLTAAPS 0x8010 +#define SH_CRTCTARGINTERPS 0x8012 +#define SH_CRTCINTERPS 0x8013 +#define SH_CRTC24INTERPS 0x8014 +#define SH_BITBLTDEPTHMRTPS 0x8016 +#define SH_CONVERT16TO32PS 0x8020 +#define SH_CONVERT32TO16PS 0x8021 +#define SH_CRTC_NEARESTPS 0x8022 +#define SH_CRTCINTER_NEARESTPS 0x8023 + +#endif diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/crc32.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/crc32.h new file mode 100644 index 0000000000..8053b6117c --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/deflate.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/deflate.h new file mode 100644 index 0000000000..804d3abe8f --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inffast.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inffast.h new file mode 100644 index 0000000000..1e88d2d97b --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inffixed.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inffixed.h new file mode 100644 index 0000000000..75ed4b5978 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inflate.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inflate.h new file mode 100644 index 0000000000..07bd3e78a7 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inftrees.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inftrees.h new file mode 100644 index 0000000000..b1104c87e7 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/trees.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/trees.h new file mode 100644 index 0000000000..72facf900f --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zconf.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zconf.h new file mode 100644 index 0000000000..5bdcd2c56c --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zconf.in.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zconf.in.h new file mode 100644 index 0000000000..f7176a3b64 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zconf.in.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.in.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zlib.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zlib.h new file mode 100644 index 0000000000..022817927c --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zutil.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zutil.h new file mode 100644 index 0000000000..ecfeb756e7 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zpipe.cpp b/plugins/zzogl-pg/opengl/ZeroGSShaders/zpipe.cpp new file mode 100644 index 0000000000..c259407e32 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zpipe.cpp @@ -0,0 +1,115 @@ +// zpipe.cpp : Defines the entry point for the console application. +// + +#include + +#include +#include +#include + +//#define ZLIB_WINAPI +#include + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress) ; + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) +{ + z_stream strm; + + int ret;//, flush; + unsigned have; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION) ; + if (ret != Z_OK) + return ret; + + /* compress */ + strm.avail_in = bytes_to_compress ; + strm.avail_out = bytes_to_compress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + + ret = deflate(&strm, Z_FINISH) ; + have = bytes_to_compress - strm.avail_out ; + *bytes_after_compressed = have ; + + assert(ret == Z_STREAM_END); /* stream will be complete */ + + /* clean up and return */ + (void)deflateEnd(&strm); + return Z_OK; +} + +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes) +{ + z_stream strm; + + int ret; + //unsigned have; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + if (ret != Z_OK) + return ret; + + /* decompress */ + strm.avail_in = bytes_to_decompress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + strm.avail_out = maximum_after_decompress ; + + ret = inflate(&strm, Z_NO_FLUSH) ; + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return ret; + } + + assert(strm.avail_in == 0); /* all input will be used */ + + if( outbytes != NULL ) + *outbytes = strm.total_out; + + /* clean up and return */ + (void)inflateEnd(&strm); + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + +/* report a zlib or i/o error */ +void zerr(int ret) +{ + fputs("zpipe: ", stderr); + switch (ret) { + case Z_ERRNO: + if (ferror(stdin)) + fputs("error reading stdin\n", stderr); + if (ferror(stdout)) + fputs("error writing stdout\n", stderr); + break; + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + } +} diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zpipe.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zpipe.h new file mode 100644 index 0000000000..2b3f8b3262 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zpipe.h @@ -0,0 +1,7 @@ +#ifndef zpipe_h +#define zpipe_h + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes); + +#endif diff --git a/plugins/zzogl-pg/opengl/buildshaders.bat b/plugins/zzogl-pg/opengl/buildshaders.bat new file mode 100644 index 0000000000..c7698558ae --- /dev/null +++ b/plugins/zzogl-pg/opengl/buildshaders.bat @@ -0,0 +1,3 @@ +ZeroGSShaders.exe ps2hw.fx ps2hw.dat +del Win32\ps2hw.dat Win32\Release\*.res Win32\Debug\*.res +move /y ps2hw.dat Win32\ps2hw.dat \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/common.h b/plugins/zzogl-pg/opengl/common.h new file mode 100644 index 0000000000..698c45c5b9 --- /dev/null +++ b/plugins/zzogl-pg/opengl/common.h @@ -0,0 +1,1142 @@ +/** + * @file common.h + * common internal api header. + */ + +#ifndef COMMON_H +#define COMMON_H + +#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) +# define CONFIG_WIN32 +#endif + +//#define ALT_BITSTREAM_WRITER +//#define ALIGNED_BITSTREAM_WRITER + +#define ALT_BITSTREAM_READER +//#define LIBMPEG2_BITSTREAM_READER +//#define A32_BITSTREAM_READER +#define LIBMPEG2_BITSTREAM_READER_HACK //add BERO + +#ifdef HAVE_AV_CONFIG_H +/* only include the following when compiling package */ +# include "config.h" + +# include +# include +# include +# include +# ifndef __BEOS__ +# include +# else +# include "berrno.h" +# endif +# include + +# ifndef ENODATA +# define ENODATA 61 +# endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#include +#ifndef offsetof +# define offsetof(T,F) ((unsigned int)((char *)&((T *)0)->F)) +#endif + +#define AVOPTION_CODEC_BOOL(name, help, field) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_BOOL } +#define AVOPTION_CODEC_DOUBLE(name, help, field, minv, maxv, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_DOUBLE, minv, maxv, defval } +#define AVOPTION_CODEC_FLAG(name, help, field, flag, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_FLAG, flag, 0, defval } +#define AVOPTION_CODEC_INT(name, help, field, minv, maxv, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_INT, minv, maxv, defval } +#define AVOPTION_CODEC_STRING(name, help, field, str, val) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_STRING, .defval = val, .defstr = str } +#define AVOPTION_CODEC_RCOVERRIDE(name, help, field) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_RCOVERRIDE, .defval = 0, .defstr = NULL } +#define AVOPTION_SUB(ptr) { .name = NULL, .help = (const char*)ptr } +#define AVOPTION_END() AVOPTION_SUB(NULL) + +struct AVOption; +#ifdef HAVE_MMX +extern const struct AVOption avoptions_common[3 + 5]; +#else +extern const struct AVOption avoptions_common[3]; +#endif +extern const struct AVOption avoptions_workaround_bug[11]; + +#endif /* HAVE_AV_CONFIG_H */ + +/* Suppress restrict if it was not defined in config.h. */ +#ifndef restrict +# define restrict +#endif + +#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0) +# define always_inline __attribute__((always_inline)) inline +#else +# define always_inline inline +#endif + +#ifdef CONFIG_WIN32 + +/* windows */ + +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned char uint8_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; +typedef signed char int8_t; +typedef signed int int32_t; +typedef signed __int64 int64_t; + +# ifndef __MINGW32__ +# define int64_t_C(c) (c ## i64) +# define uint64_t_C(c) (c ## i64) + +# define inline __inline + +# else +# define int64_t_C(c) (c ## LL) +# define uint64_t_C(c) (c ## ULL) +# endif /* __MINGW32__ */ + +# ifdef _DEBUG +# define DEBUG +# endif + +# define snprintf _snprintf +# define vsnprintf _vsnprintf + +/* CONFIG_WIN32 end */ +#elif defined (CONFIG_OS2) +/* OS/2 EMX */ + +#include + +#ifndef int64_t_C +#define int64_t_C(c) (c ## LL) +#define uint64_t_C(c) (c ## ULL) +#endif + +#ifdef HAVE_AV_CONFIG_H + +#ifdef USE_FASTMEMCPY +#include "fastmemcpy.h" +#endif + +#include + +#endif /* HAVE_AV_CONFIG_H */ + +/* CONFIG_OS2 end */ +#else + +/* unix */ + +#include + +#ifndef int64_t_C +#define int64_t_C(c) (c ## LL) +#define uint64_t_C(c) (c ## ULL) +#endif + +#ifdef HAVE_AV_CONFIG_H + +# ifdef USE_FASTMEMCPY +# include "fastmemcpy.h" +# endif +# endif /* HAVE_AV_CONFIG_H */ + +#endif /* !CONFIG_WIN32 && !CONFIG_OS2 */ + +#ifdef HAVE_AV_CONFIG_H + +# include "bswap.h" + +# if defined(__MINGW32__) || defined(__CYGWIN__) || \ + defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__)) +# define MANGLE(a) "_" #a +# else +# define MANGLE(a) #a +# endif + +/* debug stuff */ + +# ifndef DEBUG +# define NDEBUG +# endif +# include + +/* dprintf macros */ +# if defined(CONFIG_WIN32) && !defined(__MINGW32__) + +inline void dprintf(const char* fmt,...) {} + +# else + +# ifdef DEBUG +# define dprintf(fmt,args...) printf(fmt, ## args) +# else +# define dprintf(fmt,args...) +# endif + +# endif /* !CONFIG_WIN32 */ + +# define av_abort() do { fprintf(stderr, "Abort at %s:%d\n", __FILE__, __LINE__); abort(); } while (0) + +//rounded divison & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + (1<<((b)-1)))>>(b) : ((a) + (1<<((b)-1))-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +#define ABS(a) ((a) >= 0 ? (a) : (-(a))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) + +extern const uint32_t inverse[256]; + +#ifdef ARCH_X86 +# define FASTDIV(a,b) \ + ({\ + int ret,dmy;\ + asm volatile(\ + "mull %3"\ + :"=d"(ret),"=a"(dmy)\ + :"1"(a),"g"(inverse[b])\ + );\ + ret;\ + }) +#elif defined(CONFIG_FASTDIV) +# define FASTDIV(a,b) ((uint32_t)((((uint64_t)a)*inverse[b])>>32)) +#else +# define FASTDIV(a,b) ((a)/(b)) +#endif + +#ifdef ARCH_X86 +// avoid +32 for shift optimization (gcc should do that ...) +static inline int32_t NEG_SSR32( int32_t a, int8_t s){ + asm ("sarl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +static inline uint32_t NEG_USR32(uint32_t a, int8_t s){ + asm ("shrl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +#else +# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s))) +# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s))) +#endif + +/* bit output */ + +struct PutBitContext; + +typedef void (*WriteDataFunc)(void *, uint8_t *, int); + +typedef struct PutBitContext { +#ifdef ALT_BITSTREAM_WRITER + uint8_t *buf, *buf_end; + int index; +#else + uint32_t bit_buf; + int bit_left; + uint8_t *buf, *buf_ptr, *buf_end; +#endif + int64_t data_out_size; /* in bytes */ +} PutBitContext; + +void init_put_bits(PutBitContext *s, + uint8_t *buffer, int buffer_size, + void *opaque, + void (*write_data)(void *, uint8_t *, int)); + +int64_t get_bit_count(PutBitContext *s); /* XXX: change function name */ +void align_put_bits(PutBitContext *s); +void flush_put_bits(PutBitContext *s); +void put_string(PutBitContext * pbc, char *s); + +/* bit input */ + +typedef struct GetBitContext { + const uint8_t *buffer, *buffer_end; +#ifdef ALT_BITSTREAM_READER + int index; +#elif defined LIBMPEG2_BITSTREAM_READER + uint8_t *buffer_ptr; + uint32_t cache; + int bit_count; +#elif defined A32_BITSTREAM_READER + uint32_t *buffer_ptr; + uint32_t cache0; + uint32_t cache1; + int bit_count; +#endif + int size_in_bits; +} GetBitContext; + +static inline int get_bits_count(GetBitContext *s); + +#define VLC_TYPE int16_t + +typedef struct VLC { + int bits; + VLC_TYPE (*table)[2]; ///< code, bits + int table_size, table_allocated; +} VLC; + +typedef struct RL_VLC_ELEM { + int16_t level; + int8_t len; + uint8_t run; +} RL_VLC_ELEM; + +#ifdef ARCH_SPARC64 +#define UNALIGNED_STORES_ARE_BAD +#endif + +/* used to avoid missaligned exceptions on some archs (alpha, ...) */ +#ifdef ARCH_X86 +# define unaligned32(a) (*(uint32_t*)(a)) +#else +# ifdef __GNUC__ +static inline uint32_t unaligned32(const void *v) { + struct Unaligned { + uint32_t i; + } __attribute__((packed)); + + return ((const struct Unaligned *) v)->i; +} +# elif defined(__DECC) +static inline uint32_t unaligned32(const void *v) { + return *(const __unaligned uint32_t *) v; +} +# else +static inline uint32_t unaligned32(const void *v) { + return *(const uint32_t *) v; +} +# endif +#endif //!ARCH_X86 + +#ifndef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ + unsigned int bit_buf; + int bit_left; + +#ifdef STATS + st_out_bit_counts[st_current_index] += n; +#endif + // DEBUG_LOG("put_bits=%d %x\n", n, value); + assert(n == 32 || value < (1U << n)); + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + + // DEBUG_LOG("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); + /* XXX: optimize */ + if (n < bit_left) { + bit_buf = (bit_buf<> (n - bit_left); +#ifdef UNALIGNED_STORES_ARE_BAD + if (3 & (int) s->buf_ptr) { + s->buf_ptr[0] = bit_buf >> 24; + s->buf_ptr[1] = bit_buf >> 16; + s->buf_ptr[2] = bit_buf >> 8; + s->buf_ptr[3] = bit_buf ; + } else +#endif + *(uint32_t *)s->buf_ptr = be2me_32(bit_buf); + //DEBUG_LOG("bitbuf = %08x\n", bit_buf); + s->buf_ptr+=4; + bit_left+=32 - n; + bit_buf = value; + } + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} +#endif + + +#ifdef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ +# ifdef ALIGNED_BITSTREAM_WRITER +# ifdef ARCH_X86 + asm volatile( + "movl %0, %%ecx \n\t" + "xorl %%eax, %%eax \n\t" + "shrdl %%cl, %1, %%eax \n\t" + "shrl %%cl, %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "andl $0xFFFFFFFC, %%ecx \n\t" + "bswapl %1 \n\t" + "orl %1, (%2, %%ecx) \n\t" + "bswapl %%eax \n\t" + "addl %3, %0 \n\t" + "movl %%eax, 4(%2, %%ecx) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n)) + : "%eax", "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5); + + value<<= 32-n; + + ptr[0] |= be2me_32(value>>(index&31)); + ptr[1] = be2me_32(value<<(32-(index&31))); +//if(n>24) DEBUG_LOG("%d %d\n", n, value); + index+= n; + s->index= index; +# endif +# else //ALIGNED_BITSTREAM_WRITER +# ifdef ARCH_X86 + asm volatile( + "movl $7, %%ecx \n\t" + "andl %0, %%ecx \n\t" + "addl %3, %%ecx \n\t" + "negl %%ecx \n\t" + "shll %%cl, %1 \n\t" + "bswapl %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "orl %1, (%%ecx, %2) \n\t" + "addl %3, %0 \n\t" + "movl $0, 4(%%ecx, %2) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) + : "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); + + ptr[0] |= be2me_32(value<<(32-n-(index&7) )); + ptr[1] = 0; +//if(n>24) DEBUG_LOG("%d %d\n", n, value); + index+= n; + s->index= index; +# endif +# endif //!ALIGNED_BITSTREAM_WRITER +} +#endif + + +static inline uint8_t* pbBufPtr(PutBitContext *s) +{ +#ifdef ALT_BITSTREAM_WRITER + return s->buf + (s->index>>3); +#else + return s->buf_ptr; +#endif +} + +/* Bitstream reader API docs: +name + abritary name which is used as prefix for the internal variables + +gb + getbitcontext + +OPEN_READER(name, gb) + loads gb into local variables + +CLOSE_READER(name, gb) + stores local vars in gb + +UPDATE_CACHE(name, gb) + refills the internal cache from the bitstream + after this call at least MIN_CACHE_BITS will be available, + +GET_CACHE(name, gb) + will output the contents of the internal cache, next bit is MSB of 32 or 64 bit (FIXME 64bit) + +SHOW_UBITS(name, gb, num) + will return the nest num bits + +SHOW_SBITS(name, gb, num) + will return the nest num bits and do sign extension + +SKIP_BITS(name, gb, num) + will skip over the next num bits + note, this is equinvalent to SKIP_CACHE; SKIP_COUNTER + +SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache (note SKIP_COUNTER MUST be called before UPDATE_CACHE / CLOSE_READER) + +SKIP_COUNTER(name, gb, num) + will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS) + +LAST_SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache if it is needed for UPDATE_CACHE otherwise it will do nothing + +LAST_SKIP_BITS(name, gb, num) + is equinvalent to SKIP_LAST_CACHE; SKIP_COUNTER + +for examples see get_bits, show_bits, skip_bits, get_vlc +*/ + +static inline int unaligned32_be(const void *v) +{ +#ifdef CONFIG_ALIGN + const uint8_t *p=v; + return (((p[0]<<8) | p[1])<<16) | (p[2]<<8) | (p[3]); +#else + return be2me_32( unaligned32(v)); //original +#endif +} + +#ifdef ALT_BITSTREAM_READER +# define MIN_CACHE_BITS 25 + +# define OPEN_READER(name, gb)\ + int name##_index= (gb)->index;\ + int name##_cache= 0;\ + +# define CLOSE_READER(name, gb)\ + (gb)->index= name##_index;\ + +# define UPDATE_CACHE(name, gb)\ + name##_cache= unaligned32_be( ((uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\ + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num);\ + +// FIXME name? +# define SKIP_COUNTER(name, gb, num)\ + name##_index += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) ; + +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return s->index; +} +#elif defined LIBMPEG2_BITSTREAM_READER +//libmpeg2 like reader + +# define MIN_CACHE_BITS 17 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + int name##_cache= (gb)->cache;\ + uint8_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache= name##_cache;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +#ifdef LIBMPEG2_BITSTREAM_READER_HACK + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= (int)be2me_16(*(uint16_t*)name##_buffer_ptr) << name##_bit_count;\ + ((uint16_t*)name##_buffer_ptr)++;\ + name##_bit_count-= 16;\ + }\ + +#else + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= ((name##_buffer_ptr[0]<<8) + name##_buffer_ptr[1]) << name##_bit_count;\ + name##_buffer_ptr+=2;\ + name##_bit_count-= 16;\ + }\ + +#endif + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num);\ + +# define SKIP_COUNTER(name, gb, num)\ + name##_bit_count += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num) + +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return (s->buffer_ptr - s->buffer)*8 - 16 + s->bit_count; +} + +#elif defined A32_BITSTREAM_READER + +# define MIN_CACHE_BITS 32 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + uint32_t name##_cache0= (gb)->cache0;\ + uint32_t name##_cache1= (gb)->cache1;\ + uint32_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache0= name##_cache0;\ + (gb)->cache1= name##_cache1;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count > 0){\ + const uint32_t next= be2me_32( *name##_buffer_ptr );\ + name##_cache0 |= NEG_USR32(next,name##_bit_count);\ + name##_cache1 |= next<buffer_ptr - s->buffer)*8 - 32 + s->bit_count; +} + +#endif + +/** + * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). + * if MSB not set it is negative + * @param n length in bits + * @author BERO + */ +static inline int get_xbits(GetBitContext *s, int n){ + register int tmp; + register int32_t cache; + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + cache = GET_CACHE(re,s); + if ((int32_t)cache<0) { //MSB=1 + tmp = NEG_USR32(cache,n); + } else { + // tmp = (-1<index+=n for the ALT_READER :)) + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) +} + +static inline unsigned int get_bits1(GetBitContext *s){ +#ifdef ALT_BITSTREAM_READER + int index= s->index; + uint8_t result= s->buffer[ index>>3 ]; + result<<= (index&0x07); + result>>= 8 - 1; + index++; + s->index= index; + + return result; +#else + return get_bits(s, 1); +#endif +} + +static inline unsigned int show_bits1(GetBitContext *s){ + return show_bits(s, 1); +} + +static inline void skip_bits1(GetBitContext *s){ + skip_bits(s, 1); +} + +void init_get_bits(GetBitContext *s, + const uint8_t *buffer, int buffer_size); + +int check_marker(GetBitContext *s, const char *msg); +void align_get_bits(GetBitContext *s); +int init_vlc(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size); +void free_vlc(VLC *vlc); + +/** + * + * if the vlc code is invalid and max_depth=1 than no bits will be removed + * if the vlc code is invalid and max_depth>1 than the number of bits removed + * is undefined + */ +#define GET_VLC(code, name, gb, table, bits, max_depth)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + code = table[index][0];\ + n = table[index][1];\ +\ + if(max_depth > 1 && n < 0){\ + LAST_SKIP_BITS(name, gb, bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + if(max_depth > 2 && n < 0){\ + LAST_SKIP_BITS(name, gb, nb_bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + }\ + }\ + SKIP_BITS(name, gb, n)\ +} + +#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + level = table[index].level;\ + n = table[index].len;\ +\ + if(max_depth > 1 && n < 0){\ + LAST_SKIP_BITS(name, gb, bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + level;\ + level = table[index].level;\ + n = table[index].len;\ + }\ + run= table[index].run;\ + SKIP_BITS(name, gb, n)\ +} + +// deprecated, dont use get_vlc for new code, use get_vlc2 instead or use GET_VLC directly +static inline int get_vlc(GetBitContext *s, VLC *vlc) +{ + int code; + VLC_TYPE (*table)[2]= vlc->table; + + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + + GET_VLC(code, re, s, table, vlc->bits, 3) + + CLOSE_READER(re, s) + return code; +} + +/** + * parses a vlc code, faster then get_vlc() + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be readed to completly + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + */ +static always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], + int bits, int max_depth) +{ + int code; + + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + + GET_VLC(code, re, s, table, bits, max_depth) + + CLOSE_READER(re, s) + return code; +} + +//#define TRACE + +#ifdef TRACE + +static inline void print_bin(int bits, int n){ + int i; + + for(i=n-1; i>=0; i--){ + DEBUG_LOG("%d", (bits>>i)&1); + } + for(i=n; i<24; i++) + DEBUG_LOG(" "); +} + +static inline int get_bits_trace(GetBitContext *s, int n, char *file, char *func, int line){ + int r= get_bits(s, n); + + print_bin(r, n); + DEBUG_LOG("%5d %2d %3d bit @%5d in %s %s:%d\n", r, n, r, get_bits_count(s)-n, file, func, line); + return r; +} +static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth, char *file, char *func, int line){ + int show= show_bits(s, 24); + int pos= get_bits_count(s); + int r= get_vlc2(s, table, bits, max_depth); + int len= get_bits_count(s) - pos; + int bits2= show>>(24-len); + + print_bin(bits2, len); + + DEBUG_LOG("%5d %2d %3d vlc @%5d in %s %s:%d\n", bits2, len, r, pos, file, func, line); + return r; +} +static inline int get_xbits_trace(GetBitContext *s, int n, char *file, char *func, int line){ + int show= show_bits(s, n); + int r= get_xbits(s, n); + + print_bin(show, n); + DEBUG_LOG("%5d %2d %3d xbt @%5d in %s %s:%d\n", show, n, r, get_bits_count(s)-n, file, func, line); + return r; +} + +#define get_bits(s, n) get_bits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_bits1(s) get_bits_trace(s, 1, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc(s, vlc) get_vlc_trace(s, (vlc)->table, (vlc)->bits, 3, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__) + +#define tprintf printf + +#else //TRACE +#define tprintf(_arg...) {} +#endif + +/* define it to include statistics code (useful only for optimizing + codec efficiency */ +//#define STATS + +#ifdef STATS + +enum { + ST_UNKNOWN, + ST_DC, + ST_INTRA_AC, + ST_INTER_AC, + ST_INTRA_MB, + ST_INTER_MB, + ST_MV, + ST_NB, +}; + +extern int st_current_index; +extern unsigned int st_bit_counts[ST_NB]; +extern unsigned int st_out_bit_counts[ST_NB]; + +void print_stats(void); +#endif + +/* misc math functions */ +extern const uint8_t ff_log2_tab[256]; + +static inline int av_log2(unsigned int v) +{ + int n; + + n = 0; + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +static inline int av_log2_16bit(unsigned int v) +{ + int n; + + n = 0; + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + + +/* median of 3 */ +static inline int mid_pred(int a, int b, int c) +{ + int vmin, vmax; + vmax = vmin = a; + if (b < vmin) + vmin = b; + else + vmax = b; + + if (c < vmin) + vmin = c; + else if (c > vmax) + vmax = c; + + return a + b + c - vmin - vmax; +} + +static inline int clip(int a, int amin, int amax) +{ + if (a < amin) + return amin; + else if (a > amax) + return amax; + else + return a; +} + +/* math */ +extern const uint8_t ff_sqrt_tab[128]; + +int64_t ff_gcd(int64_t a, int64_t b); + +static inline int ff_sqrt(int a) +{ + int ret=0; + int s; + int ret_sq=0; + + if(a<128) return ff_sqrt_tab[a]; + + for(s=15; s>=0; s--){ + int b= ret_sq + (1<<(s*2)) + (ret<>31;\ + level= (level^mask)-mask; +#endif + + +#if __CPU__ >= 686 && !defined(RUNTIME_CPUDETECT) +#define COPY3_IF_LT(x,y,a,b,c,d)\ +asm volatile (\ + "cmpl %0, %3 \n\t"\ + "cmovl %3, %0 \n\t"\ + "cmovl %4, %1 \n\t"\ + "cmovl %5, %2 \n\t"\ + : "+r" (x), "+r" (a), "+r" (c)\ + : "r" (y), "r" (b), "r" (d)\ +); +#else +#define COPY3_IF_LT(x,y,a,b,c,d)\ +if((y)<(x)){\ + (x)=(y);\ + (a)=(b);\ + (c)=(d);\ +} +#endif + +#ifdef ARCH_X86 +static inline long long rdtsc() +{ + long long l; + asm volatile( "rdtsc\n\t" + : "=A" (l) + ); + return l; +} + +#define START_TIMER \ +static uint64_t tsum=0;\ +static int tcount=0;\ +static int tskip_count=0;\ +uint64_t tend;\ +uint64_t tstart= rdtsc();\ + +#define STOP_TIMER(id) \ +tend= rdtsc();\ +if(tcount<2 || tend - tstart < 4*tsum/tcount){\ + tsum+= tend - tstart;\ + tcount++;\ +}else\ + tskip_count++;\ +if(256*256*256*64%(tcount+tskip_count)==0){\ + fprintf(stderr, "%Ld dezicycles in %s, %d runs, %d skips\n", tsum*10/tcount, id, tcount, tskip_count);\ +} +#endif + +#define CLAMP_TO_8BIT(d) ((d > 0xff) ? 0xff : (d < 0) ? 0 : d) + +/* avoid usage of various functions */ +#define malloc please_use_av_malloc +#define free please_use_av_free +#define realloc please_use_av_realloc + +#define CHECKED_ALLOCZ(p, size)\ +{\ + p= av_mallocz(size);\ + if(p==NULL && (size)!=0){\ + perror("malloc");\ + goto fail;\ + }\ +} + +#endif /* HAVE_AV_CONFIG_H */ + +#endif /* COMMON_H */ diff --git a/plugins/zzogl-pg/opengl/common/PS2Edefs.h b/plugins/zzogl-pg/opengl/common/PS2Edefs.h new file mode 100644 index 0000000000..dbd2f1fcff --- /dev/null +++ b/plugins/zzogl-pg/opengl/common/PS2Edefs.h @@ -0,0 +1,876 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2008 Pcsx2 Team + * + * 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 __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct _cdvdSubQ { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct _cdvdTD { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct _cdvdTN { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct _GSdriverInfo { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WINDOWS_ +typedef struct _winInfo { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits) +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int crc, int gameoptions); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +// if start is 1, starts recording spu2 data, else stops +// returns a non zero value if successful +// for now, pData is not used +int CALLBACK GSsetupRecording(int start, void* pData); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// call to give a hint to the PAD plugin to query for the keyboard state. A +// good plugin will query the OS for keyboard state ONLY in this function. +// This function is necessary when multithreading because otherwise +// the PAD plugin can get into deadlocks with the thread that really owns +// the window (and input). Note that PADupdate can be called from a different +// thread than the other functions, so mutex or other multithreading primitives +// have to be added to maintain data integrity. +void CALLBACK PADupdate(int pad); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); + +// all addresses passed by dma will be pointers to the array starting at baseaddr +// This function is necessary to successfully save and reload the spu2 state +void CALLBACK SPU2setDMABaseAddr(uptr baseaddr); + +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); + +// extended funcs +// if start is 1, starts recording spu2 data, else stops +// returns a non zero value if successful +// for now, pData is not used +int CALLBACK SPU2setupRecording(int start, void* pData); + +void CALLBACK SPU2setClockPtr(u32* ptr); +void CALLBACK SPU2setTimeStretcher(short int enable); + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(const char* pTitleFilename); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +void CALLBACK USBasync(u32 cycles); + +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgetLastTag)(u64* ptag); // returns the last tag processed (64 bits) +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int, int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef int (CALLBACK* _GSsetupRecording)(int, void*); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WINDOWS_ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(const char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(const char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); +typedef void (CALLBACK* _PADupdate)(int pad); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2setDMABaseAddr)(uptr baseaddr); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef int (CALLBACK* _SPU2setupRecording)(int, void*); + +typedef void (CALLBACK* _SPU2setClockPtr)(u32*ptr); +typedef void (CALLBACK* _SPU2setTimeStretcher)(short int enable); + +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBasync)(u32 cycles); + + +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +extern _GSinit GSinit; +extern _GSopen GSopen; +extern _GSclose GSclose; +extern _GSshutdown GSshutdown; +extern _GSvsync GSvsync; +extern _GSgifTransfer1 GSgifTransfer1; +extern _GSgifTransfer2 GSgifTransfer2; +extern _GSgifTransfer3 GSgifTransfer3; +extern _GSgetLastTag GSgetLastTag; +extern _GSgifSoftReset GSgifSoftReset; +extern _GSreadFIFO GSreadFIFO; +extern _GSreadFIFO2 GSreadFIFO2; + +extern _GSkeyEvent GSkeyEvent; +extern _GSchangeSaveState GSchangeSaveState; +extern _GSmakeSnapshot GSmakeSnapshot; +extern _GSmakeSnapshot2 GSmakeSnapshot2; +extern _GSirqCallback GSirqCallback; +extern _GSprintf GSprintf; +extern _GSsetBaseMem GSsetBaseMem; +extern _GSsetGameCRC GSsetGameCRC; +extern _GSsetFrameSkip GSsetFrameSkip; +extern _GSsetupRecording GSsetupRecording; +extern _GSreset GSreset; +extern _GSwriteCSR GSwriteCSR; +extern _GSgetDriverInfo GSgetDriverInfo; +#ifdef _WINDOWS_ +extern _GSsetWindowInfo GSsetWindowInfo; +#endif +extern _GSfreeze GSfreeze; +extern _GSconfigure GSconfigure; +extern _GStest GStest; +extern _GSabout GSabout; + +// PAD1 +extern _PADinit PAD1init; +extern _PADopen PAD1open; +extern _PADclose PAD1close; +extern _PADshutdown PAD1shutdown; +extern _PADkeyEvent PAD1keyEvent; +extern _PADstartPoll PAD1startPoll; +extern _PADpoll PAD1poll; +extern _PADquery PAD1query; +extern _PADupdate PAD1update; + +extern _PADgsDriverInfo PAD1gsDriverInfo; +extern _PADconfigure PAD1configure; +extern _PADtest PAD1test; +extern _PADabout PAD1about; + +// PAD2 +extern _PADinit PAD2init; +extern _PADopen PAD2open; +extern _PADclose PAD2close; +extern _PADshutdown PAD2shutdown; +extern _PADkeyEvent PAD2keyEvent; +extern _PADstartPoll PAD2startPoll; +extern _PADpoll PAD2poll; +extern _PADquery PAD2query; +extern _PADupdate PAD2update; + +extern _PADgsDriverInfo PAD2gsDriverInfo; +extern _PADconfigure PAD2configure; +extern _PADtest PAD2test; +extern _PADabout PAD2about; + +// SIO[2] +extern _SIOinit SIOinit[2][9]; +extern _SIOopen SIOopen[2][9]; +extern _SIOclose SIOclose[2][9]; +extern _SIOshutdown SIOshutdown[2][9]; +extern _SIOstartPoll SIOstartPoll[2][9]; +extern _SIOpoll SIOpoll[2][9]; +extern _SIOquery SIOquery[2][9]; + +extern _SIOconfigure SIOconfigure[2][9]; +extern _SIOtest SIOtest[2][9]; +extern _SIOabout SIOabout[2][9]; + +// SPU2 +extern _SPU2init SPU2init; +extern _SPU2open SPU2open; +extern _SPU2close SPU2close; +extern _SPU2shutdown SPU2shutdown; +extern _SPU2write SPU2write; +extern _SPU2read SPU2read; +extern _SPU2readDMA4Mem SPU2readDMA4Mem; +extern _SPU2writeDMA4Mem SPU2writeDMA4Mem; +extern _SPU2interruptDMA4 SPU2interruptDMA4; +extern _SPU2readDMA7Mem SPU2readDMA7Mem; +extern _SPU2writeDMA7Mem SPU2writeDMA7Mem; +extern _SPU2setDMABaseAddr SPU2setDMABaseAddr; +extern _SPU2interruptDMA7 SPU2interruptDMA7; +extern _SPU2ReadMemAddr SPU2ReadMemAddr; +extern _SPU2setupRecording SPU2setupRecording; +extern _SPU2WriteMemAddr SPU2WriteMemAddr; +extern _SPU2irqCallback SPU2irqCallback; + +extern _SPU2setClockPtr SPU2setClockPtr; +extern _SPU2setTimeStretcher SPU2setTimeStretcher; + +extern _SPU2async SPU2async; +extern _SPU2freeze SPU2freeze; +extern _SPU2configure SPU2configure; +extern _SPU2test SPU2test; +extern _SPU2about SPU2about; + +// CDVD +extern _CDVDinit CDVDinit; +extern _CDVDopen CDVDopen; +extern _CDVDclose CDVDclose; +extern _CDVDshutdown CDVDshutdown; +extern _CDVDreadTrack CDVDreadTrack; +extern _CDVDgetBuffer CDVDgetBuffer; +extern _CDVDreadSubQ CDVDreadSubQ; +extern _CDVDgetTN CDVDgetTN; +extern _CDVDgetTD CDVDgetTD; +extern _CDVDgetTOC CDVDgetTOC; +extern _CDVDgetDiskType CDVDgetDiskType; +extern _CDVDgetTrayStatus CDVDgetTrayStatus; +extern _CDVDctrlTrayOpen CDVDctrlTrayOpen; +extern _CDVDctrlTrayClose CDVDctrlTrayClose; + +extern _CDVDconfigure CDVDconfigure; +extern _CDVDtest CDVDtest; +extern _CDVDabout CDVDabout; +extern _CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +extern _DEV9init DEV9init; +extern _DEV9open DEV9open; +extern _DEV9close DEV9close; +extern _DEV9shutdown DEV9shutdown; +extern _DEV9read8 DEV9read8; +extern _DEV9read16 DEV9read16; +extern _DEV9read32 DEV9read32; +extern _DEV9write8 DEV9write8; +extern _DEV9write16 DEV9write16; +extern _DEV9write32 DEV9write32; +extern _DEV9readDMA8Mem DEV9readDMA8Mem; +extern _DEV9writeDMA8Mem DEV9writeDMA8Mem; +extern _DEV9irqCallback DEV9irqCallback; +extern _DEV9irqHandler DEV9irqHandler; + +extern _DEV9configure DEV9configure; +extern _DEV9freeze DEV9freeze; +extern _DEV9test DEV9test; +extern _DEV9about DEV9about; + +// USB +extern _USBinit USBinit; +extern _USBopen USBopen; +extern _USBclose USBclose; +extern _USBshutdown USBshutdown; +extern _USBread8 USBread8; +extern _USBread16 USBread16; +extern _USBread32 USBread32; +extern _USBwrite8 USBwrite8; +extern _USBwrite16 USBwrite16; +extern _USBwrite32 USBwrite32; +extern _USBasync USBasync; + +extern _USBirqCallback USBirqCallback; +extern _USBirqHandler USBirqHandler; +extern _USBsetRAM USBsetRAM; + +extern _USBconfigure USBconfigure; +extern _USBfreeze USBfreeze; +extern _USBtest USBtest; +extern _USBabout USBabout; + +// FW +extern _FWinit FWinit; +extern _FWopen FWopen; +extern _FWclose FWclose; +extern _FWshutdown FWshutdown; +extern _FWread32 FWread32; +extern _FWwrite32 FWwrite32; +extern _FWirqCallback FWirqCallback; + +extern _FWconfigure FWconfigure; +extern _FWfreeze FWfreeze; +extern _FWtest FWtest; +extern _FWabout FWabout; +#endif + +#ifdef __cplusplus +} // End extern "C" +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/zzogl-pg/opengl/common/PS2Etypes.h b/plugins/zzogl-pg/opengl/common/PS2Etypes.h new file mode 100644 index 0000000000..258deaaded --- /dev/null +++ b/plugins/zzogl-pg/opengl/common/PS2Etypes.h @@ -0,0 +1,234 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2008 Pcsx2 Team + * + * 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 __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#if defined (__linux__) && !defined(__LINUX__) // some distributions are lower case +#define __LINUX__ +#endif + +#ifdef __CYGWIN__ +#define __LINUX__ +#endif + +// Renamed ARRAYSIZE to ArraySize -- looks nice and gets rid of Windows.h conflicts (air) +#ifndef ArraySize +#define ArraySize(x) (sizeof(x)/sizeof((x)[0])) +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// jASSUME - give hints to the optimizer +// This is primarily useful for the default case switch optimizer, which enables VC to +// generate more compact switches. + +#ifdef NDEBUG +# define jBREAKPOINT() ((void) 0) +# ifdef _MSC_VER +# define jASSUME(exp) (__assume(exp)) +# else +# define jASSUME(exp) ((void) sizeof(exp)) +# endif +#else +# if defined(_MSC_VER) +# define jBREAKPOINT() do { __asm int 3 } while(0) +# else +# define jBREAKPOINT() ((void) *(volatile char *) 0) +# endif +# define jASSUME(exp) if(exp) ; else jBREAKPOINT() +#endif + +// disable the default case in a switch +#define jNO_DEFAULT \ +{ \ + break; \ + \ +default: \ + jASSUME(0); \ + break; \ +} + +////////////////////////////////////////////////////////////////////////////////////////// +// Basic Atomic Types + +#if defined(_MSC_VER) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +typedef unsigned int uint; + +// Note: building the 'extern' into PCSX2_ALIGNED16_DECL fixes Visual Assist X's intellisense. + +#define PCSX2_ALIGNED(alig,x) __declspec(align(alig)) x +#define PCSX2_ALIGNED_EXTERN(alig,x) __declspec(align(alig)) x +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#define PCSX2_ALIGNED16_EXTERN(x) extern __declspec(align(16)) x + +#define __naked __declspec(naked) +#define CALLBACK __stdcall + +#else // _MSC_VER + +#ifdef __LINUX__ + +#ifdef HAVE_STDINT_H +#include "stdint.h" + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef uintptr_t uptr; +typedef intptr_t sptr; + +#else // HAVE_STDINT_H + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#endif // HAVE_STDINT_H + +typedef unsigned int uint; + +#define LONG long +typedef union _LARGE_INTEGER +{ + long long QuadPart; +} LARGE_INTEGER; + +#define __fastcall __attribute__((fastcall)) +#define __unused __attribute__((unused)) +#define _inline __inline__ __attribute__((unused)) +#define __forceinline __attribute__((always_inline,unused)) +#define __naked // GCC lacks the naked specifier +#define CALLBACK // CALLBACK is win32-specific mess + +#endif // __LINUX__ + +#define PCSX2_ALIGNED(alig,x) x __attribute((aligned(alig))) +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) + +// fixme - is this needed for recent versions of GCC? Or can we just use the macros +// above instead for both definitions (implementations) and declarations (includes)? -- air + +#define PCSX2_ALIGNED_EXTERN(alig,x) extern x +#define PCSX2_ALIGNED16_EXTERN(x) extern x + +#endif // _MSC_VER + +#if !defined(__LINUX__) || !defined(HAVE_STDINT_H) +#if defined(__x86_64__) +typedef u64 uptr; +typedef s64 sptr; +#else +typedef u32 uptr; +typedef s32 sptr; +#endif +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// A rough-and-ready cross platform 128-bit datatype, Non-SSE style. +#ifdef __cplusplus +struct u128 +{ + u64 lo; + u64 hi; + + // Implicit conversion from u64 + u128( u64 src ) : + lo( src ) + , hi( 0 ) {} + + // Implicit conversion from u32 + u128( u32 src ) : + lo( src ) + , hi( 0 ) {} +}; + +struct s128 +{ + s64 lo; + s64 hi; + + // Implicit conversion from u64 + s128( s64 src ) : + lo( src ) + , hi( 0 ) {} + + // Implicit conversion from u32 + s128( s32 src ) : + lo( src ) + , hi( 0 ) {} +}; + +#else + +typedef union _u128_t +{ + u64 lo; + u64 hi; +} u128; + +typedef union _s128_t +{ + s64 lo; + s64 hi; +} s128; + +#endif + +typedef struct { + int size; + s8 *data; +} freezeData; + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct _keyEvent { + u32 key; + u32 evt; +} keyEvent; + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/zzogl-pg/opengl/compile b/plugins/zzogl-pg/opengl/compile new file mode 120000 index 0000000000..cf0edba287 --- /dev/null +++ b/plugins/zzogl-pg/opengl/compile @@ -0,0 +1 @@ +/usr/share/automake-1.11/compile \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/configure.ac b/plugins/zzogl-pg/opengl/configure.ac new file mode 100644 index 0000000000..8aaafdcca5 --- /dev/null +++ b/plugins/zzogl-pg/opengl/configure.ac @@ -0,0 +1,151 @@ +AC_INIT(ZZOgl-pg,0.1.0,arcum42@gmail.com) + +AM_INIT_AUTOMAKE(ZZOgl-pg,0.1.0) + +AC_PROG_CC([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CXX([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CPP([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AM_PROG_CC_C_O + +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl necessary for compiling assembly +AM_PROG_AS + +ZEROGS_CURRENT=0 +ZEROGS_REVISION=1 +ZEROGS_AGE=0 +ZEROGS_SONAME=libzzoglpg.so.[$ZEROGS_CURRENT].[$ZEROGS_REVISION].[$ZEROGS_AGE] +ZEROGS_RELEASE=[$ZEROGS_CURRENT].[$ZEROGS_REVISION].[$ZEROGS_AGE] + +AC_SUBST(ZEROGS_CURRENT) +AC_SUBST(ZEROGS_REVISION) +AC_SUBST(ZEROGS_AGE) +AC_SUBST(ZEROGS_RELEASE) +AC_SUBST(ZEROGS_SONAME) + +CFLAGS=" -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused " +CPPFLAGS=" -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused " +CXXFLAGS=" -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused " + +dnl Check for debug build +AC_MSG_CHECKING(debug build) +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [debug build]), + debug=$enableval,debug=no) +if test "x$debug" == xyes +then + AC_DEFINE(_DEBUG,1,[_DEBUG]) + CFLAGS+="-g " + CPPFLAGS+="-g " + CXXFLAGS+="-g -fpermissive " +else + AC_DEFINE(NDEBUG,1,[NDEBUG]) + CFLAGS+="-O2 -msse2 " + CPPFLAGS+="-O2 -msse2 " + CXXFLAGS+="-O2 -msse2 -fno-regmove " +fi +AC_MSG_RESULT($debug) + +AC_CHECK_FUNCS([ _aligned_malloc _aligned_free ], AC_DEFINE(HAVE_ALIGNED_MALLOC)) + +dnl Check for dev build +AC_MSG_CHECKING(for development build...) +AC_ARG_ENABLE(devbuild, AC_HELP_STRING([--enable-devbuild], [Special Build for developers that simplifies testing and adds extra checks]), + devbuild=$enableval,devbuild=no) +if test "x$devbuild" == xno +then + AC_DEFINE(RELEASE_TO_PUBLIC,1,[RELEASE_TO_PUBLIC]) +fi +AC_MSG_RESULT($devbuild) +AM_CONDITIONAL(RELEASE_TO_PUBLIC, test x$devbuild = xno) + +dnl Check for recompilation +AC_MSG_CHECKING(check for sse2...) +AC_ARG_ENABLE(sse2, AC_HELP_STRING([--enable-sse2], [Enable sse2 instructions]), + sse2=$enableval,sse2=no) +if test "x$sse2" == xyes +then + AC_DEFINE(ZEROGS_SSE2,1,[ZEROGS_SSE2]) +fi +AC_MSG_RESULT($sse2) +AM_CONDITIONAL(SSE2, test x$sse2 = xyes) + +dnl Check for 64bit CPU +AC_MSG_CHECKING(for a x86-64 CPU) +dnl if test "$build_os" == "target_os" +dnl then +AC_TRY_RUN([ +int main() +{ +int a = 0; +int*pa = &a; +asm(".intel_syntax\n" + "mov %%rax, %0\n" + "mov %%eax, [%%rax]\n" + ".att_syntax\n" + : : "r"(pa) : "%rax"); +return 0; +} +],cpu64=yes,cpu64=no,) +dnl else +dnl cpu64=no +dnl fi +if test "x$cpu64" == xyes +then +AC_DEFINE(__x86_64__,1,[__x86_64__]) +fi +AC_MSG_RESULT($cpu64) +AM_CONDITIONAL(X86_64, test x$cpu64 = xyes) + +dnl gtk +AC_MSG_CHECKING(gtk2+) +AC_CHECK_PROG(GTK_CONFIG, pkg-config, pkg-config) +LIBS+=$(pkg-config --libs gtk+-2.0) + +dnl bindir = pcsx2exe + +dnl assuming linux environment +so_ext=".so.$ZEROGS_RELEASE" +SHARED_LDFLAGS="-shared" +AC_SUBST(so_ext) +AC_SUBST(SHARED_LDFLAGS) + +AC_MSG_CHECKING(OpenGL) +AC_CHECK_HEADERS([GL/gl.h GL/glu.h GL/glext.h],,, + [[#if HAVE_GL_GL_H + #include + #endif + #if HAVE_GL_GLU_H + #include + #endif + ]]) +AC_CHECK_LIB(GL,main,[LIBS="$LIBS -lGL"]) +AC_CHECK_LIB(GLU,main,[LIBS="$LIBS -lGLU"]) +AC_CHECK_LIB(GLEW,main,[LIBS="$LIBS -lGLEW"]) +AC_MSG_CHECKING(Cg) +AC_CHECK_HEADERS([Cg/cg.h Cg/cgGL.h]) +AC_CHECK_LIB(jpeg,main,[LIBS="$LIBS -ljpeg"]) +AC_CHECK_HEADERS([jpeglib.h],,[AC_MSG_ERROR(Install libjpeg-dev)]) +AC_CHECK_LIB(pthread,main,[LIBS="$LIBS -lpthread"]) +AC_CHECK_LIB(stdc++,main,[LIBS="$LIBS -lstdc++"]) +AC_CHECK_LIB(z,main,[LIBS="$LIBS -lz"]) +AC_CHECK_LIB(dl,main,[LIBS="$LIBS -ldl"]) +AC_CHECK_LIB(Xxf86vm,main,[LIBS="$LIBS -lXxf86vm"],[echo "Error! You need to have libXxf86vm-dev." ; exit -1]) + +dnl AC_CHECK_LIB(Cg,cgCreateContext,[LIBS="$LIBS -lCg"]) +dnl AC_CHECK_LIB(CgGL,cgGLEnableProfile,[LIBS="$LIBS -lCgGL"]) +LIBS+=" -lCg -lCgGL" + +AC_OUTPUT([ + Makefile + Linux/Makefile + ZeroGSShaders/Makefile + ]) + +echo "Configuration:" +echo " Target system type: $target" +echo " x86-64 build? $cpu64" +echo " Debug build? $debug" +echo " Dev build? $devbuild" +echo " SSE2 enabled? $sse2" diff --git a/plugins/zzogl-pg/opengl/ctx0/ps2hw_ctx.fx b/plugins/zzogl-pg/opengl/ctx0/ps2hw_ctx.fx new file mode 100644 index 0000000000..7988a22bb7 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ctx0/ps2hw_ctx.fx @@ -0,0 +1,24 @@ +// main ps2 memory, each pixel is stored in 32bit color +uniform samplerRECT g_sMemory : register(s0); + +// per context pixel shader constants +uniform half4 fTexAlpha2 : register(c2); + +uniform float4 g_fTexOffset : register(c4); // converts the page and block offsets into the mem addr/1024 +uniform float4 g_fTexDims : register(c6); // mult by tex dims when accessing the block texture +uniform float4 g_fTexBlock : register(c8); + +uniform float4 g_fClampExts : register(c10); // if clamping the texture, use (minu, minv, maxu, maxv) +uniform float4 TexWrapMode : register(c12); // 0 - repeat/clamp, 1 - region rep (use fRegRepMask) + +uniform float4 g_fRealTexDims : register(c14); // tex dims used for linear filtering (w,h,1/w,1/h) + +// (alpha0, alpha1, 1 if highlight2 and tcc is rgba, 1-y) +uniform half4 g_fTestBlack : register(c16); // used for aem bit + +uniform float4 g_fPageOffset : register(c18); + +uniform half4 fTexAlpha : register(c20); + +// vertex shader constants +uniform float4 g_fPosXY : register(c2); \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/ctx1/ps2hw_ctx.fx b/plugins/zzogl-pg/opengl/ctx1/ps2hw_ctx.fx new file mode 100644 index 0000000000..c6332c1a59 --- /dev/null +++ b/plugins/zzogl-pg/opengl/ctx1/ps2hw_ctx.fx @@ -0,0 +1,23 @@ +uniform samplerRECT g_sMemory : register(s1); + +// per context pixel shader constants +uniform half4 fTexAlpha2 : register(c3); + +uniform float4 g_fTexOffset : register(c5); // converts the page and block offsets into the mem addr/1024 +uniform float4 g_fTexDims : register(c7); // mult by tex dims when accessing the block texture +uniform float4 g_fTexBlock : register(c9); + +uniform float4 g_fClampExts : register(c11); // if clamping the texture, use (minu, minv, maxu, maxv) +uniform float4 TexWrapMode : register(c13); // 0 - repeat/clamp, 1 - region rep (use fRegRepMask) + +uniform float4 g_fRealTexDims : register(c15); // tex dims used for linear filtering (w,h,1/w,1/h) + +// (alpha0, alpha1, 1 if highlight2 and tcc is rgba, 1-y) +uniform half4 g_fTestBlack : register(c17); // used for aem bit + +uniform float4 g_fPageOffset : register(c19); + +uniform half4 fTexAlpha : register(c21); + +// vertex shader constants +uniform float4 g_fPosXY : register(c3); \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/depcomp b/plugins/zzogl-pg/opengl/depcomp new file mode 120000 index 0000000000..b0ad20c05e --- /dev/null +++ b/plugins/zzogl-pg/opengl/depcomp @@ -0,0 +1 @@ +/usr/share/automake-1.11/depcomp \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/glprocs.c b/plugins/zzogl-pg/opengl/glprocs.c new file mode 100644 index 0000000000..f7e3af4efa --- /dev/null +++ b/plugins/zzogl-pg/opengl/glprocs.c @@ -0,0 +1,17864 @@ +/* +** GLprocs utility for getting function addresses for OpenGL(R) 1.2, +** OpenGL 1.3, OpenGL 1.4, OpenGL 1.5 and OpenGL extension functions. +** +** Version: 1.1 +** +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +** +** Initial version of glprocs.{c,h} contributed by Intel(R) Corporation. +*/ + +#include +#include + +#ifdef _WIN32 + #include + #include //"gl.h" /* Include local "gl.h". Don't include vc32 . */ + #include "glprocs.h" +#else /* GLX */ + #include + #include + #include +#include "glprocs.h"// +// #define wglGetProcAddress glXGetProcAddress +inline void* wglGetProcAddress(const char* x) { + return (void*)glXGetProcAddress((const GLubyte*)x); +} + +#endif + +#define _ASSERT(a) assert(a) + +static void APIENTRY InitBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendColor"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendColor = extproc; + + glBlendColor(red, green, blue, alpha); +} + +static void APIENTRY InitBlendEquation (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendEquation"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendEquation = extproc; + + glBlendEquation(mode); +} + +static void APIENTRY InitDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElements"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElements = extproc; + + glDrawRangeElements(mode, start, end, count, type, indices); +} + +static void APIENTRY InitColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTable = extproc; + + glColorTable(target, internalformat, width, format, type, table); +} + +static void APIENTRY InitColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameterfv = extproc; + + glColorTableParameterfv(target, pname, params); +} + +static void APIENTRY InitColorTableParameteriv (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameteriv = extproc; + + glColorTableParameteriv(target, pname, params); +} + +static void APIENTRY InitCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorTable = extproc; + + glCopyColorTable(target, internalformat, x, y, width); +} + +static void APIENTRY InitGetColorTable (GLenum target, GLenum format, GLenum type, GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTable = extproc; + + glGetColorTable(target, format, type, table); +} + +static void APIENTRY InitGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterfv = extproc; + + glGetColorTableParameterfv(target, pname, params); +} + +static void APIENTRY InitGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameteriv = extproc; + + glGetColorTableParameteriv(target, pname, params); +} + +static void APIENTRY InitColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorSubTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorSubTable = extproc; + + glColorSubTable(target, start, count, format, type, data); +} + +static void APIENTRY InitCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorSubTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorSubTable = extproc; + + glCopyColorSubTable(target, start, x, y, width); +} + +static void APIENTRY InitConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter1D = extproc; + + glConvolutionFilter1D(target, internalformat, width, format, type, image); +} + +static void APIENTRY InitConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter2D = extproc; + + glConvolutionFilter2D(target, internalformat, width, height, format, type, image); +} + +static void APIENTRY InitConvolutionParameterf (GLenum target, GLenum pname, GLfloat params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterf = extproc; + + glConvolutionParameterf(target, pname, params); +} + +static void APIENTRY InitConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterfv = extproc; + + glConvolutionParameterfv(target, pname, params); +} + +static void APIENTRY InitConvolutionParameteri (GLenum target, GLenum pname, GLint params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameteri"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameteri = extproc; + + glConvolutionParameteri(target, pname, params); +} + +static void APIENTRY InitConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameteriv = extproc; + + glConvolutionParameteriv(target, pname, params); +} + +static void APIENTRY InitCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter1D = extproc; + + glCopyConvolutionFilter1D(target, internalformat, x, y, width); +} + +static void APIENTRY InitCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter2D = extproc; + + glCopyConvolutionFilter2D(target, internalformat, x, y, width, height); +} + +static void APIENTRY InitGetConvolutionFilter (GLenum target, GLenum format, GLenum type, GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionFilter"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionFilter = extproc; + + glGetConvolutionFilter(target, format, type, image); +} + +static void APIENTRY InitGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameterfv = extproc; + + glGetConvolutionParameterfv(target, pname, params); +} + +static void APIENTRY InitGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameteriv = extproc; + + glGetConvolutionParameteriv(target, pname, params); +} + +static void APIENTRY InitGetSeparableFilter (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetSeparableFilter"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetSeparableFilter = extproc; + + glGetSeparableFilter(target, format, type, row, column, span); +} + +static void APIENTRY InitSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSeparableFilter2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSeparableFilter2D = extproc; + + glSeparableFilter2D(target, internalformat, width, height, format, type, row, column); +} + +static void APIENTRY InitGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogram"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogram = extproc; + + glGetHistogram(target, reset, format, type, values); +} + +static void APIENTRY InitGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameterfv = extproc; + + glGetHistogramParameterfv(target, pname, params); +} + +static void APIENTRY InitGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameteriv = extproc; + + glGetHistogramParameteriv(target, pname, params); +} + +static void APIENTRY InitGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmax"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmax = extproc; + + glGetMinmax(target, reset, format, type, values); +} + +static void APIENTRY InitGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameterfv = extproc; + + glGetMinmaxParameterfv(target, pname, params); +} + +static void APIENTRY InitGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameteriv = extproc; + + glGetMinmaxParameteriv(target, pname, params); +} + +static void APIENTRY InitHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glHistogram"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glHistogram = extproc; + + glHistogram(target, width, internalformat, sink); +} + +static void APIENTRY InitMinmax (GLenum target, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMinmax"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMinmax = extproc; + + glMinmax(target, internalformat, sink); +} + +static void APIENTRY InitResetHistogram (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetHistogram"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetHistogram = extproc; + + glResetHistogram(target); +} + +static void APIENTRY InitResetMinmax (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetMinmax"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetMinmax = extproc; + + glResetMinmax(target); +} + +static void APIENTRY InitTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexImage3D = extproc; + + glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); +} + +static void APIENTRY InitTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage3D = extproc; + + glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); +} + +static void APIENTRY InitCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage3D = extproc; + + glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); +} + +static void APIENTRY InitActiveTexture (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glActiveTexture"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glActiveTexture = extproc; + + glActiveTexture(texture); +} + +static void APIENTRY InitClientActiveTexture (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glClientActiveTexture"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glClientActiveTexture = extproc; + + glClientActiveTexture(texture); +} + +static void APIENTRY InitMultiTexCoord1d (GLenum target, GLdouble s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1d = extproc; + + glMultiTexCoord1d(target, s); +} + +static void APIENTRY InitMultiTexCoord1dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1dv = extproc; + + glMultiTexCoord1dv(target, v); +} + +static void APIENTRY InitMultiTexCoord1f (GLenum target, GLfloat s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1f = extproc; + + glMultiTexCoord1f(target, s); +} + +static void APIENTRY InitMultiTexCoord1fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1fv = extproc; + + glMultiTexCoord1fv(target, v); +} + +static void APIENTRY InitMultiTexCoord1i (GLenum target, GLint s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1i = extproc; + + glMultiTexCoord1i(target, s); +} + +static void APIENTRY InitMultiTexCoord1iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1iv = extproc; + + glMultiTexCoord1iv(target, v); +} + +static void APIENTRY InitMultiTexCoord1s (GLenum target, GLshort s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1s = extproc; + + glMultiTexCoord1s(target, s); +} + +static void APIENTRY InitMultiTexCoord1sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1sv = extproc; + + glMultiTexCoord1sv(target, v); +} + +static void APIENTRY InitMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2d = extproc; + + glMultiTexCoord2d(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2dv = extproc; + + glMultiTexCoord2dv(target, v); +} + +static void APIENTRY InitMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2f = extproc; + + glMultiTexCoord2f(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2fv = extproc; + + glMultiTexCoord2fv(target, v); +} + +static void APIENTRY InitMultiTexCoord2i (GLenum target, GLint s, GLint t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2i = extproc; + + glMultiTexCoord2i(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2iv = extproc; + + glMultiTexCoord2iv(target, v); +} + +static void APIENTRY InitMultiTexCoord2s (GLenum target, GLshort s, GLshort t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2s = extproc; + + glMultiTexCoord2s(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2sv = extproc; + + glMultiTexCoord2sv(target, v); +} + +static void APIENTRY InitMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3d = extproc; + + glMultiTexCoord3d(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3dv = extproc; + + glMultiTexCoord3dv(target, v); +} + +static void APIENTRY InitMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3f = extproc; + + glMultiTexCoord3f(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3fv = extproc; + + glMultiTexCoord3fv(target, v); +} + +static void APIENTRY InitMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3i = extproc; + + glMultiTexCoord3i(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3iv = extproc; + + glMultiTexCoord3iv(target, v); +} + +static void APIENTRY InitMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3s = extproc; + + glMultiTexCoord3s(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3sv = extproc; + + glMultiTexCoord3sv(target, v); +} + +static void APIENTRY InitMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4d = extproc; + + glMultiTexCoord4d(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4dv = extproc; + + glMultiTexCoord4dv(target, v); +} + +static void APIENTRY InitMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4f = extproc; + + glMultiTexCoord4f(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4fv = extproc; + + glMultiTexCoord4fv(target, v); +} + +static void APIENTRY InitMultiTexCoord4i (GLenum target, GLint s, GLint t, GLint r, GLint q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4i = extproc; + + glMultiTexCoord4i(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4iv = extproc; + + glMultiTexCoord4iv(target, v); +} + +static void APIENTRY InitMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4s = extproc; + + glMultiTexCoord4s(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4sv = extproc; + + glMultiTexCoord4sv(target, v); +} + +static void APIENTRY InitLoadTransposeMatrixf (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixf = extproc; + + glLoadTransposeMatrixf(m); +} + +static void APIENTRY InitLoadTransposeMatrixd (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixd"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixd = extproc; + + glLoadTransposeMatrixd(m); +} + +static void APIENTRY InitMultTransposeMatrixf (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixf = extproc; + + glMultTransposeMatrixf(m); +} + +static void APIENTRY InitMultTransposeMatrixd (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixd"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixd = extproc; + + glMultTransposeMatrixd(m); +} + +static void APIENTRY InitSampleCoverage (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleCoverage"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleCoverage = extproc; + + glSampleCoverage(value, invert); +} + +static void APIENTRY InitCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage3D = extproc; + + glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage2D = extproc; + + glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage1D = extproc; + + glCompressedTexImage1D(target, level, internalformat, width, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage3D = extproc; + + glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage2D = extproc; + + glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage1D = extproc; + + glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data); +} + +static void APIENTRY InitGetCompressedTexImage (GLenum target, GLint level, GLvoid *img) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCompressedTexImage"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCompressedTexImage = extproc; + + glGetCompressedTexImage(target, level, img); +} + +static void APIENTRY InitBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendFuncSeparate"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendFuncSeparate = extproc; + + glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void APIENTRY InitFogCoordf (GLfloat coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordf = extproc; + + glFogCoordf(coord); +} + +static void APIENTRY InitFogCoordfv (const GLfloat *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordfv = extproc; + + glFogCoordfv(coord); +} + +static void APIENTRY InitFogCoordd (GLdouble coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordd"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordd = extproc; + + glFogCoordd(coord); +} + +static void APIENTRY InitFogCoorddv (const GLdouble *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoorddv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoorddv = extproc; + + glFogCoorddv(coord); +} + +static void APIENTRY InitFogCoordPointer (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordPointer"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordPointer = extproc; + + glFogCoordPointer(type, stride, pointer); +} + +static void APIENTRY InitMultiDrawArrays (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawArrays"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawArrays = extproc; + + glMultiDrawArrays(mode, first, count, primcount); +} + +static void APIENTRY InitMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawElements"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawElements = extproc; + + glMultiDrawElements(mode, count, type, indices, primcount); +} + +static void APIENTRY InitPointParameterf (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterf = extproc; + + glPointParameterf(pname, param); +} + +static void APIENTRY InitPointParameterfv (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfv = extproc; + + glPointParameterfv(pname, params); +} + +static void APIENTRY InitPointParameteri (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameteri"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameteri = extproc; + + glPointParameteri(pname, param); +} + +static void APIENTRY InitPointParameteriv (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameteriv = extproc; + + glPointParameteriv(pname, params); +} + +static void APIENTRY InitSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3b"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3b = extproc; + + glSecondaryColor3b(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3bv (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3bv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3bv = extproc; + + glSecondaryColor3bv(v); +} + +static void APIENTRY InitSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3d = extproc; + + glSecondaryColor3d(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3dv (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3dv = extproc; + + glSecondaryColor3dv(v); +} + +static void APIENTRY InitSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3f = extproc; + + glSecondaryColor3f(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3fv (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3fv = extproc; + + glSecondaryColor3fv(v); +} + +static void APIENTRY InitSecondaryColor3i (GLint red, GLint green, GLint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3i = extproc; + + glSecondaryColor3i(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3iv (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3iv = extproc; + + glSecondaryColor3iv(v); +} + +static void APIENTRY InitSecondaryColor3s (GLshort red, GLshort green, GLshort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3s = extproc; + + glSecondaryColor3s(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3sv (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3sv = extproc; + + glSecondaryColor3sv(v); +} + +static void APIENTRY InitSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ub"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ub = extproc; + + glSecondaryColor3ub(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3ubv (const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ubv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ubv = extproc; + + glSecondaryColor3ubv(v); +} + +static void APIENTRY InitSecondaryColor3ui (GLuint red, GLuint green, GLuint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ui"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ui = extproc; + + glSecondaryColor3ui(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3uiv (const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3uiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3uiv = extproc; + + glSecondaryColor3uiv(v); +} + +static void APIENTRY InitSecondaryColor3us (GLushort red, GLushort green, GLushort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3us"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3us = extproc; + + glSecondaryColor3us(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3usv (const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3usv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3usv = extproc; + + glSecondaryColor3usv(v); +} + +static void APIENTRY InitSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColorPointer"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColorPointer = extproc; + + glSecondaryColorPointer(size, type, stride, pointer); +} + +static void APIENTRY InitWindowPos2d (GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2d = extproc; + + glWindowPos2d(x, y); +} + +static void APIENTRY InitWindowPos2dv (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dv = extproc; + + glWindowPos2dv(v); +} + +static void APIENTRY InitWindowPos2f (GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2f = extproc; + + glWindowPos2f(x, y); +} + +static void APIENTRY InitWindowPos2fv (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fv = extproc; + + glWindowPos2fv(v); +} + +static void APIENTRY InitWindowPos2i (GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2i = extproc; + + glWindowPos2i(x, y); +} + +static void APIENTRY InitWindowPos2iv (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2iv = extproc; + + glWindowPos2iv(v); +} + +static void APIENTRY InitWindowPos2s (GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2s = extproc; + + glWindowPos2s(x, y); +} + +static void APIENTRY InitWindowPos2sv (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2sv = extproc; + + glWindowPos2sv(v); +} + +static void APIENTRY InitWindowPos3d (GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3d = extproc; + + glWindowPos3d(x, y, z); +} + +static void APIENTRY InitWindowPos3dv (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dv = extproc; + + glWindowPos3dv(v); +} + +static void APIENTRY InitWindowPos3f (GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3f = extproc; + + glWindowPos3f(x, y, z); +} + +static void APIENTRY InitWindowPos3fv (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fv = extproc; + + glWindowPos3fv(v); +} + +static void APIENTRY InitWindowPos3i (GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3i = extproc; + + glWindowPos3i(x, y, z); +} + +static void APIENTRY InitWindowPos3iv (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3iv = extproc; + + glWindowPos3iv(v); +} + +static void APIENTRY InitWindowPos3s (GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3s = extproc; + + glWindowPos3s(x, y, z); +} + +static void APIENTRY InitWindowPos3sv (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3sv = extproc; + + glWindowPos3sv(v); +} + +static void APIENTRY InitGenQueries (GLsizei n, GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenQueries"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenQueries = extproc; + + glGenQueries(n, ids); +} + +static void APIENTRY InitDeleteQueries (GLsizei n, const GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteQueries"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteQueries = extproc; + + glDeleteQueries(n, ids); +} + +static GLboolean APIENTRY InitIsQuery (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsQuery"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsQuery = extproc; + + return glIsQuery(id); +} + +static void APIENTRY InitBeginQuery (GLenum target, GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginQuery"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginQuery = extproc; + + glBeginQuery(target, id); +} + +static void APIENTRY InitEndQuery (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndQuery"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndQuery = extproc; + + glEndQuery(target); +} + +static void APIENTRY InitGetQueryiv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryiv = extproc; + + glGetQueryiv(target, pname, params); +} + +static void APIENTRY InitGetQueryObjectiv (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectiv = extproc; + + glGetQueryObjectiv(id, pname, params); +} + +static void APIENTRY InitGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectuiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectuiv = extproc; + + glGetQueryObjectuiv(id, pname, params); +} + +static void APIENTRY InitBindBuffer (GLenum target, GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindBuffer = extproc; + + glBindBuffer(target, buffer); +} + +static void APIENTRY InitDeleteBuffers (GLsizei n, const GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteBuffers"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteBuffers = extproc; + + glDeleteBuffers(n, buffers); +} + +static void APIENTRY InitGenBuffers (GLsizei n, GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenBuffers"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenBuffers = extproc; + + glGenBuffers(n, buffers); +} + +static GLboolean APIENTRY InitIsBuffer (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsBuffer = extproc; + + return glIsBuffer(buffer); +} + +static void APIENTRY InitBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferData"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferData = extproc; + + glBufferData(target, size, data, usage); +} + +static void APIENTRY InitBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferSubData"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferSubData = extproc; + + glBufferSubData(target, offset, size, data); +} + +static void APIENTRY InitGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferSubData"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferSubData = extproc; + + glGetBufferSubData(target, offset, size, data); +} + +static GLvoid* APIENTRY InitMapBuffer (GLenum target, GLenum access) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glMapBuffer = extproc; + + return glMapBuffer(target, access); +} + +static GLboolean APIENTRY InitUnmapBuffer (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnmapBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glUnmapBuffer = extproc; + + return glUnmapBuffer(target); +} + +static void APIENTRY InitGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferParameteriv = extproc; + + glGetBufferParameteriv(target, pname, params); +} + +static void APIENTRY InitGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferPointerv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferPointerv = extproc; + + glGetBufferPointerv(target, pname, params); +} + +static void APIENTRY InitActiveTextureARB (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glActiveTextureARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glActiveTextureARB = extproc; + + glActiveTextureARB(texture); +} + +static void APIENTRY InitClientActiveTextureARB (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glClientActiveTextureARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glClientActiveTextureARB = extproc; + + glClientActiveTextureARB(texture); +} + +static void APIENTRY InitMultiTexCoord1dARB (GLenum target, GLdouble s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1dARB = extproc; + + glMultiTexCoord1dARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1dvARB = extproc; + + glMultiTexCoord1dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord1fARB (GLenum target, GLfloat s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1fARB = extproc; + + glMultiTexCoord1fARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1fvARB = extproc; + + glMultiTexCoord1fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord1iARB (GLenum target, GLint s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1iARB = extproc; + + glMultiTexCoord1iARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1ivARB = extproc; + + glMultiTexCoord1ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord1sARB (GLenum target, GLshort s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1sARB = extproc; + + glMultiTexCoord1sARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1svARB = extproc; + + glMultiTexCoord1svARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2dARB (GLenum target, GLdouble s, GLdouble t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2dARB = extproc; + + glMultiTexCoord2dARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2dvARB = extproc; + + glMultiTexCoord2dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2fARB (GLenum target, GLfloat s, GLfloat t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2fARB = extproc; + + glMultiTexCoord2fARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2fvARB = extproc; + + glMultiTexCoord2fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2iARB (GLenum target, GLint s, GLint t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2iARB = extproc; + + glMultiTexCoord2iARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2ivARB = extproc; + + glMultiTexCoord2ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2sARB (GLenum target, GLshort s, GLshort t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2sARB = extproc; + + glMultiTexCoord2sARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2svARB = extproc; + + glMultiTexCoord2svARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3dARB = extproc; + + glMultiTexCoord3dARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3dvARB = extproc; + + glMultiTexCoord3dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3fARB = extproc; + + glMultiTexCoord3fARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3fvARB = extproc; + + glMultiTexCoord3fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3iARB (GLenum target, GLint s, GLint t, GLint r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3iARB = extproc; + + glMultiTexCoord3iARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3ivARB = extproc; + + glMultiTexCoord3ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3sARB (GLenum target, GLshort s, GLshort t, GLshort r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3sARB = extproc; + + glMultiTexCoord3sARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3svARB = extproc; + + glMultiTexCoord3svARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4dARB = extproc; + + glMultiTexCoord4dARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4dvARB = extproc; + + glMultiTexCoord4dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4fARB = extproc; + + glMultiTexCoord4fARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4fvARB = extproc; + + glMultiTexCoord4fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4iARB (GLenum target, GLint s, GLint t, GLint r, GLint q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4iARB = extproc; + + glMultiTexCoord4iARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4ivARB = extproc; + + glMultiTexCoord4ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4sARB (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4sARB = extproc; + + glMultiTexCoord4sARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4svARB = extproc; + + glMultiTexCoord4svARB(target, v); +} + +static void APIENTRY InitLoadTransposeMatrixfARB (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixfARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixfARB = extproc; + + glLoadTransposeMatrixfARB(m); +} + +static void APIENTRY InitLoadTransposeMatrixdARB (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixdARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixdARB = extproc; + + glLoadTransposeMatrixdARB(m); +} + +static void APIENTRY InitMultTransposeMatrixfARB (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixfARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixfARB = extproc; + + glMultTransposeMatrixfARB(m); +} + +static void APIENTRY InitMultTransposeMatrixdARB (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixdARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixdARB = extproc; + + glMultTransposeMatrixdARB(m); +} + +static void APIENTRY InitSampleCoverageARB (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleCoverageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleCoverageARB = extproc; + + glSampleCoverageARB(value, invert); +} + +static void APIENTRY InitCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage3DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage3DARB = extproc; + + glCompressedTexImage3DARB(target, level, internalformat, width, height, depth, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage2DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage2DARB = extproc; + + glCompressedTexImage2DARB(target, level, internalformat, width, height, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage1DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage1DARB = extproc; + + glCompressedTexImage1DARB(target, level, internalformat, width, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage3DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage3DARB = extproc; + + glCompressedTexSubImage3DARB(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage2DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage2DARB = extproc; + + glCompressedTexSubImage2DARB(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage1DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage1DARB = extproc; + + glCompressedTexSubImage1DARB(target, level, xoffset, width, format, imageSize, data); +} + +static void APIENTRY InitGetCompressedTexImageARB (GLenum target, GLint level, GLvoid *img) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCompressedTexImageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCompressedTexImageARB = extproc; + + glGetCompressedTexImageARB(target, level, img); +} + +static void APIENTRY InitPointParameterfARB (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfARB = extproc; + + glPointParameterfARB(pname, param); +} + +static void APIENTRY InitPointParameterfvARB (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfvARB = extproc; + + glPointParameterfvARB(pname, params); +} + +static void APIENTRY InitWeightbvARB (GLint size, const GLbyte *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightbvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightbvARB = extproc; + + glWeightbvARB(size, weights); +} + +static void APIENTRY InitWeightsvARB (GLint size, const GLshort *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightsvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightsvARB = extproc; + + glWeightsvARB(size, weights); +} + +static void APIENTRY InitWeightivARB (GLint size, const GLint *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightivARB = extproc; + + glWeightivARB(size, weights); +} + +static void APIENTRY InitWeightfvARB (GLint size, const GLfloat *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightfvARB = extproc; + + glWeightfvARB(size, weights); +} + +static void APIENTRY InitWeightdvARB (GLint size, const GLdouble *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightdvARB = extproc; + + glWeightdvARB(size, weights); +} + +static void APIENTRY InitWeightubvARB (GLint size, const GLubyte *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightubvARB = extproc; + + glWeightubvARB(size, weights); +} + +static void APIENTRY InitWeightusvARB (GLint size, const GLushort *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightusvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightusvARB = extproc; + + glWeightusvARB(size, weights); +} + +static void APIENTRY InitWeightuivARB (GLint size, const GLuint *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightuivARB = extproc; + + glWeightuivARB(size, weights); +} + +static void APIENTRY InitWeightPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightPointerARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightPointerARB = extproc; + + glWeightPointerARB(size, type, stride, pointer); +} + +static void APIENTRY InitVertexBlendARB (GLint count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexBlendARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexBlendARB = extproc; + + glVertexBlendARB(count); +} + +static void APIENTRY InitCurrentPaletteMatrixARB (GLint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCurrentPaletteMatrixARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCurrentPaletteMatrixARB = extproc; + + glCurrentPaletteMatrixARB(index); +} + +static void APIENTRY InitMatrixIndexubvARB (GLint size, const GLubyte *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexubvARB = extproc; + + glMatrixIndexubvARB(size, indices); +} + +static void APIENTRY InitMatrixIndexusvARB (GLint size, const GLushort *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexusvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexusvARB = extproc; + + glMatrixIndexusvARB(size, indices); +} + +static void APIENTRY InitMatrixIndexuivARB (GLint size, const GLuint *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexuivARB = extproc; + + glMatrixIndexuivARB(size, indices); +} + +static void APIENTRY InitMatrixIndexPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexPointerARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexPointerARB = extproc; + + glMatrixIndexPointerARB(size, type, stride, pointer); +} + +static void APIENTRY InitWindowPos2dARB (GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dARB = extproc; + + glWindowPos2dARB(x, y); +} + +static void APIENTRY InitWindowPos2dvARB (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dvARB = extproc; + + glWindowPos2dvARB(v); +} + +static void APIENTRY InitWindowPos2fARB (GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fARB = extproc; + + glWindowPos2fARB(x, y); +} + +static void APIENTRY InitWindowPos2fvARB (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fvARB = extproc; + + glWindowPos2fvARB(v); +} + +static void APIENTRY InitWindowPos2iARB (GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2iARB = extproc; + + glWindowPos2iARB(x, y); +} + +static void APIENTRY InitWindowPos2ivARB (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2ivARB = extproc; + + glWindowPos2ivARB(v); +} + +static void APIENTRY InitWindowPos2sARB (GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2sARB = extproc; + + glWindowPos2sARB(x, y); +} + +static void APIENTRY InitWindowPos2svARB (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2svARB = extproc; + + glWindowPos2svARB(v); +} + +static void APIENTRY InitWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dARB = extproc; + + glWindowPos3dARB(x, y, z); +} + +static void APIENTRY InitWindowPos3dvARB (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dvARB = extproc; + + glWindowPos3dvARB(v); +} + +static void APIENTRY InitWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fARB = extproc; + + glWindowPos3fARB(x, y, z); +} + +static void APIENTRY InitWindowPos3fvARB (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fvARB = extproc; + + glWindowPos3fvARB(v); +} + +static void APIENTRY InitWindowPos3iARB (GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3iARB = extproc; + + glWindowPos3iARB(x, y, z); +} + +static void APIENTRY InitWindowPos3ivARB (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3ivARB = extproc; + + glWindowPos3ivARB(v); +} + +static void APIENTRY InitWindowPos3sARB (GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3sARB = extproc; + + glWindowPos3sARB(x, y, z); +} + +static void APIENTRY InitWindowPos3svARB (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3svARB = extproc; + + glWindowPos3svARB(v); +} + +static void APIENTRY InitVertexAttrib1dARB (GLuint index, GLdouble x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dARB = extproc; + + glVertexAttrib1dARB(index, x); +} + +static void APIENTRY InitVertexAttrib1dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dvARB = extproc; + + glVertexAttrib1dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib1fARB (GLuint index, GLfloat x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fARB = extproc; + + glVertexAttrib1fARB(index, x); +} + +static void APIENTRY InitVertexAttrib1fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fvARB = extproc; + + glVertexAttrib1fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib1sARB (GLuint index, GLshort x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1sARB = extproc; + + glVertexAttrib1sARB(index, x); +} + +static void APIENTRY InitVertexAttrib1svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1svARB = extproc; + + glVertexAttrib1svARB(index, v); +} + +static void APIENTRY InitVertexAttrib2dARB (GLuint index, GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dARB = extproc; + + glVertexAttrib2dARB(index, x, y); +} + +static void APIENTRY InitVertexAttrib2dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dvARB = extproc; + + glVertexAttrib2dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib2fARB (GLuint index, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fARB = extproc; + + glVertexAttrib2fARB(index, x, y); +} + +static void APIENTRY InitVertexAttrib2fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fvARB = extproc; + + glVertexAttrib2fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib2sARB (GLuint index, GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2sARB = extproc; + + glVertexAttrib2sARB(index, x, y); +} + +static void APIENTRY InitVertexAttrib2svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2svARB = extproc; + + glVertexAttrib2svARB(index, v); +} + +static void APIENTRY InitVertexAttrib3dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dARB = extproc; + + glVertexAttrib3dARB(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dvARB = extproc; + + glVertexAttrib3dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib3fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fARB = extproc; + + glVertexAttrib3fARB(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fvARB = extproc; + + glVertexAttrib3fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib3sARB (GLuint index, GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3sARB = extproc; + + glVertexAttrib3sARB(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3svARB = extproc; + + glVertexAttrib3svARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NbvARB (GLuint index, const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NbvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NbvARB = extproc; + + glVertexAttrib4NbvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NivARB (GLuint index, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NivARB = extproc; + + glVertexAttrib4NivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NsvARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NsvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NsvARB = extproc; + + glVertexAttrib4NsvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NubARB (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NubARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NubARB = extproc; + + glVertexAttrib4NubARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4NubvARB (GLuint index, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NubvARB = extproc; + + glVertexAttrib4NubvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NuivARB (GLuint index, const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NuivARB = extproc; + + glVertexAttrib4NuivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NusvARB (GLuint index, const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NusvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NusvARB = extproc; + + glVertexAttrib4NusvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4bvARB (GLuint index, const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4bvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4bvARB = extproc; + + glVertexAttrib4bvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dARB = extproc; + + glVertexAttrib4dARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dvARB = extproc; + + glVertexAttrib4dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fARB = extproc; + + glVertexAttrib4fARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fvARB = extproc; + + glVertexAttrib4fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4ivARB (GLuint index, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ivARB = extproc; + + glVertexAttrib4ivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4sARB (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4sARB = extproc; + + glVertexAttrib4sARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4svARB = extproc; + + glVertexAttrib4svARB(index, v); +} + +static void APIENTRY InitVertexAttrib4ubvARB (GLuint index, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ubvARB = extproc; + + glVertexAttrib4ubvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4uivARB (GLuint index, const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4uivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4uivARB = extproc; + + glVertexAttrib4uivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4usvARB (GLuint index, const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4usvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4usvARB = extproc; + + glVertexAttrib4usvARB(index, v); +} + +static void APIENTRY InitVertexAttribPointerARB (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribPointerARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribPointerARB = extproc; + + glVertexAttribPointerARB(index, size, type, normalized, stride, pointer); +} + +static void APIENTRY InitEnableVertexAttribArrayARB (GLuint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEnableVertexAttribArrayARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEnableVertexAttribArrayARB = extproc; + + glEnableVertexAttribArrayARB(index); +} + +static void APIENTRY InitDisableVertexAttribArrayARB (GLuint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDisableVertexAttribArrayARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDisableVertexAttribArrayARB = extproc; + + glDisableVertexAttribArrayARB(index); +} + +static void APIENTRY InitProgramStringARB (GLenum target, GLenum format, GLsizei len, const GLvoid *string) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramStringARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramStringARB = extproc; + + glProgramStringARB(target, format, len, string); +} + +static void APIENTRY InitBindProgramARB (GLenum target, GLuint program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindProgramARB = extproc; + + glBindProgramARB(target, program); +} + +static void APIENTRY InitDeleteProgramsARB (GLsizei n, const GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteProgramsARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteProgramsARB = extproc; + + glDeleteProgramsARB(n, programs); +} + +static void APIENTRY InitGenProgramsARB (GLsizei n, GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenProgramsARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenProgramsARB = extproc; + + glGenProgramsARB(n, programs); +} + +static void APIENTRY InitProgramEnvParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4dARB = extproc; + + glProgramEnvParameter4dARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramEnvParameter4dvARB (GLenum target, GLuint index, const GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4dvARB = extproc; + + glProgramEnvParameter4dvARB(target, index, params); +} + +static void APIENTRY InitProgramEnvParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4fARB = extproc; + + glProgramEnvParameter4fARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramEnvParameter4fvARB (GLenum target, GLuint index, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4fvARB = extproc; + + glProgramEnvParameter4fvARB(target, index, params); +} + +static void APIENTRY InitProgramLocalParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4dARB = extproc; + + glProgramLocalParameter4dARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramLocalParameter4dvARB (GLenum target, GLuint index, const GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4dvARB = extproc; + + glProgramLocalParameter4dvARB(target, index, params); +} + +static void APIENTRY InitProgramLocalParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4fARB = extproc; + + glProgramLocalParameter4fARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramLocalParameter4fvARB (GLenum target, GLuint index, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4fvARB = extproc; + + glProgramLocalParameter4fvARB(target, index, params); +} + +static void APIENTRY InitGetProgramEnvParameterdvARB (GLenum target, GLuint index, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramEnvParameterdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramEnvParameterdvARB = extproc; + + glGetProgramEnvParameterdvARB(target, index, params); +} + +static void APIENTRY InitGetProgramEnvParameterfvARB (GLenum target, GLuint index, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramEnvParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramEnvParameterfvARB = extproc; + + glGetProgramEnvParameterfvARB(target, index, params); +} + +static void APIENTRY InitGetProgramLocalParameterdvARB (GLenum target, GLuint index, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramLocalParameterdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramLocalParameterdvARB = extproc; + + glGetProgramLocalParameterdvARB(target, index, params); +} + +static void APIENTRY InitGetProgramLocalParameterfvARB (GLenum target, GLuint index, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramLocalParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramLocalParameterfvARB = extproc; + + glGetProgramLocalParameterfvARB(target, index, params); +} + +static void APIENTRY InitGetProgramivARB (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramivARB = extproc; + + glGetProgramivARB(target, pname, params); +} + +static void APIENTRY InitGetProgramStringARB (GLenum target, GLenum pname, GLvoid *string) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramStringARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramStringARB = extproc; + + glGetProgramStringARB(target, pname, string); +} + +static void APIENTRY InitGetVertexAttribdvARB (GLuint index, GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribdvARB = extproc; + + glGetVertexAttribdvARB(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribfvARB (GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribfvARB = extproc; + + glGetVertexAttribfvARB(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribivARB (GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribivARB = extproc; + + glGetVertexAttribivARB(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribPointervARB (GLuint index, GLenum pname, GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribPointervARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribPointervARB = extproc; + + glGetVertexAttribPointervARB(index, pname, pointer); +} + +static GLboolean APIENTRY InitIsProgramARB (GLuint program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsProgramARB = extproc; + + return glIsProgramARB(program); +} + +static void APIENTRY InitBindBufferARB (GLenum target, GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindBufferARB = extproc; + + glBindBufferARB(target, buffer); +} + +static void APIENTRY InitDeleteBuffersARB (GLsizei n, const GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteBuffersARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteBuffersARB = extproc; + + glDeleteBuffersARB(n, buffers); +} + +static void APIENTRY InitGenBuffersARB (GLsizei n, GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenBuffersARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenBuffersARB = extproc; + + glGenBuffersARB(n, buffers); +} + +static GLboolean APIENTRY InitIsBufferARB (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsBufferARB = extproc; + + return glIsBufferARB(buffer); +} + +static void APIENTRY InitBufferDataARB (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferDataARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferDataARB = extproc; + + glBufferDataARB(target, size, data, usage); +} + +static void APIENTRY InitBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferSubDataARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferSubDataARB = extproc; + + glBufferSubDataARB(target, offset, size, data); +} + +static void APIENTRY InitGetBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferSubDataARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferSubDataARB = extproc; + + glGetBufferSubDataARB(target, offset, size, data); +} + +static GLvoid* APIENTRY InitMapBufferARB (GLenum target, GLenum access) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glMapBufferARB = extproc; + + return glMapBufferARB(target, access); +} + +static GLboolean APIENTRY InitUnmapBufferARB (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnmapBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glUnmapBufferARB = extproc; + + return glUnmapBufferARB(target); +} + +static void APIENTRY InitGetBufferParameterivARB (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferParameterivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferParameterivARB = extproc; + + glGetBufferParameterivARB(target, pname, params); +} + +static void APIENTRY InitGetBufferPointervARB (GLenum target, GLenum pname, GLvoid* *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferPointervARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferPointervARB = extproc; + + glGetBufferPointervARB(target, pname, params); +} + +static void APIENTRY InitGenQueriesARB (GLsizei n, GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenQueriesARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenQueriesARB = extproc; + + glGenQueriesARB(n, ids); +} + +static void APIENTRY InitDeleteQueriesARB (GLsizei n, const GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteQueriesARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteQueriesARB = extproc; + + glDeleteQueriesARB(n, ids); +} + +static GLboolean APIENTRY InitIsQueryARB (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsQueryARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsQueryARB = extproc; + + return glIsQueryARB(id); +} + +static void APIENTRY InitBeginQueryARB (GLenum target, GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginQueryARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginQueryARB = extproc; + + glBeginQueryARB(target, id); +} + +static void APIENTRY InitEndQueryARB (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndQueryARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndQueryARB = extproc; + + glEndQueryARB(target); +} + +static void APIENTRY InitGetQueryivARB (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryivARB = extproc; + + glGetQueryivARB(target, pname, params); +} + +static void APIENTRY InitGetQueryObjectivARB (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectivARB = extproc; + + glGetQueryObjectivARB(id, pname, params); +} + +static void APIENTRY InitGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectuivARB = extproc; + + glGetQueryObjectuivARB(id, pname, params); +} + +static void APIENTRY InitDeleteObjectARB (GLhandleARB obj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteObjectARB = extproc; + + glDeleteObjectARB(obj); +} + +static GLhandleARB APIENTRY InitGetHandleARB (GLenum pname) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHandleARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetHandleARB = extproc; + + return glGetHandleARB(pname); +} + +static void APIENTRY InitDetachObjectARB (GLhandleARB containerObj, GLhandleARB attachedObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDetachObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDetachObjectARB = extproc; + + glDetachObjectARB(containerObj, attachedObj); +} + +static GLhandleARB APIENTRY InitCreateShaderObjectARB (GLenum shaderType) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCreateShaderObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glCreateShaderObjectARB = extproc; + + return glCreateShaderObjectARB(shaderType); +} + +static void APIENTRY InitShaderSourceARB (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderSourceARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderSourceARB = extproc; + + glShaderSourceARB(shaderObj, count, string, length); +} + +static void APIENTRY InitCompileShaderARB (GLhandleARB shaderObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompileShaderARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompileShaderARB = extproc; + + glCompileShaderARB(shaderObj); +} + +static GLhandleARB APIENTRY InitCreateProgramObjectARB (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCreateProgramObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glCreateProgramObjectARB = extproc; + + return glCreateProgramObjectARB(); +} + +static void APIENTRY InitAttachObjectARB (GLhandleARB containerObj, GLhandleARB obj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAttachObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAttachObjectARB = extproc; + + glAttachObjectARB(containerObj, obj); +} + +static void APIENTRY InitLinkProgramARB (GLhandleARB programObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLinkProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLinkProgramARB = extproc; + + glLinkProgramARB(programObj); +} + +static void APIENTRY InitUseProgramObjectARB (GLhandleARB programObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUseProgramObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUseProgramObjectARB = extproc; + + glUseProgramObjectARB(programObj); +} + +static void APIENTRY InitValidateProgramARB (GLhandleARB programObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glValidateProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glValidateProgramARB = extproc; + + glValidateProgramARB(programObj); +} + +static void APIENTRY InitUniform1fARB (GLint location, GLfloat v0) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1fARB = extproc; + + glUniform1fARB(location, v0); +} + +static void APIENTRY InitUniform2fARB (GLint location, GLfloat v0, GLfloat v1) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2fARB = extproc; + + glUniform2fARB(location, v0, v1); +} + +static void APIENTRY InitUniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3fARB = extproc; + + glUniform3fARB(location, v0, v1, v2); +} + +static void APIENTRY InitUniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4fARB = extproc; + + glUniform4fARB(location, v0, v1, v2, v3); +} + +static void APIENTRY InitUniform1iARB (GLint location, GLint v0) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1iARB = extproc; + + glUniform1iARB(location, v0); +} + +static void APIENTRY InitUniform2iARB (GLint location, GLint v0, GLint v1) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2iARB = extproc; + + glUniform2iARB(location, v0, v1); +} + +static void APIENTRY InitUniform3iARB (GLint location, GLint v0, GLint v1, GLint v2) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3iARB = extproc; + + glUniform3iARB(location, v0, v1, v2); +} + +static void APIENTRY InitUniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4iARB = extproc; + + glUniform4iARB(location, v0, v1, v2, v3); +} + +static void APIENTRY InitUniform1fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1fvARB = extproc; + + glUniform1fvARB(location, count, value); +} + +static void APIENTRY InitUniform2fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2fvARB = extproc; + + glUniform2fvARB(location, count, value); +} + +static void APIENTRY InitUniform3fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3fvARB = extproc; + + glUniform3fvARB(location, count, value); +} + +static void APIENTRY InitUniform4fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4fvARB = extproc; + + glUniform4fvARB(location, count, value); +} + +static void APIENTRY InitUniform1ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1ivARB = extproc; + + glUniform1ivARB(location, count, value); +} + +static void APIENTRY InitUniform2ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2ivARB = extproc; + + glUniform2ivARB(location, count, value); +} + +static void APIENTRY InitUniform3ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3ivARB = extproc; + + glUniform3ivARB(location, count, value); +} + +static void APIENTRY InitUniform4ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4ivARB = extproc; + + glUniform4ivARB(location, count, value); +} + +static void APIENTRY InitUniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniformMatrix2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniformMatrix2fvARB = extproc; + + glUniformMatrix2fvARB(location, count, transpose, value); +} + +static void APIENTRY InitUniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniformMatrix3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniformMatrix3fvARB = extproc; + + glUniformMatrix3fvARB(location, count, transpose, value); +} + +static void APIENTRY InitUniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniformMatrix4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniformMatrix4fvARB = extproc; + + glUniformMatrix4fvARB(location, count, transpose, value); +} + +static void APIENTRY InitGetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectParameterfvARB = extproc; + + glGetObjectParameterfvARB(obj, pname, params); +} + +static void APIENTRY InitGetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectParameterivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectParameterivARB = extproc; + + glGetObjectParameterivARB(obj, pname, params); +} + +static void APIENTRY InitGetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInfoLogARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInfoLogARB = extproc; + + glGetInfoLogARB(obj, maxLength, length, infoLog); +} + +static void APIENTRY InitGetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetAttachedObjectsARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetAttachedObjectsARB = extproc; + + glGetAttachedObjectsARB(containerObj, maxCount, count, obj); +} + +static GLint APIENTRY InitGetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetUniformLocationARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetUniformLocationARB = extproc; + + return glGetUniformLocationARB(programObj, name); +} + +static void APIENTRY InitGetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetActiveUniformARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetActiveUniformARB = extproc; + + glGetActiveUniformARB(programObj, index, maxLength, length, size, type, name); +} + +static void APIENTRY InitGetUniformfvARB (GLhandleARB programObj, GLint location, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetUniformfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetUniformfvARB = extproc; + + glGetUniformfvARB(programObj, location, params); +} + +static void APIENTRY InitGetUniformivARB (GLhandleARB programObj, GLint location, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetUniformivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetUniformivARB = extproc; + + glGetUniformivARB(programObj, location, params); +} + +static void APIENTRY InitGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetShaderSourceARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetShaderSourceARB = extproc; + + glGetShaderSourceARB(obj, maxLength, length, source); +} + +static void APIENTRY InitBindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindAttribLocationARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindAttribLocationARB = extproc; + + glBindAttribLocationARB(programObj, index, name); +} + +static void APIENTRY InitGetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetActiveAttribARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetActiveAttribARB = extproc; + + glGetActiveAttribARB(programObj, index, maxLength, length, size, type, name); +} + +static GLint APIENTRY InitGetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetAttribLocationARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetAttribLocationARB = extproc; + + return glGetAttribLocationARB(programObj, name); +} + +static void APIENTRY InitBlendColorEXT (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendColorEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendColorEXT = extproc; + + glBlendColorEXT(red, green, blue, alpha); +} + +static void APIENTRY InitPolygonOffsetEXT (GLfloat factor, GLfloat bias) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPolygonOffsetEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPolygonOffsetEXT = extproc; + + glPolygonOffsetEXT(factor, bias); +} + +static void APIENTRY InitTexImage3DEXT (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexImage3DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexImage3DEXT = extproc; + + glTexImage3DEXT(target, level, internalformat, width, height, depth, border, format, type, pixels); +} + +static void APIENTRY InitTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage3DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage3DEXT = extproc; + + glTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); +} + +static void APIENTRY InitGetTexFilterFuncSGIS (GLenum target, GLenum filter, GLfloat *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTexFilterFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTexFilterFuncSGIS = extproc; + + glGetTexFilterFuncSGIS(target, filter, weights); +} + +static void APIENTRY InitTexFilterFuncSGIS (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexFilterFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexFilterFuncSGIS = extproc; + + glTexFilterFuncSGIS(target, filter, n, weights); +} + +static void APIENTRY InitTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage1DEXT = extproc; + + glTexSubImage1DEXT(target, level, xoffset, width, format, type, pixels); +} + +static void APIENTRY InitTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage2DEXT = extproc; + + glTexSubImage2DEXT(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +static void APIENTRY InitCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexImage1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexImage1DEXT = extproc; + + glCopyTexImage1DEXT(target, level, internalformat, x, y, width, border); +} + +static void APIENTRY InitCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexImage2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexImage2DEXT = extproc; + + glCopyTexImage2DEXT(target, level, internalformat, x, y, width, height, border); +} + +static void APIENTRY InitCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage1DEXT = extproc; + + glCopyTexSubImage1DEXT(target, level, xoffset, x, y, width); +} + +static void APIENTRY InitCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage2DEXT = extproc; + + glCopyTexSubImage2DEXT(target, level, xoffset, yoffset, x, y, width, height); +} + +static void APIENTRY InitCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage3DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage3DEXT = extproc; + + glCopyTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, x, y, width, height); +} + +static void APIENTRY InitGetHistogramEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramEXT = extproc; + + glGetHistogramEXT(target, reset, format, type, values); +} + +static void APIENTRY InitGetHistogramParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameterfvEXT = extproc; + + glGetHistogramParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetHistogramParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameterivEXT = extproc; + + glGetHistogramParameterivEXT(target, pname, params); +} + +static void APIENTRY InitGetMinmaxEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxEXT = extproc; + + glGetMinmaxEXT(target, reset, format, type, values); +} + +static void APIENTRY InitGetMinmaxParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameterfvEXT = extproc; + + glGetMinmaxParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetMinmaxParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameterivEXT = extproc; + + glGetMinmaxParameterivEXT(target, pname, params); +} + +static void APIENTRY InitHistogramEXT (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glHistogramEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glHistogramEXT = extproc; + + glHistogramEXT(target, width, internalformat, sink); +} + +static void APIENTRY InitMinmaxEXT (GLenum target, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMinmaxEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMinmaxEXT = extproc; + + glMinmaxEXT(target, internalformat, sink); +} + +static void APIENTRY InitResetHistogramEXT (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetHistogramEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetHistogramEXT = extproc; + + glResetHistogramEXT(target); +} + +static void APIENTRY InitResetMinmaxEXT (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetMinmaxEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetMinmaxEXT = extproc; + + glResetMinmaxEXT(target); +} + +static void APIENTRY InitConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter1DEXT = extproc; + + glConvolutionFilter1DEXT(target, internalformat, width, format, type, image); +} + +static void APIENTRY InitConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter2DEXT = extproc; + + glConvolutionFilter2DEXT(target, internalformat, width, height, format, type, image); +} + +static void APIENTRY InitConvolutionParameterfEXT (GLenum target, GLenum pname, GLfloat params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterfEXT = extproc; + + glConvolutionParameterfEXT(target, pname, params); +} + +static void APIENTRY InitConvolutionParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterfvEXT = extproc; + + glConvolutionParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitConvolutionParameteriEXT (GLenum target, GLenum pname, GLint params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameteriEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameteriEXT = extproc; + + glConvolutionParameteriEXT(target, pname, params); +} + +static void APIENTRY InitConvolutionParameterivEXT (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterivEXT = extproc; + + glConvolutionParameterivEXT(target, pname, params); +} + +static void APIENTRY InitCopyConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter1DEXT = extproc; + + glCopyConvolutionFilter1DEXT(target, internalformat, x, y, width); +} + +static void APIENTRY InitCopyConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter2DEXT = extproc; + + glCopyConvolutionFilter2DEXT(target, internalformat, x, y, width, height); +} + +static void APIENTRY InitGetConvolutionFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionFilterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionFilterEXT = extproc; + + glGetConvolutionFilterEXT(target, format, type, image); +} + +static void APIENTRY InitGetConvolutionParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameterfvEXT = extproc; + + glGetConvolutionParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetConvolutionParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameterivEXT = extproc; + + glGetConvolutionParameterivEXT(target, pname, params); +} + +static void APIENTRY InitGetSeparableFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetSeparableFilterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetSeparableFilterEXT = extproc; + + glGetSeparableFilterEXT(target, format, type, row, column, span); +} + +static void APIENTRY InitSeparableFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSeparableFilter2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSeparableFilter2DEXT = extproc; + + glSeparableFilter2DEXT(target, internalformat, width, height, format, type, row, column); +} + +static void APIENTRY InitColorTableSGI (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableSGI = extproc; + + glColorTableSGI(target, internalformat, width, format, type, table); +} + +static void APIENTRY InitColorTableParameterfvSGI (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameterfvSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameterfvSGI = extproc; + + glColorTableParameterfvSGI(target, pname, params); +} + +static void APIENTRY InitColorTableParameterivSGI (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameterivSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameterivSGI = extproc; + + glColorTableParameterivSGI(target, pname, params); +} + +static void APIENTRY InitCopyColorTableSGI (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorTableSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorTableSGI = extproc; + + glCopyColorTableSGI(target, internalformat, x, y, width); +} + +static void APIENTRY InitGetColorTableSGI (GLenum target, GLenum format, GLenum type, GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableSGI = extproc; + + glGetColorTableSGI(target, format, type, table); +} + +static void APIENTRY InitGetColorTableParameterfvSGI (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterfvSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterfvSGI = extproc; + + glGetColorTableParameterfvSGI(target, pname, params); +} + +static void APIENTRY InitGetColorTableParameterivSGI (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterivSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterivSGI = extproc; + + glGetColorTableParameterivSGI(target, pname, params); +} + +static void APIENTRY InitPixelTexGenSGIX (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenSGIX = extproc; + + glPixelTexGenSGIX(mode); +} + +static void APIENTRY InitPixelTexGenParameteriSGIS (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameteriSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameteriSGIS = extproc; + + glPixelTexGenParameteriSGIS(pname, param); +} + +static void APIENTRY InitPixelTexGenParameterivSGIS (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameterivSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameterivSGIS = extproc; + + glPixelTexGenParameterivSGIS(pname, params); +} + +static void APIENTRY InitPixelTexGenParameterfSGIS (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameterfSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameterfSGIS = extproc; + + glPixelTexGenParameterfSGIS(pname, param); +} + +static void APIENTRY InitPixelTexGenParameterfvSGIS (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameterfvSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameterfvSGIS = extproc; + + glPixelTexGenParameterfvSGIS(pname, params); +} + +static void APIENTRY InitGetPixelTexGenParameterivSGIS (GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetPixelTexGenParameterivSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetPixelTexGenParameterivSGIS = extproc; + + glGetPixelTexGenParameterivSGIS(pname, params); +} + +static void APIENTRY InitGetPixelTexGenParameterfvSGIS (GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetPixelTexGenParameterfvSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetPixelTexGenParameterfvSGIS = extproc; + + glGetPixelTexGenParameterfvSGIS(pname, params); +} + +static void APIENTRY InitTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexImage4DSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexImage4DSGIS = extproc; + + glTexImage4DSGIS(target, level, internalformat, width, height, depth, size4d, border, format, type, pixels); +} + +static void APIENTRY InitTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage4DSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage4DSGIS = extproc; + + glTexSubImage4DSGIS(target, level, xoffset, yoffset, zoffset, woffset, width, height, depth, size4d, format, type, pixels); +} + +static GLboolean APIENTRY InitAreTexturesResidentEXT (GLsizei n, const GLuint *textures, GLboolean *residences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAreTexturesResidentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glAreTexturesResidentEXT = extproc; + + return glAreTexturesResidentEXT(n, textures, residences); +} + +static void APIENTRY InitBindTextureEXT (GLenum target, GLuint texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindTextureEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindTextureEXT = extproc; + + glBindTextureEXT(target, texture); +} + +static void APIENTRY InitDeleteTexturesEXT (GLsizei n, const GLuint *textures) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteTexturesEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteTexturesEXT = extproc; + + glDeleteTexturesEXT(n, textures); +} + +static void APIENTRY InitGenTexturesEXT (GLsizei n, GLuint *textures) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenTexturesEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenTexturesEXT = extproc; + + glGenTexturesEXT(n, textures); +} + +static GLboolean APIENTRY InitIsTextureEXT (GLuint texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsTextureEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsTextureEXT = extproc; + + return glIsTextureEXT(texture); +} + +static void APIENTRY InitPrioritizeTexturesEXT (GLsizei n, const GLuint *textures, const GLclampf *priorities) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPrioritizeTexturesEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPrioritizeTexturesEXT = extproc; + + glPrioritizeTexturesEXT(n, textures, priorities); +} + +static void APIENTRY InitDetailTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDetailTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDetailTexFuncSGIS = extproc; + + glDetailTexFuncSGIS(target, n, points); +} + +static void APIENTRY InitGetDetailTexFuncSGIS (GLenum target, GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetDetailTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetDetailTexFuncSGIS = extproc; + + glGetDetailTexFuncSGIS(target, points); +} + +static void APIENTRY InitSharpenTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSharpenTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSharpenTexFuncSGIS = extproc; + + glSharpenTexFuncSGIS(target, n, points); +} + +static void APIENTRY InitGetSharpenTexFuncSGIS (GLenum target, GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetSharpenTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetSharpenTexFuncSGIS = extproc; + + glGetSharpenTexFuncSGIS(target, points); +} + +static void APIENTRY InitSampleMaskSGIS (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleMaskSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleMaskSGIS = extproc; + + glSampleMaskSGIS(value, invert); +} + +static void APIENTRY InitSamplePatternSGIS (GLenum pattern) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSamplePatternSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSamplePatternSGIS = extproc; + + glSamplePatternSGIS(pattern); +} + +static void APIENTRY InitArrayElementEXT (GLint i) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glArrayElementEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glArrayElementEXT = extproc; + + glArrayElementEXT(i); +} + +static void APIENTRY InitColorPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorPointerEXT = extproc; + + glColorPointerEXT(size, type, stride, count, pointer); +} + +static void APIENTRY InitDrawArraysEXT (GLenum mode, GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawArraysEXT = extproc; + + glDrawArraysEXT(mode, first, count); +} + +static void APIENTRY InitEdgeFlagPointerEXT (GLsizei stride, GLsizei count, const GLboolean *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEdgeFlagPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEdgeFlagPointerEXT = extproc; + + glEdgeFlagPointerEXT(stride, count, pointer); +} + +static void APIENTRY InitGetPointervEXT (GLenum pname, GLvoid* *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetPointervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetPointervEXT = extproc; + + glGetPointervEXT(pname, params); +} + +static void APIENTRY InitIndexPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexPointerEXT = extproc; + + glIndexPointerEXT(type, stride, count, pointer); +} + +static void APIENTRY InitNormalPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalPointerEXT = extproc; + + glNormalPointerEXT(type, stride, count, pointer); +} + +static void APIENTRY InitTexCoordPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoordPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoordPointerEXT = extproc; + + glTexCoordPointerEXT(size, type, stride, count, pointer); +} + +static void APIENTRY InitVertexPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexPointerEXT = extproc; + + glVertexPointerEXT(size, type, stride, count, pointer); +} + +static void APIENTRY InitBlendEquationEXT (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendEquationEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendEquationEXT = extproc; + + glBlendEquationEXT(mode); +} + +static void APIENTRY InitSpriteParameterfSGIX (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameterfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameterfSGIX = extproc; + + glSpriteParameterfSGIX(pname, param); +} + +static void APIENTRY InitSpriteParameterfvSGIX (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameterfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameterfvSGIX = extproc; + + glSpriteParameterfvSGIX(pname, params); +} + +static void APIENTRY InitSpriteParameteriSGIX (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameteriSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameteriSGIX = extproc; + + glSpriteParameteriSGIX(pname, param); +} + +static void APIENTRY InitSpriteParameterivSGIX (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameterivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameterivSGIX = extproc; + + glSpriteParameterivSGIX(pname, params); +} + +static void APIENTRY InitPointParameterfEXT (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfEXT = extproc; + + glPointParameterfEXT(pname, param); +} + +static void APIENTRY InitPointParameterfvEXT (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfvEXT = extproc; + + glPointParameterfvEXT(pname, params); +} + +static void APIENTRY InitPointParameterfSGIS (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfSGIS = extproc; + + glPointParameterfSGIS(pname, param); +} + +static void APIENTRY InitPointParameterfvSGIS (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfvSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfvSGIS = extproc; + + glPointParameterfvSGIS(pname, params); +} + +static GLint APIENTRY InitGetInstrumentsSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetInstrumentsSGIX = extproc; + + return glGetInstrumentsSGIX(); +} + +static void APIENTRY InitInstrumentsBufferSGIX (GLsizei size, GLint *buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glInstrumentsBufferSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glInstrumentsBufferSGIX = extproc; + + glInstrumentsBufferSGIX(size, buffer); +} + +static GLint APIENTRY InitPollInstrumentsSGIX (GLint *marker_p) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPollInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glPollInstrumentsSGIX = extproc; + + return glPollInstrumentsSGIX(marker_p); +} + +static void APIENTRY InitReadInstrumentsSGIX (GLint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReadInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReadInstrumentsSGIX = extproc; + + glReadInstrumentsSGIX(marker); +} + +static void APIENTRY InitStartInstrumentsSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStartInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStartInstrumentsSGIX = extproc; + + glStartInstrumentsSGIX(); +} + +static void APIENTRY InitStopInstrumentsSGIX (GLint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStopInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStopInstrumentsSGIX = extproc; + + glStopInstrumentsSGIX(marker); +} + +static void APIENTRY InitFrameZoomSGIX (GLint factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFrameZoomSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFrameZoomSGIX = extproc; + + glFrameZoomSGIX(factor); +} + +static void APIENTRY InitTagSampleBufferSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTagSampleBufferSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTagSampleBufferSGIX = extproc; + + glTagSampleBufferSGIX(); +} + +static void APIENTRY InitDeformationMap3dSGIX (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeformationMap3dSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeformationMap3dSGIX = extproc; + + glDeformationMap3dSGIX(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, w1, w2, wstride, worder, points); +} + +static void APIENTRY InitDeformationMap3fSGIX (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeformationMap3fSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeformationMap3fSGIX = extproc; + + glDeformationMap3fSGIX(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, w1, w2, wstride, worder, points); +} + +static void APIENTRY InitDeformSGIX (GLbitfield mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeformSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeformSGIX = extproc; + + glDeformSGIX(mask); +} + +static void APIENTRY InitLoadIdentityDeformationMapSGIX (GLbitfield mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadIdentityDeformationMapSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadIdentityDeformationMapSGIX = extproc; + + glLoadIdentityDeformationMapSGIX(mask); +} + +static void APIENTRY InitReferencePlaneSGIX (const GLdouble *equation) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReferencePlaneSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReferencePlaneSGIX = extproc; + + glReferencePlaneSGIX(equation); +} + +static void APIENTRY InitFlushRasterSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushRasterSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushRasterSGIX = extproc; + + glFlushRasterSGIX(); +} + +static void APIENTRY InitFogFuncSGIS (GLsizei n, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogFuncSGIS = extproc; + + glFogFuncSGIS(n, points); +} + +static void APIENTRY InitGetFogFuncSGIS (GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFogFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFogFuncSGIS = extproc; + + glGetFogFuncSGIS(points); +} + +static void APIENTRY InitImageTransformParameteriHP (GLenum target, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameteriHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameteriHP = extproc; + + glImageTransformParameteriHP(target, pname, param); +} + +static void APIENTRY InitImageTransformParameterfHP (GLenum target, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameterfHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameterfHP = extproc; + + glImageTransformParameterfHP(target, pname, param); +} + +static void APIENTRY InitImageTransformParameterivHP (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameterivHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameterivHP = extproc; + + glImageTransformParameterivHP(target, pname, params); +} + +static void APIENTRY InitImageTransformParameterfvHP (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameterfvHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameterfvHP = extproc; + + glImageTransformParameterfvHP(target, pname, params); +} + +static void APIENTRY InitGetImageTransformParameterivHP (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetImageTransformParameterivHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetImageTransformParameterivHP = extproc; + + glGetImageTransformParameterivHP(target, pname, params); +} + +static void APIENTRY InitGetImageTransformParameterfvHP (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetImageTransformParameterfvHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetImageTransformParameterfvHP = extproc; + + glGetImageTransformParameterfvHP(target, pname, params); +} + +static void APIENTRY InitColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorSubTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorSubTableEXT = extproc; + + glColorSubTableEXT(target, start, count, format, type, data); +} + +static void APIENTRY InitCopyColorSubTableEXT (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorSubTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorSubTableEXT = extproc; + + glCopyColorSubTableEXT(target, start, x, y, width); +} + +static void APIENTRY InitHintPGI (GLenum target, GLint mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glHintPGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glHintPGI = extproc; + + glHintPGI(target, mode); +} + +static void APIENTRY InitColorTableEXT (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableEXT = extproc; + + glColorTableEXT(target, internalFormat, width, format, type, table); +} + +static void APIENTRY InitGetColorTableEXT (GLenum target, GLenum format, GLenum type, GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableEXT = extproc; + + glGetColorTableEXT(target, format, type, data); +} + +static void APIENTRY InitGetColorTableParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterivEXT = extproc; + + glGetColorTableParameterivEXT(target, pname, params); +} + +static void APIENTRY InitGetColorTableParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterfvEXT = extproc; + + glGetColorTableParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetListParameterfvSGIX (GLuint list, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetListParameterfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetListParameterfvSGIX = extproc; + + glGetListParameterfvSGIX(list, pname, params); +} + +static void APIENTRY InitGetListParameterivSGIX (GLuint list, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetListParameterivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetListParameterivSGIX = extproc; + + glGetListParameterivSGIX(list, pname, params); +} + +static void APIENTRY InitListParameterfSGIX (GLuint list, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameterfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameterfSGIX = extproc; + + glListParameterfSGIX(list, pname, param); +} + +static void APIENTRY InitListParameterfvSGIX (GLuint list, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameterfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameterfvSGIX = extproc; + + glListParameterfvSGIX(list, pname, params); +} + +static void APIENTRY InitListParameteriSGIX (GLuint list, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameteriSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameteriSGIX = extproc; + + glListParameteriSGIX(list, pname, param); +} + +static void APIENTRY InitListParameterivSGIX (GLuint list, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameterivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameterivSGIX = extproc; + + glListParameterivSGIX(list, pname, params); +} + +static void APIENTRY InitIndexMaterialEXT (GLenum face, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexMaterialEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexMaterialEXT = extproc; + + glIndexMaterialEXT(face, mode); +} + +static void APIENTRY InitIndexFuncEXT (GLenum func, GLclampf ref) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexFuncEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexFuncEXT = extproc; + + glIndexFuncEXT(func, ref); +} + +static void APIENTRY InitLockArraysEXT (GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLockArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLockArraysEXT = extproc; + + glLockArraysEXT(first, count); +} + +static void APIENTRY InitUnlockArraysEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnlockArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUnlockArraysEXT = extproc; + + glUnlockArraysEXT(); +} + +static void APIENTRY InitCullParameterdvEXT (GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCullParameterdvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCullParameterdvEXT = extproc; + + glCullParameterdvEXT(pname, params); +} + +static void APIENTRY InitCullParameterfvEXT (GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCullParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCullParameterfvEXT = extproc; + + glCullParameterfvEXT(pname, params); +} + +static void APIENTRY InitFragmentColorMaterialSGIX (GLenum face, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentColorMaterialSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentColorMaterialSGIX = extproc; + + glFragmentColorMaterialSGIX(face, mode); +} + +static void APIENTRY InitFragmentLightfSGIX (GLenum light, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightfSGIX = extproc; + + glFragmentLightfSGIX(light, pname, param); +} + +static void APIENTRY InitFragmentLightfvSGIX (GLenum light, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightfvSGIX = extproc; + + glFragmentLightfvSGIX(light, pname, params); +} + +static void APIENTRY InitFragmentLightiSGIX (GLenum light, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightiSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightiSGIX = extproc; + + glFragmentLightiSGIX(light, pname, param); +} + +static void APIENTRY InitFragmentLightivSGIX (GLenum light, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightivSGIX = extproc; + + glFragmentLightivSGIX(light, pname, params); +} + +static void APIENTRY InitFragmentLightModelfSGIX (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModelfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModelfSGIX = extproc; + + glFragmentLightModelfSGIX(pname, param); +} + +static void APIENTRY InitFragmentLightModelfvSGIX (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModelfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModelfvSGIX = extproc; + + glFragmentLightModelfvSGIX(pname, params); +} + +static void APIENTRY InitFragmentLightModeliSGIX (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModeliSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModeliSGIX = extproc; + + glFragmentLightModeliSGIX(pname, param); +} + +static void APIENTRY InitFragmentLightModelivSGIX (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModelivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModelivSGIX = extproc; + + glFragmentLightModelivSGIX(pname, params); +} + +static void APIENTRY InitFragmentMaterialfSGIX (GLenum face, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialfSGIX = extproc; + + glFragmentMaterialfSGIX(face, pname, param); +} + +static void APIENTRY InitFragmentMaterialfvSGIX (GLenum face, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialfvSGIX = extproc; + + glFragmentMaterialfvSGIX(face, pname, params); +} + +static void APIENTRY InitFragmentMaterialiSGIX (GLenum face, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialiSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialiSGIX = extproc; + + glFragmentMaterialiSGIX(face, pname, param); +} + +static void APIENTRY InitFragmentMaterialivSGIX (GLenum face, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialivSGIX = extproc; + + glFragmentMaterialivSGIX(face, pname, params); +} + +static void APIENTRY InitGetFragmentLightfvSGIX (GLenum light, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentLightfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentLightfvSGIX = extproc; + + glGetFragmentLightfvSGIX(light, pname, params); +} + +static void APIENTRY InitGetFragmentLightivSGIX (GLenum light, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentLightivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentLightivSGIX = extproc; + + glGetFragmentLightivSGIX(light, pname, params); +} + +static void APIENTRY InitGetFragmentMaterialfvSGIX (GLenum face, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentMaterialfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentMaterialfvSGIX = extproc; + + glGetFragmentMaterialfvSGIX(face, pname, params); +} + +static void APIENTRY InitGetFragmentMaterialivSGIX (GLenum face, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentMaterialivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentMaterialivSGIX = extproc; + + glGetFragmentMaterialivSGIX(face, pname, params); +} + +static void APIENTRY InitLightEnviSGIX (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLightEnviSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLightEnviSGIX = extproc; + + glLightEnviSGIX(pname, param); +} + +static void APIENTRY InitDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElementsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElementsEXT = extproc; + + glDrawRangeElementsEXT(mode, start, end, count, type, indices); +} + +static void APIENTRY InitApplyTextureEXT (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glApplyTextureEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glApplyTextureEXT = extproc; + + glApplyTextureEXT(mode); +} + +static void APIENTRY InitTextureLightEXT (GLenum pname) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureLightEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureLightEXT = extproc; + + glTextureLightEXT(pname); +} + +static void APIENTRY InitTextureMaterialEXT (GLenum face, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureMaterialEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureMaterialEXT = extproc; + + glTextureMaterialEXT(face, mode); +} + +static void APIENTRY InitAsyncMarkerSGIX (GLuint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAsyncMarkerSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAsyncMarkerSGIX = extproc; + + glAsyncMarkerSGIX(marker); +} + +static GLint APIENTRY InitFinishAsyncSGIX (GLuint *markerp) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishAsyncSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glFinishAsyncSGIX = extproc; + + return glFinishAsyncSGIX(markerp); +} + +static GLint APIENTRY InitPollAsyncSGIX (GLuint *markerp) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPollAsyncSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glPollAsyncSGIX = extproc; + + return glPollAsyncSGIX(markerp); +} + +static GLuint APIENTRY InitGenAsyncMarkersSGIX (GLsizei range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenAsyncMarkersSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenAsyncMarkersSGIX = extproc; + + return glGenAsyncMarkersSGIX(range); +} + +static void APIENTRY InitDeleteAsyncMarkersSGIX (GLuint marker, GLsizei range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteAsyncMarkersSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteAsyncMarkersSGIX = extproc; + + glDeleteAsyncMarkersSGIX(marker, range); +} + +static GLboolean APIENTRY InitIsAsyncMarkerSGIX (GLuint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsAsyncMarkerSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsAsyncMarkerSGIX = extproc; + + return glIsAsyncMarkerSGIX(marker); +} + +static void APIENTRY InitVertexPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexPointervINTEL = extproc; + + glVertexPointervINTEL(size, type, pointer); +} + +static void APIENTRY InitNormalPointervINTEL (GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalPointervINTEL = extproc; + + glNormalPointervINTEL(type, pointer); +} + +static void APIENTRY InitColorPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorPointervINTEL = extproc; + + glColorPointervINTEL(size, type, pointer); +} + +static void APIENTRY InitTexCoordPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoordPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoordPointervINTEL = extproc; + + glTexCoordPointervINTEL(size, type, pointer); +} + +static void APIENTRY InitPixelTransformParameteriEXT (GLenum target, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameteriEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameteriEXT = extproc; + + glPixelTransformParameteriEXT(target, pname, param); +} + +static void APIENTRY InitPixelTransformParameterfEXT (GLenum target, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameterfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameterfEXT = extproc; + + glPixelTransformParameterfEXT(target, pname, param); +} + +static void APIENTRY InitPixelTransformParameterivEXT (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameterivEXT = extproc; + + glPixelTransformParameterivEXT(target, pname, params); +} + +static void APIENTRY InitPixelTransformParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameterfvEXT = extproc; + + glPixelTransformParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitSecondaryColor3bEXT (GLbyte red, GLbyte green, GLbyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3bEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3bEXT = extproc; + + glSecondaryColor3bEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3bvEXT (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3bvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3bvEXT = extproc; + + glSecondaryColor3bvEXT(v); +} + +static void APIENTRY InitSecondaryColor3dEXT (GLdouble red, GLdouble green, GLdouble blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3dEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3dEXT = extproc; + + glSecondaryColor3dEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3dvEXT (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3dvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3dvEXT = extproc; + + glSecondaryColor3dvEXT(v); +} + +static void APIENTRY InitSecondaryColor3fEXT (GLfloat red, GLfloat green, GLfloat blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3fEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3fEXT = extproc; + + glSecondaryColor3fEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3fvEXT (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3fvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3fvEXT = extproc; + + glSecondaryColor3fvEXT(v); +} + +static void APIENTRY InitSecondaryColor3iEXT (GLint red, GLint green, GLint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3iEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3iEXT = extproc; + + glSecondaryColor3iEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3ivEXT (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ivEXT = extproc; + + glSecondaryColor3ivEXT(v); +} + +static void APIENTRY InitSecondaryColor3sEXT (GLshort red, GLshort green, GLshort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3sEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3sEXT = extproc; + + glSecondaryColor3sEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3svEXT (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3svEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3svEXT = extproc; + + glSecondaryColor3svEXT(v); +} + +static void APIENTRY InitSecondaryColor3ubEXT (GLubyte red, GLubyte green, GLubyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ubEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ubEXT = extproc; + + glSecondaryColor3ubEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3ubvEXT (const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ubvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ubvEXT = extproc; + + glSecondaryColor3ubvEXT(v); +} + +static void APIENTRY InitSecondaryColor3uiEXT (GLuint red, GLuint green, GLuint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3uiEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3uiEXT = extproc; + + glSecondaryColor3uiEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3uivEXT (const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3uivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3uivEXT = extproc; + + glSecondaryColor3uivEXT(v); +} + +static void APIENTRY InitSecondaryColor3usEXT (GLushort red, GLushort green, GLushort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3usEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3usEXT = extproc; + + glSecondaryColor3usEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3usvEXT (const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3usvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3usvEXT = extproc; + + glSecondaryColor3usvEXT(v); +} + +static void APIENTRY InitSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColorPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColorPointerEXT = extproc; + + glSecondaryColorPointerEXT(size, type, stride, pointer); +} + +static void APIENTRY InitTextureNormalEXT (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureNormalEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureNormalEXT = extproc; + + glTextureNormalEXT(mode); +} + +static void APIENTRY InitMultiDrawArraysEXT (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawArraysEXT = extproc; + + glMultiDrawArraysEXT(mode, first, count, primcount); +} + +static void APIENTRY InitMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawElementsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawElementsEXT = extproc; + + glMultiDrawElementsEXT(mode, count, type, indices, primcount); +} + +static void APIENTRY InitFogCoordfEXT (GLfloat coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordfEXT = extproc; + + glFogCoordfEXT(coord); +} + +static void APIENTRY InitFogCoordfvEXT (const GLfloat *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordfvEXT = extproc; + + glFogCoordfvEXT(coord); +} + +static void APIENTRY InitFogCoorddEXT (GLdouble coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoorddEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoorddEXT = extproc; + + glFogCoorddEXT(coord); +} + +static void APIENTRY InitFogCoorddvEXT (const GLdouble *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoorddvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoorddvEXT = extproc; + + glFogCoorddvEXT(coord); +} + +static void APIENTRY InitFogCoordPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordPointerEXT = extproc; + + glFogCoordPointerEXT(type, stride, pointer); +} + +static void APIENTRY InitTangent3bEXT (GLbyte tx, GLbyte ty, GLbyte tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3bEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3bEXT = extproc; + + glTangent3bEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3bvEXT (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3bvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3bvEXT = extproc; + + glTangent3bvEXT(v); +} + +static void APIENTRY InitTangent3dEXT (GLdouble tx, GLdouble ty, GLdouble tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3dEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3dEXT = extproc; + + glTangent3dEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3dvEXT (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3dvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3dvEXT = extproc; + + glTangent3dvEXT(v); +} + +static void APIENTRY InitTangent3fEXT (GLfloat tx, GLfloat ty, GLfloat tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3fEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3fEXT = extproc; + + glTangent3fEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3fvEXT (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3fvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3fvEXT = extproc; + + glTangent3fvEXT(v); +} + +static void APIENTRY InitTangent3iEXT (GLint tx, GLint ty, GLint tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3iEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3iEXT = extproc; + + glTangent3iEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3ivEXT (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3ivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3ivEXT = extproc; + + glTangent3ivEXT(v); +} + +static void APIENTRY InitTangent3sEXT (GLshort tx, GLshort ty, GLshort tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3sEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3sEXT = extproc; + + glTangent3sEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3svEXT (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3svEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3svEXT = extproc; + + glTangent3svEXT(v); +} + +static void APIENTRY InitBinormal3bEXT (GLbyte bx, GLbyte by, GLbyte bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3bEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3bEXT = extproc; + + glBinormal3bEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3bvEXT (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3bvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3bvEXT = extproc; + + glBinormal3bvEXT(v); +} + +static void APIENTRY InitBinormal3dEXT (GLdouble bx, GLdouble by, GLdouble bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3dEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3dEXT = extproc; + + glBinormal3dEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3dvEXT (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3dvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3dvEXT = extproc; + + glBinormal3dvEXT(v); +} + +static void APIENTRY InitBinormal3fEXT (GLfloat bx, GLfloat by, GLfloat bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3fEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3fEXT = extproc; + + glBinormal3fEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3fvEXT (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3fvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3fvEXT = extproc; + + glBinormal3fvEXT(v); +} + +static void APIENTRY InitBinormal3iEXT (GLint bx, GLint by, GLint bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3iEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3iEXT = extproc; + + glBinormal3iEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3ivEXT (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3ivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3ivEXT = extproc; + + glBinormal3ivEXT(v); +} + +static void APIENTRY InitBinormal3sEXT (GLshort bx, GLshort by, GLshort bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3sEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3sEXT = extproc; + + glBinormal3sEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3svEXT (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3svEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3svEXT = extproc; + + glBinormal3svEXT(v); +} + +static void APIENTRY InitTangentPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangentPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangentPointerEXT = extproc; + + glTangentPointerEXT(type, stride, pointer); +} + +static void APIENTRY InitBinormalPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormalPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormalPointerEXT = extproc; + + glBinormalPointerEXT(type, stride, pointer); +} + +static void APIENTRY InitFinishTextureSUNX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishTextureSUNX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishTextureSUNX = extproc; + + glFinishTextureSUNX(); +} + +static void APIENTRY InitGlobalAlphaFactorbSUN (GLbyte factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorbSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorbSUN = extproc; + + glGlobalAlphaFactorbSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorsSUN (GLshort factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorsSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorsSUN = extproc; + + glGlobalAlphaFactorsSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactoriSUN (GLint factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactoriSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactoriSUN = extproc; + + glGlobalAlphaFactoriSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorfSUN (GLfloat factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorfSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorfSUN = extproc; + + glGlobalAlphaFactorfSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactordSUN (GLdouble factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactordSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactordSUN = extproc; + + glGlobalAlphaFactordSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorubSUN (GLubyte factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorubSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorubSUN = extproc; + + glGlobalAlphaFactorubSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorusSUN (GLushort factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorusSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorusSUN = extproc; + + glGlobalAlphaFactorusSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactoruiSUN (GLuint factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactoruiSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactoruiSUN = extproc; + + glGlobalAlphaFactoruiSUN(factor); +} + +static void APIENTRY InitReplacementCodeuiSUN (GLuint code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiSUN = extproc; + + glReplacementCodeuiSUN(code); +} + +static void APIENTRY InitReplacementCodeusSUN (GLushort code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeusSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeusSUN = extproc; + + glReplacementCodeusSUN(code); +} + +static void APIENTRY InitReplacementCodeubSUN (GLubyte code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeubSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeubSUN = extproc; + + glReplacementCodeubSUN(code); +} + +static void APIENTRY InitReplacementCodeuivSUN (const GLuint *code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuivSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuivSUN = extproc; + + glReplacementCodeuivSUN(code); +} + +static void APIENTRY InitReplacementCodeusvSUN (const GLushort *code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeusvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeusvSUN = extproc; + + glReplacementCodeusvSUN(code); +} + +static void APIENTRY InitReplacementCodeubvSUN (const GLubyte *code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeubvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeubvSUN = extproc; + + glReplacementCodeubvSUN(code); +} + +static void APIENTRY InitReplacementCodePointerSUN (GLenum type, GLsizei stride, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodePointerSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodePointerSUN = extproc; + + glReplacementCodePointerSUN(type, stride, pointer); +} + +static void APIENTRY InitColor4ubVertex2fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex2fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex2fSUN = extproc; + + glColor4ubVertex2fSUN(r, g, b, a, x, y); +} + +static void APIENTRY InitColor4ubVertex2fvSUN (const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex2fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex2fvSUN = extproc; + + glColor4ubVertex2fvSUN(c, v); +} + +static void APIENTRY InitColor4ubVertex3fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex3fSUN = extproc; + + glColor4ubVertex3fSUN(r, g, b, a, x, y, z); +} + +static void APIENTRY InitColor4ubVertex3fvSUN (const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex3fvSUN = extproc; + + glColor4ubVertex3fvSUN(c, v); +} + +static void APIENTRY InitColor3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3fVertex3fSUN = extproc; + + glColor3fVertex3fSUN(r, g, b, x, y, z); +} + +static void APIENTRY InitColor3fVertex3fvSUN (const GLfloat *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3fVertex3fvSUN = extproc; + + glColor3fVertex3fvSUN(c, v); +} + +static void APIENTRY InitNormal3fVertex3fSUN (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3fVertex3fSUN = extproc; + + glNormal3fVertex3fSUN(nx, ny, nz, x, y, z); +} + +static void APIENTRY InitNormal3fVertex3fvSUN (const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3fVertex3fvSUN = extproc; + + glNormal3fVertex3fvSUN(n, v); +} + +static void APIENTRY InitColor4fNormal3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4fNormal3fVertex3fSUN = extproc; + + glColor4fNormal3fVertex3fSUN(r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitColor4fNormal3fVertex3fvSUN (const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4fNormal3fVertex3fvSUN = extproc; + + glColor4fNormal3fVertex3fvSUN(c, n, v); +} + +static void APIENTRY InitTexCoord2fVertex3fSUN (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fVertex3fSUN = extproc; + + glTexCoord2fVertex3fSUN(s, t, x, y, z); +} + +static void APIENTRY InitTexCoord2fVertex3fvSUN (const GLfloat *tc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fVertex3fvSUN = extproc; + + glTexCoord2fVertex3fvSUN(tc, v); +} + +static void APIENTRY InitTexCoord4fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fVertex4fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fVertex4fSUN = extproc; + + glTexCoord4fVertex4fSUN(s, t, p, q, x, y, z, w); +} + +static void APIENTRY InitTexCoord4fVertex4fvSUN (const GLfloat *tc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fVertex4fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fVertex4fvSUN = extproc; + + glTexCoord4fVertex4fvSUN(tc, v); +} + +static void APIENTRY InitTexCoord2fColor4ubVertex3fSUN (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4ubVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4ubVertex3fSUN = extproc; + + glTexCoord2fColor4ubVertex3fSUN(s, t, r, g, b, a, x, y, z); +} + +static void APIENTRY InitTexCoord2fColor4ubVertex3fvSUN (const GLfloat *tc, const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4ubVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4ubVertex3fvSUN = extproc; + + glTexCoord2fColor4ubVertex3fvSUN(tc, c, v); +} + +static void APIENTRY InitTexCoord2fColor3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor3fVertex3fSUN = extproc; + + glTexCoord2fColor3fVertex3fSUN(s, t, r, g, b, x, y, z); +} + +static void APIENTRY InitTexCoord2fColor3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor3fVertex3fvSUN = extproc; + + glTexCoord2fColor3fVertex3fvSUN(tc, c, v); +} + +static void APIENTRY InitTexCoord2fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fNormal3fVertex3fSUN = extproc; + + glTexCoord2fNormal3fVertex3fSUN(s, t, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitTexCoord2fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fNormal3fVertex3fvSUN = extproc; + + glTexCoord2fNormal3fVertex3fvSUN(tc, n, v); +} + +static void APIENTRY InitTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4fNormal3fVertex3fSUN = extproc; + + glTexCoord2fColor4fNormal3fVertex3fSUN(s, t, r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4fNormal3fVertex3fvSUN = extproc; + + glTexCoord2fColor4fNormal3fVertex3fvSUN(tc, c, n, v); +} + +static void APIENTRY InitTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fColor4fNormal3fVertex4fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fColor4fNormal3fVertex4fSUN = extproc; + + glTexCoord4fColor4fNormal3fVertex4fSUN(s, t, p, q, r, g, b, a, nx, ny, nz, x, y, z, w); +} + +static void APIENTRY InitTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fColor4fNormal3fVertex4fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fColor4fNormal3fVertex4fvSUN = extproc; + + glTexCoord4fColor4fNormal3fVertex4fvSUN(tc, c, n, v); +} + +static void APIENTRY InitReplacementCodeuiVertex3fSUN (GLuint rc, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiVertex3fSUN = extproc; + + glReplacementCodeuiVertex3fSUN(rc, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiVertex3fvSUN (const GLuint *rc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiVertex3fvSUN = extproc; + + glReplacementCodeuiVertex3fvSUN(rc, v); +} + +static void APIENTRY InitReplacementCodeuiColor4ubVertex3fSUN (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4ubVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4ubVertex3fSUN = extproc; + + glReplacementCodeuiColor4ubVertex3fSUN(rc, r, g, b, a, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *rc, const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4ubVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4ubVertex3fvSUN = extproc; + + glReplacementCodeuiColor4ubVertex3fvSUN(rc, c, v); +} + +static void APIENTRY InitReplacementCodeuiColor3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor3fVertex3fSUN = extproc; + + glReplacementCodeuiColor3fVertex3fSUN(rc, r, g, b, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiColor3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor3fVertex3fvSUN = extproc; + + glReplacementCodeuiColor3fVertex3fvSUN(rc, c, v); +} + +static void APIENTRY InitReplacementCodeuiNormal3fVertex3fSUN (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiNormal3fVertex3fSUN(rc, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiNormal3fVertex3fvSUN(rc, n, v); +} + +static void APIENTRY InitReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4fNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiColor4fNormal3fVertex3fSUN(rc, r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4fNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiColor4fNormal3fVertex3fvSUN(rc, c, n, v); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fVertex3fSUN = extproc; + + glReplacementCodeuiTexCoord2fVertex3fSUN(rc, s, t, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fVertex3fvSUN = extproc; + + glReplacementCodeuiTexCoord2fVertex3fvSUN(rc, tc, v); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN(rc, s, t, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN(rc, tc, n, v); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN(rc, s, t, r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN(rc, tc, c, n, v); +} + +static void APIENTRY InitBlendFuncSeparateEXT (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendFuncSeparateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendFuncSeparateEXT = extproc; + + glBlendFuncSeparateEXT(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void APIENTRY InitBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendFuncSeparateINGR"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendFuncSeparateINGR = extproc; + + glBlendFuncSeparateINGR(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void APIENTRY InitVertexWeightfEXT (GLfloat weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeightfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeightfEXT = extproc; + + glVertexWeightfEXT(weight); +} + +static void APIENTRY InitVertexWeightfvEXT (const GLfloat *weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeightfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeightfvEXT = extproc; + + glVertexWeightfvEXT(weight); +} + +static void APIENTRY InitVertexWeightPointerEXT (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeightPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeightPointerEXT = extproc; + + glVertexWeightPointerEXT(size, type, stride, pointer); +} + +static void APIENTRY InitFlushVertexArrayRangeNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushVertexArrayRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushVertexArrayRangeNV = extproc; + + glFlushVertexArrayRangeNV(); +} + +static void APIENTRY InitVertexArrayRangeNV (GLsizei length, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexArrayRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexArrayRangeNV = extproc; + + glVertexArrayRangeNV(length, pointer); +} + +static void APIENTRY InitCombinerParameterfvNV (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameterfvNV = extproc; + + glCombinerParameterfvNV(pname, params); +} + +static void APIENTRY InitCombinerParameterfNV (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameterfNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameterfNV = extproc; + + glCombinerParameterfNV(pname, param); +} + +static void APIENTRY InitCombinerParameterivNV (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameterivNV = extproc; + + glCombinerParameterivNV(pname, params); +} + +static void APIENTRY InitCombinerParameteriNV (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameteriNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameteriNV = extproc; + + glCombinerParameteriNV(pname, param); +} + +static void APIENTRY InitCombinerInputNV (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerInputNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerInputNV = extproc; + + glCombinerInputNV(stage, portion, variable, input, mapping, componentUsage); +} + +static void APIENTRY InitCombinerOutputNV (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerOutputNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerOutputNV = extproc; + + glCombinerOutputNV(stage, portion, abOutput, cdOutput, sumOutput, scale, bias, abDotProduct, cdDotProduct, muxSum); +} + +static void APIENTRY InitFinalCombinerInputNV (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinalCombinerInputNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinalCombinerInputNV = extproc; + + glFinalCombinerInputNV(variable, input, mapping, componentUsage); +} + +static void APIENTRY InitGetCombinerInputParameterfvNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerInputParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerInputParameterfvNV = extproc; + + glGetCombinerInputParameterfvNV(stage, portion, variable, pname, params); +} + +static void APIENTRY InitGetCombinerInputParameterivNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerInputParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerInputParameterivNV = extproc; + + glGetCombinerInputParameterivNV(stage, portion, variable, pname, params); +} + +static void APIENTRY InitGetCombinerOutputParameterfvNV (GLenum stage, GLenum portion, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerOutputParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerOutputParameterfvNV = extproc; + + glGetCombinerOutputParameterfvNV(stage, portion, pname, params); +} + +static void APIENTRY InitGetCombinerOutputParameterivNV (GLenum stage, GLenum portion, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerOutputParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerOutputParameterivNV = extproc; + + glGetCombinerOutputParameterivNV(stage, portion, pname, params); +} + +static void APIENTRY InitGetFinalCombinerInputParameterfvNV (GLenum variable, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFinalCombinerInputParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFinalCombinerInputParameterfvNV = extproc; + + glGetFinalCombinerInputParameterfvNV(variable, pname, params); +} + +static void APIENTRY InitGetFinalCombinerInputParameterivNV (GLenum variable, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFinalCombinerInputParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFinalCombinerInputParameterivNV = extproc; + + glGetFinalCombinerInputParameterivNV(variable, pname, params); +} + +static void APIENTRY InitResizeBuffersMESA (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResizeBuffersMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResizeBuffersMESA = extproc; + + glResizeBuffersMESA(); +} + +static void APIENTRY InitWindowPos2dMESA (GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dMESA = extproc; + + glWindowPos2dMESA(x, y); +} + +static void APIENTRY InitWindowPos2dvMESA (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dvMESA = extproc; + + glWindowPos2dvMESA(v); +} + +static void APIENTRY InitWindowPos2fMESA (GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fMESA = extproc; + + glWindowPos2fMESA(x, y); +} + +static void APIENTRY InitWindowPos2fvMESA (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fvMESA = extproc; + + glWindowPos2fvMESA(v); +} + +static void APIENTRY InitWindowPos2iMESA (GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2iMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2iMESA = extproc; + + glWindowPos2iMESA(x, y); +} + +static void APIENTRY InitWindowPos2ivMESA (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2ivMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2ivMESA = extproc; + + glWindowPos2ivMESA(v); +} + +static void APIENTRY InitWindowPos2sMESA (GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2sMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2sMESA = extproc; + + glWindowPos2sMESA(x, y); +} + +static void APIENTRY InitWindowPos2svMESA (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2svMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2svMESA = extproc; + + glWindowPos2svMESA(v); +} + +static void APIENTRY InitWindowPos3dMESA (GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dMESA = extproc; + + glWindowPos3dMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3dvMESA (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dvMESA = extproc; + + glWindowPos3dvMESA(v); +} + +static void APIENTRY InitWindowPos3fMESA (GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fMESA = extproc; + + glWindowPos3fMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3fvMESA (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fvMESA = extproc; + + glWindowPos3fvMESA(v); +} + +static void APIENTRY InitWindowPos3iMESA (GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3iMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3iMESA = extproc; + + glWindowPos3iMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3ivMESA (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3ivMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3ivMESA = extproc; + + glWindowPos3ivMESA(v); +} + +static void APIENTRY InitWindowPos3sMESA (GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3sMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3sMESA = extproc; + + glWindowPos3sMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3svMESA (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3svMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3svMESA = extproc; + + glWindowPos3svMESA(v); +} + +static void APIENTRY InitWindowPos4dMESA (GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4dMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4dMESA = extproc; + + glWindowPos4dMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4dvMESA (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4dvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4dvMESA = extproc; + + glWindowPos4dvMESA(v); +} + +static void APIENTRY InitWindowPos4fMESA (GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4fMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4fMESA = extproc; + + glWindowPos4fMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4fvMESA (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4fvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4fvMESA = extproc; + + glWindowPos4fvMESA(v); +} + +static void APIENTRY InitWindowPos4iMESA (GLint x, GLint y, GLint z, GLint w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4iMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4iMESA = extproc; + + glWindowPos4iMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4ivMESA (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4ivMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4ivMESA = extproc; + + glWindowPos4ivMESA(v); +} + +static void APIENTRY InitWindowPos4sMESA (GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4sMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4sMESA = extproc; + + glWindowPos4sMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4svMESA (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4svMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4svMESA = extproc; + + glWindowPos4svMESA(v); +} + +static void APIENTRY InitMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiModeDrawArraysIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiModeDrawArraysIBM = extproc; + + glMultiModeDrawArraysIBM(mode, first, count, primcount, modestride); +} + +static void APIENTRY InitMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiModeDrawElementsIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiModeDrawElementsIBM = extproc; + + glMultiModeDrawElementsIBM(mode, count, type, indices, primcount, modestride); +} + +static void APIENTRY InitColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorPointerListIBM = extproc; + + glColorPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitSecondaryColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColorPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColorPointerListIBM = extproc; + + glSecondaryColorPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitEdgeFlagPointerListIBM (GLint stride, const GLboolean* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEdgeFlagPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEdgeFlagPointerListIBM = extproc; + + glEdgeFlagPointerListIBM(stride, pointer, ptrstride); +} + +static void APIENTRY InitFogCoordPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordPointerListIBM = extproc; + + glFogCoordPointerListIBM(type, stride, pointer, ptrstride); +} + +static void APIENTRY InitIndexPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexPointerListIBM = extproc; + + glIndexPointerListIBM(type, stride, pointer, ptrstride); +} + +static void APIENTRY InitNormalPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalPointerListIBM = extproc; + + glNormalPointerListIBM(type, stride, pointer, ptrstride); +} + +static void APIENTRY InitTexCoordPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoordPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoordPointerListIBM = extproc; + + glTexCoordPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitVertexPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexPointerListIBM = extproc; + + glVertexPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitTbufferMask3DFX (GLuint mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTbufferMask3DFX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTbufferMask3DFX = extproc; + + glTbufferMask3DFX(mask); +} + +static void APIENTRY InitSampleMaskEXT (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleMaskEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleMaskEXT = extproc; + + glSampleMaskEXT(value, invert); +} + +static void APIENTRY InitSamplePatternEXT (GLenum pattern) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSamplePatternEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSamplePatternEXT = extproc; + + glSamplePatternEXT(pattern); +} + +static void APIENTRY InitTextureColorMaskSGIS (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureColorMaskSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureColorMaskSGIS = extproc; + + glTextureColorMaskSGIS(red, green, blue, alpha); +} + +static void APIENTRY InitIglooInterfaceSGIX (GLenum pname, const GLvoid *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIglooInterfaceSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIglooInterfaceSGIX = extproc; + + glIglooInterfaceSGIX(pname, params); +} + +static void APIENTRY InitDeleteFencesNV (GLsizei n, const GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteFencesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteFencesNV = extproc; + + glDeleteFencesNV(n, fences); +} + +static void APIENTRY InitGenFencesNV (GLsizei n, GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenFencesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenFencesNV = extproc; + + glGenFencesNV(n, fences); +} + +static GLboolean APIENTRY InitIsFenceNV (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsFenceNV = extproc; + + return glIsFenceNV(fence); +} + +static GLboolean APIENTRY InitTestFenceNV (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTestFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glTestFenceNV = extproc; + + return glTestFenceNV(fence); +} + +static void APIENTRY InitGetFenceivNV (GLuint fence, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFenceivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFenceivNV = extproc; + + glGetFenceivNV(fence, pname, params); +} + +static void APIENTRY InitFinishFenceNV (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishFenceNV = extproc; + + glFinishFenceNV(fence); +} + +static void APIENTRY InitSetFenceNV (GLuint fence, GLenum condition) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetFenceNV = extproc; + + glSetFenceNV(fence, condition); +} + +static void APIENTRY InitMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapControlPointsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMapControlPointsNV = extproc; + + glMapControlPointsNV(target, index, type, ustride, vstride, uorder, vorder, packed, points); +} + +static void APIENTRY InitMapParameterivNV (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMapParameterivNV = extproc; + + glMapParameterivNV(target, pname, params); +} + +static void APIENTRY InitMapParameterfvNV (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMapParameterfvNV = extproc; + + glMapParameterfvNV(target, pname, params); +} + +static void APIENTRY InitGetMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapControlPointsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapControlPointsNV = extproc; + + glGetMapControlPointsNV(target, index, type, ustride, vstride, packed, points); +} + +static void APIENTRY InitGetMapParameterivNV (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapParameterivNV = extproc; + + glGetMapParameterivNV(target, pname, params); +} + +static void APIENTRY InitGetMapParameterfvNV (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapParameterfvNV = extproc; + + glGetMapParameterfvNV(target, pname, params); +} + +static void APIENTRY InitGetMapAttribParameterivNV (GLenum target, GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapAttribParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapAttribParameterivNV = extproc; + + glGetMapAttribParameterivNV(target, index, pname, params); +} + +static void APIENTRY InitGetMapAttribParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapAttribParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapAttribParameterfvNV = extproc; + + glGetMapAttribParameterfvNV(target, index, pname, params); +} + +static void APIENTRY InitEvalMapsNV (GLenum target, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEvalMapsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEvalMapsNV = extproc; + + glEvalMapsNV(target, mode); +} + +static void APIENTRY InitCombinerStageParameterfvNV (GLenum stage, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerStageParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerStageParameterfvNV = extproc; + + glCombinerStageParameterfvNV(stage, pname, params); +} + +static void APIENTRY InitGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerStageParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerStageParameterfvNV = extproc; + + glGetCombinerStageParameterfvNV(stage, pname, params); +} + +static GLboolean APIENTRY InitAreProgramsResidentNV (GLsizei n, const GLuint *programs, GLboolean *residences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAreProgramsResidentNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glAreProgramsResidentNV = extproc; + + return glAreProgramsResidentNV(n, programs, residences); +} + +static void APIENTRY InitBindProgramNV (GLenum target, GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindProgramNV = extproc; + + glBindProgramNV(target, id); +} + +static void APIENTRY InitDeleteProgramsNV (GLsizei n, const GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteProgramsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteProgramsNV = extproc; + + glDeleteProgramsNV(n, programs); +} + +static void APIENTRY InitExecuteProgramNV (GLenum target, GLuint id, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glExecuteProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glExecuteProgramNV = extproc; + + glExecuteProgramNV(target, id, params); +} + +static void APIENTRY InitGenProgramsNV (GLsizei n, GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenProgramsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenProgramsNV = extproc; + + glGenProgramsNV(n, programs); +} + +static void APIENTRY InitGetProgramParameterdvNV (GLenum target, GLuint index, GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramParameterdvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramParameterdvNV = extproc; + + glGetProgramParameterdvNV(target, index, pname, params); +} + +static void APIENTRY InitGetProgramParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramParameterfvNV = extproc; + + glGetProgramParameterfvNV(target, index, pname, params); +} + +static void APIENTRY InitGetProgramivNV (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramivNV = extproc; + + glGetProgramivNV(id, pname, params); +} + +static void APIENTRY InitGetProgramStringNV (GLuint id, GLenum pname, GLubyte *program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramStringNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramStringNV = extproc; + + glGetProgramStringNV(id, pname, program); +} + +static void APIENTRY InitGetTrackMatrixivNV (GLenum target, GLuint address, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTrackMatrixivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTrackMatrixivNV = extproc; + + glGetTrackMatrixivNV(target, address, pname, params); +} + +static void APIENTRY InitGetVertexAttribdvNV (GLuint index, GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribdvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribdvNV = extproc; + + glGetVertexAttribdvNV(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribfvNV (GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribfvNV = extproc; + + glGetVertexAttribfvNV(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribivNV (GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribivNV = extproc; + + glGetVertexAttribivNV(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribPointervNV (GLuint index, GLenum pname, GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribPointervNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribPointervNV = extproc; + + glGetVertexAttribPointervNV(index, pname, pointer); +} + +static GLboolean APIENTRY InitIsProgramNV (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsProgramNV = extproc; + + return glIsProgramNV(id); +} + +static void APIENTRY InitLoadProgramNV (GLenum target, GLuint id, GLsizei len, const GLubyte *program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadProgramNV = extproc; + + glLoadProgramNV(target, id, len, program); +} + +static void APIENTRY InitProgramParameter4dNV (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4dNV = extproc; + + glProgramParameter4dNV(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramParameter4dvNV (GLenum target, GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4dvNV = extproc; + + glProgramParameter4dvNV(target, index, v); +} + +static void APIENTRY InitProgramParameter4fNV (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4fNV = extproc; + + glProgramParameter4fNV(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramParameter4fvNV (GLenum target, GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4fvNV = extproc; + + glProgramParameter4fvNV(target, index, v); +} + +static void APIENTRY InitProgramParameters4dvNV (GLenum target, GLuint index, GLuint count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameters4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameters4dvNV = extproc; + + glProgramParameters4dvNV(target, index, count, v); +} + +static void APIENTRY InitProgramParameters4fvNV (GLenum target, GLuint index, GLuint count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameters4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameters4fvNV = extproc; + + glProgramParameters4fvNV(target, index, count, v); +} + +static void APIENTRY InitRequestResidentProgramsNV (GLsizei n, const GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glRequestResidentProgramsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glRequestResidentProgramsNV = extproc; + + glRequestResidentProgramsNV(n, programs); +} + +static void APIENTRY InitTrackMatrixNV (GLenum target, GLuint address, GLenum matrix, GLenum transform) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTrackMatrixNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTrackMatrixNV = extproc; + + glTrackMatrixNV(target, address, matrix, transform); +} + +static void APIENTRY InitVertexAttribPointerNV (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribPointerNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribPointerNV = extproc; + + glVertexAttribPointerNV(index, fsize, type, stride, pointer); +} + +static void APIENTRY InitVertexAttrib1dNV (GLuint index, GLdouble x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dNV = extproc; + + glVertexAttrib1dNV(index, x); +} + +static void APIENTRY InitVertexAttrib1dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dvNV = extproc; + + glVertexAttrib1dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib1fNV (GLuint index, GLfloat x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fNV = extproc; + + glVertexAttrib1fNV(index, x); +} + +static void APIENTRY InitVertexAttrib1fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fvNV = extproc; + + glVertexAttrib1fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib1sNV (GLuint index, GLshort x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1sNV = extproc; + + glVertexAttrib1sNV(index, x); +} + +static void APIENTRY InitVertexAttrib1svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1svNV = extproc; + + glVertexAttrib1svNV(index, v); +} + +static void APIENTRY InitVertexAttrib2dNV (GLuint index, GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dNV = extproc; + + glVertexAttrib2dNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dvNV = extproc; + + glVertexAttrib2dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib2fNV (GLuint index, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fNV = extproc; + + glVertexAttrib2fNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fvNV = extproc; + + glVertexAttrib2fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib2sNV (GLuint index, GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2sNV = extproc; + + glVertexAttrib2sNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2svNV = extproc; + + glVertexAttrib2svNV(index, v); +} + +static void APIENTRY InitVertexAttrib3dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dNV = extproc; + + glVertexAttrib3dNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dvNV = extproc; + + glVertexAttrib3dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib3fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fNV = extproc; + + glVertexAttrib3fNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fvNV = extproc; + + glVertexAttrib3fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib3sNV (GLuint index, GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3sNV = extproc; + + glVertexAttrib3sNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3svNV = extproc; + + glVertexAttrib3svNV(index, v); +} + +static void APIENTRY InitVertexAttrib4dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dNV = extproc; + + glVertexAttrib4dNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dvNV = extproc; + + glVertexAttrib4dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib4fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fNV = extproc; + + glVertexAttrib4fNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fvNV = extproc; + + glVertexAttrib4fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib4sNV (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4sNV = extproc; + + glVertexAttrib4sNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4svNV = extproc; + + glVertexAttrib4svNV(index, v); +} + +static void APIENTRY InitVertexAttrib4ubNV (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ubNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ubNV = extproc; + + glVertexAttrib4ubNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4ubvNV (GLuint index, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ubvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ubvNV = extproc; + + glVertexAttrib4ubvNV(index, v); +} + +static void APIENTRY InitVertexAttribs1dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1dvNV = extproc; + + glVertexAttribs1dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs1fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1fvNV = extproc; + + glVertexAttribs1fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs1svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1svNV = extproc; + + glVertexAttribs1svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs2dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2dvNV = extproc; + + glVertexAttribs2dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs2fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2fvNV = extproc; + + glVertexAttribs2fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs2svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2svNV = extproc; + + glVertexAttribs2svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs3dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3dvNV = extproc; + + glVertexAttribs3dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs3fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3fvNV = extproc; + + glVertexAttribs3fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs3svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3svNV = extproc; + + glVertexAttribs3svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4dvNV = extproc; + + glVertexAttribs4dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4fvNV = extproc; + + glVertexAttribs4fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4svNV = extproc; + + glVertexAttribs4svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4ubvNV (GLuint index, GLsizei count, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4ubvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4ubvNV = extproc; + + glVertexAttribs4ubvNV(index, count, v); +} + +static void APIENTRY InitTexBumpParameterivATI (GLenum pname, const GLint *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexBumpParameterivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexBumpParameterivATI = extproc; + + glTexBumpParameterivATI(pname, param); +} + +static void APIENTRY InitTexBumpParameterfvATI (GLenum pname, const GLfloat *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexBumpParameterfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexBumpParameterfvATI = extproc; + + glTexBumpParameterfvATI(pname, param); +} + +static void APIENTRY InitGetTexBumpParameterivATI (GLenum pname, GLint *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTexBumpParameterivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTexBumpParameterivATI = extproc; + + glGetTexBumpParameterivATI(pname, param); +} + +static void APIENTRY InitGetTexBumpParameterfvATI (GLenum pname, GLfloat *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTexBumpParameterfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTexBumpParameterfvATI = extproc; + + glGetTexBumpParameterfvATI(pname, param); +} + +static GLuint APIENTRY InitGenFragmentShadersATI (GLuint range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenFragmentShadersATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenFragmentShadersATI = extproc; + + return glGenFragmentShadersATI(range); +} + +static void APIENTRY InitBindFragmentShaderATI (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindFragmentShaderATI = extproc; + + glBindFragmentShaderATI(id); +} + +static void APIENTRY InitDeleteFragmentShaderATI (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteFragmentShaderATI = extproc; + + glDeleteFragmentShaderATI(id); +} + +static void APIENTRY InitBeginFragmentShaderATI (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginFragmentShaderATI = extproc; + + glBeginFragmentShaderATI(); +} + +static void APIENTRY InitEndFragmentShaderATI (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndFragmentShaderATI = extproc; + + glEndFragmentShaderATI(); +} + +static void APIENTRY InitPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPassTexCoordATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPassTexCoordATI = extproc; + + glPassTexCoordATI(dst, coord, swizzle); +} + +static void APIENTRY InitSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleMapATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleMapATI = extproc; + + glSampleMapATI(dst, interp, swizzle); +} + +static void APIENTRY InitColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorFragmentOp1ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorFragmentOp1ATI = extproc; + + glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod); +} + +static void APIENTRY InitColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorFragmentOp2ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorFragmentOp2ATI = extproc; + + glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod); +} + +static void APIENTRY InitColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorFragmentOp3ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorFragmentOp3ATI = extproc; + + glColorFragmentOp3ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod); +} + +static void APIENTRY InitAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAlphaFragmentOp1ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAlphaFragmentOp1ATI = extproc; + + glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod); +} + +static void APIENTRY InitAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAlphaFragmentOp2ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAlphaFragmentOp2ATI = extproc; + + glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod); +} + +static void APIENTRY InitAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAlphaFragmentOp3ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAlphaFragmentOp3ATI = extproc; + + glAlphaFragmentOp3ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod); +} + +static void APIENTRY InitSetFragmentShaderConstantATI (GLuint dst, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetFragmentShaderConstantATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetFragmentShaderConstantATI = extproc; + + glSetFragmentShaderConstantATI(dst, value); +} + +static void APIENTRY InitPNTrianglesiATI (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPNTrianglesiATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPNTrianglesiATI = extproc; + + glPNTrianglesiATI(pname, param); +} + +static void APIENTRY InitPNTrianglesfATI (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPNTrianglesfATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPNTrianglesfATI = extproc; + + glPNTrianglesfATI(pname, param); +} + +static GLuint APIENTRY InitNewObjectBufferATI (GLsizei size, const GLvoid *pointer, GLenum usage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNewObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glNewObjectBufferATI = extproc; + + return glNewObjectBufferATI(size, pointer, usage); +} + +static GLboolean APIENTRY InitIsObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsObjectBufferATI = extproc; + + return glIsObjectBufferATI(buffer); +} + +static void APIENTRY InitUpdateObjectBufferATI (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUpdateObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUpdateObjectBufferATI = extproc; + + glUpdateObjectBufferATI(buffer, offset, size, pointer, preserve); +} + +static void APIENTRY InitGetObjectBufferfvATI (GLuint buffer, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectBufferfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectBufferfvATI = extproc; + + glGetObjectBufferfvATI(buffer, pname, params); +} + +static void APIENTRY InitGetObjectBufferivATI (GLuint buffer, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectBufferivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectBufferivATI = extproc; + + glGetObjectBufferivATI(buffer, pname, params); +} + +static void APIENTRY InitFreeObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFreeObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFreeObjectBufferATI = extproc; + + glFreeObjectBufferATI(buffer); +} + +static void APIENTRY InitArrayObjectATI (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glArrayObjectATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glArrayObjectATI = extproc; + + glArrayObjectATI(array, size, type, stride, buffer, offset); +} + +static void APIENTRY InitGetArrayObjectfvATI (GLenum array, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetArrayObjectfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetArrayObjectfvATI = extproc; + + glGetArrayObjectfvATI(array, pname, params); +} + +static void APIENTRY InitGetArrayObjectivATI (GLenum array, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetArrayObjectivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetArrayObjectivATI = extproc; + + glGetArrayObjectivATI(array, pname, params); +} + +static void APIENTRY InitVariantArrayObjectATI (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantArrayObjectATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantArrayObjectATI = extproc; + + glVariantArrayObjectATI(id, type, stride, buffer, offset); +} + +static void APIENTRY InitGetVariantArrayObjectfvATI (GLuint id, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantArrayObjectfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantArrayObjectfvATI = extproc; + + glGetVariantArrayObjectfvATI(id, pname, params); +} + +static void APIENTRY InitGetVariantArrayObjectivATI (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantArrayObjectivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantArrayObjectivATI = extproc; + + glGetVariantArrayObjectivATI(id, pname, params); +} + +static void APIENTRY InitBeginVertexShaderEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginVertexShaderEXT = extproc; + + glBeginVertexShaderEXT(); +} + +static void APIENTRY InitEndVertexShaderEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndVertexShaderEXT = extproc; + + glEndVertexShaderEXT(); +} + +static void APIENTRY InitBindVertexShaderEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindVertexShaderEXT = extproc; + + glBindVertexShaderEXT(id); +} + +static GLuint APIENTRY InitGenVertexShadersEXT (GLuint range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenVertexShadersEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenVertexShadersEXT = extproc; + + return glGenVertexShadersEXT(range); +} + +static void APIENTRY InitDeleteVertexShaderEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteVertexShaderEXT = extproc; + + glDeleteVertexShaderEXT(id); +} + +static void APIENTRY InitShaderOp1EXT (GLenum op, GLuint res, GLuint arg1) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderOp1EXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderOp1EXT = extproc; + + glShaderOp1EXT(op, res, arg1); +} + +static void APIENTRY InitShaderOp2EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderOp2EXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderOp2EXT = extproc; + + glShaderOp2EXT(op, res, arg1, arg2); +} + +static void APIENTRY InitShaderOp3EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderOp3EXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderOp3EXT = extproc; + + glShaderOp3EXT(op, res, arg1, arg2, arg3); +} + +static void APIENTRY InitSwizzleEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSwizzleEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSwizzleEXT = extproc; + + glSwizzleEXT(res, in, outX, outY, outZ, outW); +} + +static void APIENTRY InitWriteMaskEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWriteMaskEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWriteMaskEXT = extproc; + + glWriteMaskEXT(res, in, outX, outY, outZ, outW); +} + +static void APIENTRY InitInsertComponentEXT (GLuint res, GLuint src, GLuint num) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glInsertComponentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glInsertComponentEXT = extproc; + + glInsertComponentEXT(res, src, num); +} + +static void APIENTRY InitExtractComponentEXT (GLuint res, GLuint src, GLuint num) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glExtractComponentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glExtractComponentEXT = extproc; + + glExtractComponentEXT(res, src, num); +} + +static GLuint APIENTRY InitGenSymbolsEXT (GLenum datatype, GLenum storagetype, GLenum range, GLuint components) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenSymbolsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenSymbolsEXT = extproc; + + return glGenSymbolsEXT(datatype, storagetype, range, components); +} + +static void APIENTRY InitSetInvariantEXT (GLuint id, GLenum type, const GLvoid *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetInvariantEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetInvariantEXT = extproc; + + glSetInvariantEXT(id, type, addr); +} + +static void APIENTRY InitSetLocalConstantEXT (GLuint id, GLenum type, const GLvoid *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetLocalConstantEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetLocalConstantEXT = extproc; + + glSetLocalConstantEXT(id, type, addr); +} + +static void APIENTRY InitVariantbvEXT (GLuint id, const GLbyte *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantbvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantbvEXT = extproc; + + glVariantbvEXT(id, addr); +} + +static void APIENTRY InitVariantsvEXT (GLuint id, const GLshort *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantsvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantsvEXT = extproc; + + glVariantsvEXT(id, addr); +} + +static void APIENTRY InitVariantivEXT (GLuint id, const GLint *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantivEXT = extproc; + + glVariantivEXT(id, addr); +} + +static void APIENTRY InitVariantfvEXT (GLuint id, const GLfloat *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantfvEXT = extproc; + + glVariantfvEXT(id, addr); +} + +static void APIENTRY InitVariantdvEXT (GLuint id, const GLdouble *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantdvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantdvEXT = extproc; + + glVariantdvEXT(id, addr); +} + +static void APIENTRY InitVariantubvEXT (GLuint id, const GLubyte *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantubvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantubvEXT = extproc; + + glVariantubvEXT(id, addr); +} + +static void APIENTRY InitVariantusvEXT (GLuint id, const GLushort *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantusvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantusvEXT = extproc; + + glVariantusvEXT(id, addr); +} + +static void APIENTRY InitVariantuivEXT (GLuint id, const GLuint *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantuivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantuivEXT = extproc; + + glVariantuivEXT(id, addr); +} + +static void APIENTRY InitVariantPointerEXT (GLuint id, GLenum type, GLuint stride, const GLvoid *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantPointerEXT = extproc; + + glVariantPointerEXT(id, type, stride, addr); +} + +static void APIENTRY InitEnableVariantClientStateEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEnableVariantClientStateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEnableVariantClientStateEXT = extproc; + + glEnableVariantClientStateEXT(id); +} + +static void APIENTRY InitDisableVariantClientStateEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDisableVariantClientStateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDisableVariantClientStateEXT = extproc; + + glDisableVariantClientStateEXT(id); +} + +static GLuint APIENTRY InitBindLightParameterEXT (GLenum light, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindLightParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindLightParameterEXT = extproc; + + return glBindLightParameterEXT(light, value); +} + +static GLuint APIENTRY InitBindMaterialParameterEXT (GLenum face, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindMaterialParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindMaterialParameterEXT = extproc; + + return glBindMaterialParameterEXT(face, value); +} + +static GLuint APIENTRY InitBindTexGenParameterEXT (GLenum unit, GLenum coord, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindTexGenParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindTexGenParameterEXT = extproc; + + return glBindTexGenParameterEXT(unit, coord, value); +} + +static GLuint APIENTRY InitBindTextureUnitParameterEXT (GLenum unit, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindTextureUnitParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindTextureUnitParameterEXT = extproc; + + return glBindTextureUnitParameterEXT(unit, value); +} + +static GLuint APIENTRY InitBindParameterEXT (GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindParameterEXT = extproc; + + return glBindParameterEXT(value); +} + +static GLboolean APIENTRY InitIsVariantEnabledEXT (GLuint id, GLenum cap) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsVariantEnabledEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsVariantEnabledEXT = extproc; + + return glIsVariantEnabledEXT(id, cap); +} + +static void APIENTRY InitGetVariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantBooleanvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantBooleanvEXT = extproc; + + glGetVariantBooleanvEXT(id, value, data); +} + +static void APIENTRY InitGetVariantIntegervEXT (GLuint id, GLenum value, GLint *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantIntegervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantIntegervEXT = extproc; + + glGetVariantIntegervEXT(id, value, data); +} + +static void APIENTRY InitGetVariantFloatvEXT (GLuint id, GLenum value, GLfloat *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantFloatvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantFloatvEXT = extproc; + + glGetVariantFloatvEXT(id, value, data); +} + +static void APIENTRY InitGetVariantPointervEXT (GLuint id, GLenum value, GLvoid* *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantPointervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantPointervEXT = extproc; + + glGetVariantPointervEXT(id, value, data); +} + +static void APIENTRY InitGetInvariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInvariantBooleanvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInvariantBooleanvEXT = extproc; + + glGetInvariantBooleanvEXT(id, value, data); +} + +static void APIENTRY InitGetInvariantIntegervEXT (GLuint id, GLenum value, GLint *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInvariantIntegervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInvariantIntegervEXT = extproc; + + glGetInvariantIntegervEXT(id, value, data); +} + +static void APIENTRY InitGetInvariantFloatvEXT (GLuint id, GLenum value, GLfloat *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInvariantFloatvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInvariantFloatvEXT = extproc; + + glGetInvariantFloatvEXT(id, value, data); +} + +static void APIENTRY InitGetLocalConstantBooleanvEXT (GLuint id, GLenum value, GLboolean *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetLocalConstantBooleanvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetLocalConstantBooleanvEXT = extproc; + + glGetLocalConstantBooleanvEXT(id, value, data); +} + +static void APIENTRY InitGetLocalConstantIntegervEXT (GLuint id, GLenum value, GLint *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetLocalConstantIntegervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetLocalConstantIntegervEXT = extproc; + + glGetLocalConstantIntegervEXT(id, value, data); +} + +static void APIENTRY InitGetLocalConstantFloatvEXT (GLuint id, GLenum value, GLfloat *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetLocalConstantFloatvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetLocalConstantFloatvEXT = extproc; + + glGetLocalConstantFloatvEXT(id, value, data); +} + +static void APIENTRY InitVertexStream1sATI (GLenum stream, GLshort x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1sATI = extproc; + + glVertexStream1sATI(stream, x); +} + +static void APIENTRY InitVertexStream1svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1svATI = extproc; + + glVertexStream1svATI(stream, coords); +} + +static void APIENTRY InitVertexStream1iATI (GLenum stream, GLint x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1iATI = extproc; + + glVertexStream1iATI(stream, x); +} + +static void APIENTRY InitVertexStream1ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1ivATI = extproc; + + glVertexStream1ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream1fATI (GLenum stream, GLfloat x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1fATI = extproc; + + glVertexStream1fATI(stream, x); +} + +static void APIENTRY InitVertexStream1fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1fvATI = extproc; + + glVertexStream1fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream1dATI (GLenum stream, GLdouble x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1dATI = extproc; + + glVertexStream1dATI(stream, x); +} + +static void APIENTRY InitVertexStream1dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1dvATI = extproc; + + glVertexStream1dvATI(stream, coords); +} + +static void APIENTRY InitVertexStream2sATI (GLenum stream, GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2sATI = extproc; + + glVertexStream2sATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2svATI = extproc; + + glVertexStream2svATI(stream, coords); +} + +static void APIENTRY InitVertexStream2iATI (GLenum stream, GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2iATI = extproc; + + glVertexStream2iATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2ivATI = extproc; + + glVertexStream2ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream2fATI (GLenum stream, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2fATI = extproc; + + glVertexStream2fATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2fvATI = extproc; + + glVertexStream2fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream2dATI (GLenum stream, GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2dATI = extproc; + + glVertexStream2dATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2dvATI = extproc; + + glVertexStream2dvATI(stream, coords); +} + +static void APIENTRY InitVertexStream3sATI (GLenum stream, GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3sATI = extproc; + + glVertexStream3sATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3svATI = extproc; + + glVertexStream3svATI(stream, coords); +} + +static void APIENTRY InitVertexStream3iATI (GLenum stream, GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3iATI = extproc; + + glVertexStream3iATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3ivATI = extproc; + + glVertexStream3ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream3fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3fATI = extproc; + + glVertexStream3fATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3fvATI = extproc; + + glVertexStream3fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream3dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3dATI = extproc; + + glVertexStream3dATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3dvATI = extproc; + + glVertexStream3dvATI(stream, coords); +} + +static void APIENTRY InitVertexStream4sATI (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4sATI = extproc; + + glVertexStream4sATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4svATI = extproc; + + glVertexStream4svATI(stream, coords); +} + +static void APIENTRY InitVertexStream4iATI (GLenum stream, GLint x, GLint y, GLint z, GLint w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4iATI = extproc; + + glVertexStream4iATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4ivATI = extproc; + + glVertexStream4ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream4fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4fATI = extproc; + + glVertexStream4fATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4fvATI = extproc; + + glVertexStream4fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream4dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4dATI = extproc; + + glVertexStream4dATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4dvATI = extproc; + + glVertexStream4dvATI(stream, coords); +} + +static void APIENTRY InitNormalStream3bATI (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3bATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3bATI = extproc; + + glNormalStream3bATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3bvATI (GLenum stream, const GLbyte *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3bvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3bvATI = extproc; + + glNormalStream3bvATI(stream, coords); +} + +static void APIENTRY InitNormalStream3sATI (GLenum stream, GLshort nx, GLshort ny, GLshort nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3sATI = extproc; + + glNormalStream3sATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3svATI = extproc; + + glNormalStream3svATI(stream, coords); +} + +static void APIENTRY InitNormalStream3iATI (GLenum stream, GLint nx, GLint ny, GLint nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3iATI = extproc; + + glNormalStream3iATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3ivATI = extproc; + + glNormalStream3ivATI(stream, coords); +} + +static void APIENTRY InitNormalStream3fATI (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3fATI = extproc; + + glNormalStream3fATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3fvATI = extproc; + + glNormalStream3fvATI(stream, coords); +} + +static void APIENTRY InitNormalStream3dATI (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3dATI = extproc; + + glNormalStream3dATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3dvATI = extproc; + + glNormalStream3dvATI(stream, coords); +} + +static void APIENTRY InitClientActiveVertexStreamATI (GLenum stream) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glClientActiveVertexStreamATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glClientActiveVertexStreamATI = extproc; + + glClientActiveVertexStreamATI(stream); +} + +static void APIENTRY InitVertexBlendEnviATI (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexBlendEnviATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexBlendEnviATI = extproc; + + glVertexBlendEnviATI(pname, param); +} + +static void APIENTRY InitVertexBlendEnvfATI (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexBlendEnvfATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexBlendEnvfATI = extproc; + + glVertexBlendEnvfATI(pname, param); +} + +static void APIENTRY InitElementPointerATI (GLenum type, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glElementPointerATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glElementPointerATI = extproc; + + glElementPointerATI(type, pointer); +} + +static void APIENTRY InitDrawElementArrayATI (GLenum mode, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawElementArrayATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawElementArrayATI = extproc; + + glDrawElementArrayATI(mode, count); +} + +static void APIENTRY InitDrawRangeElementArrayATI (GLenum mode, GLuint start, GLuint end, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElementArrayATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElementArrayATI = extproc; + + glDrawRangeElementArrayATI(mode, start, end, count); +} + +static void APIENTRY InitDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawMeshArraysSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawMeshArraysSUN = extproc; + + glDrawMeshArraysSUN(mode, first, count, width); +} + +static void APIENTRY InitGenOcclusionQueriesNV (GLsizei n, GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenOcclusionQueriesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenOcclusionQueriesNV = extproc; + + glGenOcclusionQueriesNV(n, ids); +} + +static void APIENTRY InitDeleteOcclusionQueriesNV (GLsizei n, const GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteOcclusionQueriesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteOcclusionQueriesNV = extproc; + + glDeleteOcclusionQueriesNV(n, ids); +} + +static GLboolean APIENTRY InitIsOcclusionQueryNV (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsOcclusionQueryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsOcclusionQueryNV = extproc; + + return glIsOcclusionQueryNV(id); +} + +static void APIENTRY InitBeginOcclusionQueryNV (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginOcclusionQueryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginOcclusionQueryNV = extproc; + + glBeginOcclusionQueryNV(id); +} + +static void APIENTRY InitEndOcclusionQueryNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndOcclusionQueryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndOcclusionQueryNV = extproc; + + glEndOcclusionQueryNV(); +} + +static void APIENTRY InitGetOcclusionQueryivNV (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetOcclusionQueryivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetOcclusionQueryivNV = extproc; + + glGetOcclusionQueryivNV(id, pname, params); +} + +static void APIENTRY InitGetOcclusionQueryuivNV (GLuint id, GLenum pname, GLuint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetOcclusionQueryuivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetOcclusionQueryuivNV = extproc; + + glGetOcclusionQueryuivNV(id, pname, params); +} + +static void APIENTRY InitPointParameteriNV (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameteriNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameteriNV = extproc; + + glPointParameteriNV(pname, param); +} + +static void APIENTRY InitPointParameterivNV (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterivNV = extproc; + + glPointParameterivNV(pname, params); +} + +static void APIENTRY InitActiveStencilFaceEXT (GLenum face) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glActiveStencilFaceEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glActiveStencilFaceEXT = extproc; + + glActiveStencilFaceEXT(face); +} + +static void APIENTRY InitElementPointerAPPLE (GLenum type, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glElementPointerAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glElementPointerAPPLE = extproc; + + glElementPointerAPPLE(type, pointer); +} + +static void APIENTRY InitDrawElementArrayAPPLE (GLenum mode, GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawElementArrayAPPLE = extproc; + + glDrawElementArrayAPPLE(mode, first, count); +} + +static void APIENTRY InitDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElementArrayAPPLE = extproc; + + glDrawRangeElementArrayAPPLE(mode, start, end, first, count); +} + +static void APIENTRY InitMultiDrawElementArrayAPPLE (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawElementArrayAPPLE = extproc; + + glMultiDrawElementArrayAPPLE(mode, first, count, primcount); +} + +static void APIENTRY InitMultiDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawRangeElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawRangeElementArrayAPPLE = extproc; + + glMultiDrawRangeElementArrayAPPLE(mode, start, end, first, count, primcount); +} + +static void APIENTRY InitGenFencesAPPLE (GLsizei n, GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenFencesAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenFencesAPPLE = extproc; + + glGenFencesAPPLE(n, fences); +} + +static void APIENTRY InitDeleteFencesAPPLE (GLsizei n, const GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteFencesAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteFencesAPPLE = extproc; + + glDeleteFencesAPPLE(n, fences); +} + +static void APIENTRY InitSetFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetFenceAPPLE = extproc; + + glSetFenceAPPLE(fence); +} + +static GLboolean APIENTRY InitIsFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsFenceAPPLE = extproc; + + return glIsFenceAPPLE(fence); +} + +static GLboolean APIENTRY InitTestFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTestFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glTestFenceAPPLE = extproc; + + return glTestFenceAPPLE(fence); +} + +static void APIENTRY InitFinishFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishFenceAPPLE = extproc; + + glFinishFenceAPPLE(fence); +} + +static GLboolean APIENTRY InitTestObjectAPPLE (GLenum object, GLuint name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTestObjectAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glTestObjectAPPLE = extproc; + + return glTestObjectAPPLE(object, name); +} + +static void APIENTRY InitFinishObjectAPPLE (GLenum object, GLint name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishObjectAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishObjectAPPLE = extproc; + + glFinishObjectAPPLE(object, name); +} + +static void APIENTRY InitBindVertexArrayAPPLE (GLuint array) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindVertexArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindVertexArrayAPPLE = extproc; + + glBindVertexArrayAPPLE(array); +} + +static void APIENTRY InitDeleteVertexArraysAPPLE (GLsizei n, const GLuint *arrays) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteVertexArraysAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteVertexArraysAPPLE = extproc; + + glDeleteVertexArraysAPPLE(n, arrays); +} + +static void APIENTRY InitGenVertexArraysAPPLE (GLsizei n, const GLuint *arrays) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenVertexArraysAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenVertexArraysAPPLE = extproc; + + glGenVertexArraysAPPLE(n, arrays); +} + +static GLboolean APIENTRY InitIsVertexArrayAPPLE (GLuint array) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsVertexArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsVertexArrayAPPLE = extproc; + + return glIsVertexArrayAPPLE(array); +} + +static void APIENTRY InitVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexArrayRangeAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexArrayRangeAPPLE = extproc; + + glVertexArrayRangeAPPLE(length, pointer); +} + +static void APIENTRY InitFlushVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushVertexArrayRangeAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushVertexArrayRangeAPPLE = extproc; + + glFlushVertexArrayRangeAPPLE(length, pointer); +} + +static void APIENTRY InitVertexArrayParameteriAPPLE (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexArrayParameteriAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexArrayParameteriAPPLE = extproc; + + glVertexArrayParameteriAPPLE(pname, param); +} + +static void APIENTRY InitDrawBuffersATI (GLsizei n, const GLenum *bufs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawBuffersATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawBuffersATI = extproc; + + glDrawBuffersATI(n, bufs); +} + +static void APIENTRY InitProgramNamedParameter4fNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4fNV = extproc; + + glProgramNamedParameter4fNV(id, len, name, x, y, z, w); +} + +static void APIENTRY InitProgramNamedParameter4dNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4dNV = extproc; + + glProgramNamedParameter4dNV(id, len, name, x, y, z, w); +} + +static void APIENTRY InitProgramNamedParameter4fvNV (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4fvNV = extproc; + + glProgramNamedParameter4fvNV(id, len, name, v); +} + +static void APIENTRY InitProgramNamedParameter4dvNV (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4dvNV = extproc; + + glProgramNamedParameter4dvNV(id, len, name, v); +} + +static void APIENTRY InitGetProgramNamedParameterfvNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramNamedParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramNamedParameterfvNV = extproc; + + glGetProgramNamedParameterfvNV(id, len, name, params); +} + +static void APIENTRY InitGetProgramNamedParameterdvNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramNamedParameterdvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramNamedParameterdvNV = extproc; + + glGetProgramNamedParameterdvNV(id, len, name, params); +} + +static void APIENTRY InitVertex2hNV (GLhalfNV x, GLhalfNV y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex2hNV = extproc; + + glVertex2hNV(x, y); +} + +static void APIENTRY InitVertex2hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex2hvNV = extproc; + + glVertex2hvNV(v); +} + +static void APIENTRY InitVertex3hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex3hNV = extproc; + + glVertex3hNV(x, y, z); +} + +static void APIENTRY InitVertex3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex3hvNV = extproc; + + glVertex3hvNV(v); +} + +static void APIENTRY InitVertex4hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex4hNV = extproc; + + glVertex4hNV(x, y, z, w); +} + +static void APIENTRY InitVertex4hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex4hvNV = extproc; + + glVertex4hvNV(v); +} + +static void APIENTRY InitNormal3hNV (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3hNV = extproc; + + glNormal3hNV(nx, ny, nz); +} + +static void APIENTRY InitNormal3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3hvNV = extproc; + + glNormal3hvNV(v); +} + +static void APIENTRY InitColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3hNV = extproc; + + glColor3hNV(red, green, blue); +} + +static void APIENTRY InitColor3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3hvNV = extproc; + + glColor3hvNV(v); +} + +static void APIENTRY InitColor4hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4hNV = extproc; + + glColor4hNV(red, green, blue, alpha); +} + +static void APIENTRY InitColor4hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4hvNV = extproc; + + glColor4hvNV(v); +} + +static void APIENTRY InitTexCoord1hNV (GLhalfNV s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord1hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord1hNV = extproc; + + glTexCoord1hNV(s); +} + +static void APIENTRY InitTexCoord1hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord1hvNV = extproc; + + glTexCoord1hvNV(v); +} + +static void APIENTRY InitTexCoord2hNV (GLhalfNV s, GLhalfNV t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2hNV = extproc; + + glTexCoord2hNV(s, t); +} + +static void APIENTRY InitTexCoord2hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2hvNV = extproc; + + glTexCoord2hvNV(v); +} + +static void APIENTRY InitTexCoord3hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord3hNV = extproc; + + glTexCoord3hNV(s, t, r); +} + +static void APIENTRY InitTexCoord3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord3hvNV = extproc; + + glTexCoord3hvNV(v); +} + +static void APIENTRY InitTexCoord4hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4hNV = extproc; + + glTexCoord4hNV(s, t, r, q); +} + +static void APIENTRY InitTexCoord4hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4hvNV = extproc; + + glTexCoord4hvNV(v); +} + +static void APIENTRY InitMultiTexCoord1hNV (GLenum target, GLhalfNV s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1hNV = extproc; + + glMultiTexCoord1hNV(target, s); +} + +static void APIENTRY InitMultiTexCoord1hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1hvNV = extproc; + + glMultiTexCoord1hvNV(target, v); +} + +static void APIENTRY InitMultiTexCoord2hNV (GLenum target, GLhalfNV s, GLhalfNV t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2hNV = extproc; + + glMultiTexCoord2hNV(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2hvNV = extproc; + + glMultiTexCoord2hvNV(target, v); +} + +static void APIENTRY InitMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3hNV = extproc; + + glMultiTexCoord3hNV(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3hvNV = extproc; + + glMultiTexCoord3hvNV(target, v); +} + +static void APIENTRY InitMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4hNV = extproc; + + glMultiTexCoord4hNV(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4hvNV = extproc; + + glMultiTexCoord4hvNV(target, v); +} + +static void APIENTRY InitFogCoordhNV (GLhalfNV fog) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordhNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordhNV = extproc; + + glFogCoordhNV(fog); +} + +static void APIENTRY InitFogCoordhvNV (const GLhalfNV *fog) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordhvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordhvNV = extproc; + + glFogCoordhvNV(fog); +} + +static void APIENTRY InitSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3hNV = extproc; + + glSecondaryColor3hNV(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3hvNV = extproc; + + glSecondaryColor3hvNV(v); +} + +static void APIENTRY InitVertexWeighthNV (GLhalfNV weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeighthNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeighthNV = extproc; + + glVertexWeighthNV(weight); +} + +static void APIENTRY InitVertexWeighthvNV (const GLhalfNV *weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeighthvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeighthvNV = extproc; + + glVertexWeighthvNV(weight); +} + +static void APIENTRY InitVertexAttrib1hNV (GLuint index, GLhalfNV x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1hNV = extproc; + + glVertexAttrib1hNV(index, x); +} + +static void APIENTRY InitVertexAttrib1hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1hvNV = extproc; + + glVertexAttrib1hvNV(index, v); +} + +static void APIENTRY InitVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2hNV = extproc; + + glVertexAttrib2hNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2hvNV = extproc; + + glVertexAttrib2hvNV(index, v); +} + +static void APIENTRY InitVertexAttrib3hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3hNV = extproc; + + glVertexAttrib3hNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3hvNV = extproc; + + glVertexAttrib3hvNV(index, v); +} + +static void APIENTRY InitVertexAttrib4hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4hNV = extproc; + + glVertexAttrib4hNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4hvNV = extproc; + + glVertexAttrib4hvNV(index, v); +} + +static void APIENTRY InitVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1hvNV = extproc; + + glVertexAttribs1hvNV(index, n, v); +} + +static void APIENTRY InitVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2hvNV = extproc; + + glVertexAttribs2hvNV(index, n, v); +} + +static void APIENTRY InitVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3hvNV = extproc; + + glVertexAttribs3hvNV(index, n, v); +} + +static void APIENTRY InitVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4hvNV = extproc; + + glVertexAttribs4hvNV(index, n, v); +} + +static void APIENTRY InitPixelDataRangeNV (GLenum target, GLsizei length, GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelDataRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelDataRangeNV = extproc; + + glPixelDataRangeNV(target, length, pointer); +} + +static void APIENTRY InitFlushPixelDataRangeNV (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushPixelDataRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushPixelDataRangeNV = extproc; + + glFlushPixelDataRangeNV(target); +} + +static void APIENTRY InitPrimitiveRestartNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPrimitiveRestartNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPrimitiveRestartNV = extproc; + + glPrimitiveRestartNV(); +} + +static void APIENTRY InitPrimitiveRestartIndexNV (GLuint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPrimitiveRestartIndexNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPrimitiveRestartIndexNV = extproc; + + glPrimitiveRestartIndexNV(index); +} + +static GLvoid* APIENTRY InitMapObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glMapObjectBufferATI = extproc; + + return glMapObjectBufferATI(buffer); +} + +static void APIENTRY InitUnmapObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnmapObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUnmapObjectBufferATI = extproc; + + glUnmapObjectBufferATI(buffer); +} + +static void APIENTRY InitStencilOpSeparateATI (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStencilOpSeparateATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStencilOpSeparateATI = extproc; + + glStencilOpSeparateATI(face, sfail, dpfail, dppass); +} + +static void APIENTRY InitStencilFuncSeparateATI (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStencilFuncSeparateATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStencilFuncSeparateATI = extproc; + + glStencilFuncSeparateATI(frontfunc, backfunc, ref, mask); +} + +static void APIENTRY InitVertexAttribArrayObjectATI (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribArrayObjectATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribArrayObjectATI = extproc; + + glVertexAttribArrayObjectATI(index, size, type, normalized, stride, buffer, offset); +} + +static void APIENTRY InitGetVertexAttribArrayObjectfvATI (GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribArrayObjectfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribArrayObjectfvATI = extproc; + + glGetVertexAttribArrayObjectfvATI(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribArrayObjectivATI (GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribArrayObjectivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribArrayObjectivATI = extproc; + + glGetVertexAttribArrayObjectivATI(index, pname, params); +} + +static void APIENTRY InitDepthBoundsEXT (GLclampd zmin, GLclampd zmax) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDepthBoundsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDepthBoundsEXT = extproc; + + glDepthBoundsEXT(zmin, zmax); +} + +static void APIENTRY InitBlendEquationSeparateEXT (GLenum modeRGB, GLenum modeAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendEquationSeparateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendEquationSeparateEXT = extproc; + + glBlendEquationSeparateEXT(modeRGB, modeAlpha); +} + +static void APIENTRY InitAddSwapHintRectWIN (GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAddSwapHintRectWIN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAddSwapHintRectWIN = extproc; + + glAddSwapHintRectWIN(x, y, width, height); +} + +#ifdef _WIN32 + +static HANDLE WINAPI InitCreateBufferRegionARB (HDC hDC, int iLayerPlane, UINT uType) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreateBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreateBufferRegionARB = extproc; + + return wglCreateBufferRegionARB(hDC, iLayerPlane, uType); +} + +static VOID WINAPI InitDeleteBufferRegionARB (HANDLE hRegion) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDeleteBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + wglDeleteBufferRegionARB = extproc; + + wglDeleteBufferRegionARB(hRegion); +} + +static BOOL WINAPI InitSaveBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSaveBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSaveBufferRegionARB = extproc; + + return wglSaveBufferRegionARB(hRegion, x, y, width, height); +} + +static BOOL WINAPI InitRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglRestoreBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglRestoreBufferRegionARB = extproc; + + return wglRestoreBufferRegionARB(hRegion, x, y, width, height, xSrc, ySrc); +} + +static const WINAPI InitGetExtensionsStringARB (HDC hdc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetExtensionsStringARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetExtensionsStringARB = extproc; + + return wglGetExtensionsStringARB(hdc); +} + +static BOOL WINAPI InitGetPixelFormatAttribivARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribivARB = extproc; + + return wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); +} + +static BOOL WINAPI InitGetPixelFormatAttribfvARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribfvARB = extproc; + + return wglGetPixelFormatAttribfvARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues); +} + +static BOOL WINAPI InitChoosePixelFormatARB (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglChoosePixelFormatARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglChoosePixelFormatARB = extproc; + + return wglChoosePixelFormatARB(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); +} + +static BOOL WINAPI InitMakeContextCurrentARB (HDC hDrawDC, HDC hReadDC, HGLRC hglrc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglMakeContextCurrentARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglMakeContextCurrentARB = extproc; + + return wglMakeContextCurrentARB(hDrawDC, hReadDC, hglrc); +} + +static HDC WINAPI InitGetCurrentReadDCARB (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetCurrentReadDCARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetCurrentReadDCARB = extproc; + + return wglGetCurrentReadDCARB(); +} + +static HPBUFFERARB WINAPI InitCreatePbufferARB (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreatePbufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreatePbufferARB = extproc; + + return wglCreatePbufferARB(hDC, iPixelFormat, iWidth, iHeight, piAttribList); +} + +static HDC WINAPI InitGetPbufferDCARB (HPBUFFERARB hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPbufferDCARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPbufferDCARB = extproc; + + return wglGetPbufferDCARB(hPbuffer); +} + +static int WINAPI InitReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleasePbufferDCARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleasePbufferDCARB = extproc; + + return wglReleasePbufferDCARB(hPbuffer, hDC); +} + +static BOOL WINAPI InitDestroyPbufferARB (HPBUFFERARB hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyPbufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDestroyPbufferARB = extproc; + + return wglDestroyPbufferARB(hPbuffer); +} + +static BOOL WINAPI InitQueryPbufferARB (HPBUFFERARB hPbuffer, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryPbufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryPbufferARB = extproc; + + return wglQueryPbufferARB(hPbuffer, iAttribute, piValue); +} + +static BOOL WINAPI InitBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglBindTexImageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglBindTexImageARB = extproc; + + return wglBindTexImageARB(hPbuffer, iBuffer); +} + +static BOOL WINAPI InitReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleaseTexImageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleaseTexImageARB = extproc; + + return wglReleaseTexImageARB(hPbuffer, iBuffer); +} + +static BOOL WINAPI InitSetPbufferAttribARB (HPBUFFERARB hPbuffer, const int *piAttribList) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetPbufferAttribARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetPbufferAttribARB = extproc; + + return wglSetPbufferAttribARB(hPbuffer, piAttribList); +} + +static GLboolean WINAPI InitCreateDisplayColorTableEXT (GLushort id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreateDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreateDisplayColorTableEXT = extproc; + + return wglCreateDisplayColorTableEXT(id); +} + +static GLboolean WINAPI InitLoadDisplayColorTableEXT (const GLushort *table, GLuint length) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglLoadDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglLoadDisplayColorTableEXT = extproc; + + return wglLoadDisplayColorTableEXT(table, length); +} + +static GLboolean WINAPI InitBindDisplayColorTableEXT (GLushort id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglBindDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglBindDisplayColorTableEXT = extproc; + + return wglBindDisplayColorTableEXT(id); +} + +static VOID WINAPI InitDestroyDisplayColorTableEXT (GLushort id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + wglDestroyDisplayColorTableEXT = extproc; + + wglDestroyDisplayColorTableEXT(id); +} + +static const WINAPI InitGetExtensionsStringEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetExtensionsStringEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetExtensionsStringEXT = extproc; + + return wglGetExtensionsStringEXT(); +} + +static BOOL WINAPI InitMakeContextCurrentEXT (HDC hDrawDC, HDC hReadDC, HGLRC hglrc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglMakeContextCurrentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglMakeContextCurrentEXT = extproc; + + return wglMakeContextCurrentEXT(hDrawDC, hReadDC, hglrc); +} + +static HDC WINAPI InitGetCurrentReadDCEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetCurrentReadDCEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetCurrentReadDCEXT = extproc; + + return wglGetCurrentReadDCEXT(); +} + +static HPBUFFEREXT WINAPI InitCreatePbufferEXT (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreatePbufferEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreatePbufferEXT = extproc; + + return wglCreatePbufferEXT(hDC, iPixelFormat, iWidth, iHeight, piAttribList); +} + +static HDC WINAPI InitGetPbufferDCEXT (HPBUFFEREXT hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPbufferDCEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPbufferDCEXT = extproc; + + return wglGetPbufferDCEXT(hPbuffer); +} + +static int WINAPI InitReleasePbufferDCEXT (HPBUFFEREXT hPbuffer, HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleasePbufferDCEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleasePbufferDCEXT = extproc; + + return wglReleasePbufferDCEXT(hPbuffer, hDC); +} + +static BOOL WINAPI InitDestroyPbufferEXT (HPBUFFEREXT hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyPbufferEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDestroyPbufferEXT = extproc; + + return wglDestroyPbufferEXT(hPbuffer); +} + +static BOOL WINAPI InitQueryPbufferEXT (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryPbufferEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryPbufferEXT = extproc; + + return wglQueryPbufferEXT(hPbuffer, iAttribute, piValue); +} + +static BOOL WINAPI InitGetPixelFormatAttribivEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribivEXT = extproc; + + return wglGetPixelFormatAttribivEXT(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); +} + +static BOOL WINAPI InitGetPixelFormatAttribfvEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribfvEXT = extproc; + + return wglGetPixelFormatAttribfvEXT(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues); +} + +static BOOL WINAPI InitChoosePixelFormatEXT (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglChoosePixelFormatEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglChoosePixelFormatEXT = extproc; + + return wglChoosePixelFormatEXT(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); +} + +static BOOL WINAPI InitSwapIntervalEXT (int interval) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSwapIntervalEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSwapIntervalEXT = extproc; + + return wglSwapIntervalEXT(interval); +} + +static int WINAPI InitGetSwapIntervalEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetSwapIntervalEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetSwapIntervalEXT = extproc; + + return wglGetSwapIntervalEXT(); +} + +static void* WINAPI InitAllocateMemoryNV (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglAllocateMemoryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglAllocateMemoryNV = extproc; + + return wglAllocateMemoryNV(size, readfreq, writefreq, priority); +} + +static void WINAPI InitFreeMemoryNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglFreeMemoryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + wglFreeMemoryNV = extproc; + + wglFreeMemoryNV(); +} + +static BOOL WINAPI InitGetSyncValuesOML (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetSyncValuesOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetSyncValuesOML = extproc; + + return wglGetSyncValuesOML(hdc, ust, msc, sbc); +} + +static BOOL WINAPI InitGetMscRateOML (HDC hdc, INT32 *numerator, INT32 *denominator) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetMscRateOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetMscRateOML = extproc; + + return wglGetMscRateOML(hdc, numerator, denominator); +} + +static INT64 WINAPI InitSwapBuffersMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSwapBuffersMscOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSwapBuffersMscOML = extproc; + + return wglSwapBuffersMscOML(hdc, target_msc, divisor, remainder); +} + +static INT64 WINAPI InitSwapLayerBuffersMscOML (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSwapLayerBuffersMscOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSwapLayerBuffersMscOML = extproc; + + return wglSwapLayerBuffersMscOML(hdc, fuPlanes, target_msc, divisor, remainder); +} + +static BOOL WINAPI InitWaitForMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglWaitForMscOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglWaitForMscOML = extproc; + + return wglWaitForMscOML(hdc, target_msc, divisor, remainder, ust, msc, sbc); +} + +static BOOL WINAPI InitWaitForSbcOML (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglWaitForSbcOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglWaitForSbcOML = extproc; + + return wglWaitForSbcOML(hdc, target_sbc, ust, msc, sbc); +} + +static BOOL WINAPI InitGetDigitalVideoParametersI3D (HDC hDC, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetDigitalVideoParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetDigitalVideoParametersI3D = extproc; + + return wglGetDigitalVideoParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitSetDigitalVideoParametersI3D (HDC hDC, int iAttribute, const int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetDigitalVideoParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetDigitalVideoParametersI3D = extproc; + + return wglSetDigitalVideoParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitGetGammaTableParametersI3D (HDC hDC, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGammaTableParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGammaTableParametersI3D = extproc; + + return wglGetGammaTableParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitSetGammaTableParametersI3D (HDC hDC, int iAttribute, const int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetGammaTableParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetGammaTableParametersI3D = extproc; + + return wglSetGammaTableParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitGetGammaTableI3D (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGammaTableI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGammaTableI3D = extproc; + + return wglGetGammaTableI3D(hDC, iEntries, puRed, puGreen, puBlue); +} + +static BOOL WINAPI InitSetGammaTableI3D (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetGammaTableI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetGammaTableI3D = extproc; + + return wglSetGammaTableI3D(hDC, iEntries, puRed, puGreen, puBlue); +} + +static BOOL WINAPI InitEnableGenlockI3D (HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglEnableGenlockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglEnableGenlockI3D = extproc; + + return wglEnableGenlockI3D(hDC); +} + +static BOOL WINAPI InitDisableGenlockI3D (HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDisableGenlockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDisableGenlockI3D = extproc; + + return wglDisableGenlockI3D(hDC); +} + +static BOOL WINAPI InitIsEnabledGenlockI3D (HDC hDC, BOOL *pFlag) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglIsEnabledGenlockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglIsEnabledGenlockI3D = extproc; + + return wglIsEnabledGenlockI3D(hDC, pFlag); +} + +static BOOL WINAPI InitGenlockSourceI3D (HDC hDC, UINT uSource) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSourceI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSourceI3D = extproc; + + return wglGenlockSourceI3D(hDC, uSource); +} + +static BOOL WINAPI InitGetGenlockSourceI3D (HDC hDC, UINT *uSource) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSourceI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSourceI3D = extproc; + + return wglGetGenlockSourceI3D(hDC, uSource); +} + +static BOOL WINAPI InitGenlockSourceEdgeI3D (HDC hDC, UINT uEdge) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSourceEdgeI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSourceEdgeI3D = extproc; + + return wglGenlockSourceEdgeI3D(hDC, uEdge); +} + +static BOOL WINAPI InitGetGenlockSourceEdgeI3D (HDC hDC, UINT *uEdge) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSourceEdgeI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSourceEdgeI3D = extproc; + + return wglGetGenlockSourceEdgeI3D(hDC, uEdge); +} + +static BOOL WINAPI InitGenlockSampleRateI3D (HDC hDC, UINT uRate) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSampleRateI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSampleRateI3D = extproc; + + return wglGenlockSampleRateI3D(hDC, uRate); +} + +static BOOL WINAPI InitGetGenlockSampleRateI3D (HDC hDC, UINT *uRate) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSampleRateI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSampleRateI3D = extproc; + + return wglGetGenlockSampleRateI3D(hDC, uRate); +} + +static BOOL WINAPI InitGenlockSourceDelayI3D (HDC hDC, UINT uDelay) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSourceDelayI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSourceDelayI3D = extproc; + + return wglGenlockSourceDelayI3D(hDC, uDelay); +} + +static BOOL WINAPI InitGetGenlockSourceDelayI3D (HDC hDC, UINT *uDelay) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSourceDelayI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSourceDelayI3D = extproc; + + return wglGetGenlockSourceDelayI3D(hDC, uDelay); +} + +static BOOL WINAPI InitQueryGenlockMaxSourceDelayI3D (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryGenlockMaxSourceDelayI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryGenlockMaxSourceDelayI3D = extproc; + + return wglQueryGenlockMaxSourceDelayI3D(hDC, uMaxLineDelay, uMaxPixelDelay); +} + +static LPVOID WINAPI InitCreateImageBufferI3D (HDC hDC, DWORD dwSize, UINT uFlags) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreateImageBufferI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreateImageBufferI3D = extproc; + + return wglCreateImageBufferI3D(hDC, dwSize, uFlags); +} + +static BOOL WINAPI InitDestroyImageBufferI3D (HDC hDC, LPVOID pAddress) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyImageBufferI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDestroyImageBufferI3D = extproc; + + return wglDestroyImageBufferI3D(hDC, pAddress); +} + +static BOOL WINAPI InitAssociateImageBufferEventsI3D (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglAssociateImageBufferEventsI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglAssociateImageBufferEventsI3D = extproc; + + return wglAssociateImageBufferEventsI3D(hDC, pEvent, pAddress, pSize, count); +} + +static BOOL WINAPI InitReleaseImageBufferEventsI3D (HDC hDC, const LPVOID *pAddress, UINT count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleaseImageBufferEventsI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleaseImageBufferEventsI3D = extproc; + + return wglReleaseImageBufferEventsI3D(hDC, pAddress, count); +} + +static BOOL WINAPI InitEnableFrameLockI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglEnableFrameLockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglEnableFrameLockI3D = extproc; + + return wglEnableFrameLockI3D(); +} + +static BOOL WINAPI InitDisableFrameLockI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDisableFrameLockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDisableFrameLockI3D = extproc; + + return wglDisableFrameLockI3D(); +} + +static BOOL WINAPI InitIsEnabledFrameLockI3D (BOOL *pFlag) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglIsEnabledFrameLockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglIsEnabledFrameLockI3D = extproc; + + return wglIsEnabledFrameLockI3D(pFlag); +} + +static BOOL WINAPI InitQueryFrameLockMasterI3D (BOOL *pFlag) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryFrameLockMasterI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryFrameLockMasterI3D = extproc; + + return wglQueryFrameLockMasterI3D(pFlag); +} + +static BOOL WINAPI InitGetFrameUsageI3D (float *pUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetFrameUsageI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetFrameUsageI3D = extproc; + + return wglGetFrameUsageI3D(pUsage); +} + +static BOOL WINAPI InitBeginFrameTrackingI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglBeginFrameTrackingI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglBeginFrameTrackingI3D = extproc; + + return wglBeginFrameTrackingI3D(); +} + +static BOOL WINAPI InitEndFrameTrackingI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglEndFrameTrackingI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglEndFrameTrackingI3D = extproc; + + return wglEndFrameTrackingI3D(); +} + +static BOOL WINAPI InitQueryFrameTrackingI3D (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryFrameTrackingI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryFrameTrackingI3D = extproc; + + return wglQueryFrameTrackingI3D(pFrameCount, pMissedFrames, pLastMissedUsage); +} + +#endif /* _WIN32 */ + +_GLextensionProcs _extensionProcs = { + InitBlendColor, + InitBlendEquation, + InitDrawRangeElements, + InitColorTable, + InitColorTableParameterfv, + InitColorTableParameteriv, + InitCopyColorTable, + InitGetColorTable, + InitGetColorTableParameterfv, + InitGetColorTableParameteriv, + InitColorSubTable, + InitCopyColorSubTable, + InitConvolutionFilter1D, + InitConvolutionFilter2D, + InitConvolutionParameterf, + InitConvolutionParameterfv, + InitConvolutionParameteri, + InitConvolutionParameteriv, + InitCopyConvolutionFilter1D, + InitCopyConvolutionFilter2D, + InitGetConvolutionFilter, + InitGetConvolutionParameterfv, + InitGetConvolutionParameteriv, + InitGetSeparableFilter, + InitSeparableFilter2D, + InitGetHistogram, + InitGetHistogramParameterfv, + InitGetHistogramParameteriv, + InitGetMinmax, + InitGetMinmaxParameterfv, + InitGetMinmaxParameteriv, + InitHistogram, + InitMinmax, + InitResetHistogram, + InitResetMinmax, + InitTexImage3D, + InitTexSubImage3D, + InitCopyTexSubImage3D, + InitActiveTexture, + InitClientActiveTexture, + InitMultiTexCoord1d, + InitMultiTexCoord1dv, + InitMultiTexCoord1f, + InitMultiTexCoord1fv, + InitMultiTexCoord1i, + InitMultiTexCoord1iv, + InitMultiTexCoord1s, + InitMultiTexCoord1sv, + InitMultiTexCoord2d, + InitMultiTexCoord2dv, + InitMultiTexCoord2f, + InitMultiTexCoord2fv, + InitMultiTexCoord2i, + InitMultiTexCoord2iv, + InitMultiTexCoord2s, + InitMultiTexCoord2sv, + InitMultiTexCoord3d, + InitMultiTexCoord3dv, + InitMultiTexCoord3f, + InitMultiTexCoord3fv, + InitMultiTexCoord3i, + InitMultiTexCoord3iv, + InitMultiTexCoord3s, + InitMultiTexCoord3sv, + InitMultiTexCoord4d, + InitMultiTexCoord4dv, + InitMultiTexCoord4f, + InitMultiTexCoord4fv, + InitMultiTexCoord4i, + InitMultiTexCoord4iv, + InitMultiTexCoord4s, + InitMultiTexCoord4sv, + InitLoadTransposeMatrixf, + InitLoadTransposeMatrixd, + InitMultTransposeMatrixf, + InitMultTransposeMatrixd, + InitSampleCoverage, + InitCompressedTexImage3D, + InitCompressedTexImage2D, + InitCompressedTexImage1D, + InitCompressedTexSubImage3D, + InitCompressedTexSubImage2D, + InitCompressedTexSubImage1D, + InitGetCompressedTexImage, + InitBlendFuncSeparate, + InitFogCoordf, + InitFogCoordfv, + InitFogCoordd, + InitFogCoorddv, + InitFogCoordPointer, + InitMultiDrawArrays, + InitMultiDrawElements, + InitPointParameterf, + InitPointParameterfv, + InitPointParameteri, + InitPointParameteriv, + InitSecondaryColor3b, + InitSecondaryColor3bv, + InitSecondaryColor3d, + InitSecondaryColor3dv, + InitSecondaryColor3f, + InitSecondaryColor3fv, + InitSecondaryColor3i, + InitSecondaryColor3iv, + InitSecondaryColor3s, + InitSecondaryColor3sv, + InitSecondaryColor3ub, + InitSecondaryColor3ubv, + InitSecondaryColor3ui, + InitSecondaryColor3uiv, + InitSecondaryColor3us, + InitSecondaryColor3usv, + InitSecondaryColorPointer, + InitWindowPos2d, + InitWindowPos2dv, + InitWindowPos2f, + InitWindowPos2fv, + InitWindowPos2i, + InitWindowPos2iv, + InitWindowPos2s, + InitWindowPos2sv, + InitWindowPos3d, + InitWindowPos3dv, + InitWindowPos3f, + InitWindowPos3fv, + InitWindowPos3i, + InitWindowPos3iv, + InitWindowPos3s, + InitWindowPos3sv, + InitGenQueries, + InitDeleteQueries, + InitIsQuery, + InitBeginQuery, + InitEndQuery, + InitGetQueryiv, + InitGetQueryObjectiv, + InitGetQueryObjectuiv, + InitBindBuffer, + InitDeleteBuffers, + InitGenBuffers, + InitIsBuffer, + InitBufferData, + InitBufferSubData, + InitGetBufferSubData, + InitMapBuffer, + InitUnmapBuffer, + InitGetBufferParameteriv, + InitGetBufferPointerv, + InitActiveTextureARB, + InitClientActiveTextureARB, + InitMultiTexCoord1dARB, + InitMultiTexCoord1dvARB, + InitMultiTexCoord1fARB, + InitMultiTexCoord1fvARB, + InitMultiTexCoord1iARB, + InitMultiTexCoord1ivARB, + InitMultiTexCoord1sARB, + InitMultiTexCoord1svARB, + InitMultiTexCoord2dARB, + InitMultiTexCoord2dvARB, + InitMultiTexCoord2fARB, + InitMultiTexCoord2fvARB, + InitMultiTexCoord2iARB, + InitMultiTexCoord2ivARB, + InitMultiTexCoord2sARB, + InitMultiTexCoord2svARB, + InitMultiTexCoord3dARB, + InitMultiTexCoord3dvARB, + InitMultiTexCoord3fARB, + InitMultiTexCoord3fvARB, + InitMultiTexCoord3iARB, + InitMultiTexCoord3ivARB, + InitMultiTexCoord3sARB, + InitMultiTexCoord3svARB, + InitMultiTexCoord4dARB, + InitMultiTexCoord4dvARB, + InitMultiTexCoord4fARB, + InitMultiTexCoord4fvARB, + InitMultiTexCoord4iARB, + InitMultiTexCoord4ivARB, + InitMultiTexCoord4sARB, + InitMultiTexCoord4svARB, + InitLoadTransposeMatrixfARB, + InitLoadTransposeMatrixdARB, + InitMultTransposeMatrixfARB, + InitMultTransposeMatrixdARB, + InitSampleCoverageARB, + InitCompressedTexImage3DARB, + InitCompressedTexImage2DARB, + InitCompressedTexImage1DARB, + InitCompressedTexSubImage3DARB, + InitCompressedTexSubImage2DARB, + InitCompressedTexSubImage1DARB, + InitGetCompressedTexImageARB, + InitPointParameterfARB, + InitPointParameterfvARB, + InitWeightbvARB, + InitWeightsvARB, + InitWeightivARB, + InitWeightfvARB, + InitWeightdvARB, + InitWeightubvARB, + InitWeightusvARB, + InitWeightuivARB, + InitWeightPointerARB, + InitVertexBlendARB, + InitCurrentPaletteMatrixARB, + InitMatrixIndexubvARB, + InitMatrixIndexusvARB, + InitMatrixIndexuivARB, + InitMatrixIndexPointerARB, + InitWindowPos2dARB, + InitWindowPos2dvARB, + InitWindowPos2fARB, + InitWindowPos2fvARB, + InitWindowPos2iARB, + InitWindowPos2ivARB, + InitWindowPos2sARB, + InitWindowPos2svARB, + InitWindowPos3dARB, + InitWindowPos3dvARB, + InitWindowPos3fARB, + InitWindowPos3fvARB, + InitWindowPos3iARB, + InitWindowPos3ivARB, + InitWindowPos3sARB, + InitWindowPos3svARB, + InitVertexAttrib1dARB, + InitVertexAttrib1dvARB, + InitVertexAttrib1fARB, + InitVertexAttrib1fvARB, + InitVertexAttrib1sARB, + InitVertexAttrib1svARB, + InitVertexAttrib2dARB, + InitVertexAttrib2dvARB, + InitVertexAttrib2fARB, + InitVertexAttrib2fvARB, + InitVertexAttrib2sARB, + InitVertexAttrib2svARB, + InitVertexAttrib3dARB, + InitVertexAttrib3dvARB, + InitVertexAttrib3fARB, + InitVertexAttrib3fvARB, + InitVertexAttrib3sARB, + InitVertexAttrib3svARB, + InitVertexAttrib4NbvARB, + InitVertexAttrib4NivARB, + InitVertexAttrib4NsvARB, + InitVertexAttrib4NubARB, + InitVertexAttrib4NubvARB, + InitVertexAttrib4NuivARB, + InitVertexAttrib4NusvARB, + InitVertexAttrib4bvARB, + InitVertexAttrib4dARB, + InitVertexAttrib4dvARB, + InitVertexAttrib4fARB, + InitVertexAttrib4fvARB, + InitVertexAttrib4ivARB, + InitVertexAttrib4sARB, + InitVertexAttrib4svARB, + InitVertexAttrib4ubvARB, + InitVertexAttrib4uivARB, + InitVertexAttrib4usvARB, + InitVertexAttribPointerARB, + InitEnableVertexAttribArrayARB, + InitDisableVertexAttribArrayARB, + InitProgramStringARB, + InitBindProgramARB, + InitDeleteProgramsARB, + InitGenProgramsARB, + InitProgramEnvParameter4dARB, + InitProgramEnvParameter4dvARB, + InitProgramEnvParameter4fARB, + InitProgramEnvParameter4fvARB, + InitProgramLocalParameter4dARB, + InitProgramLocalParameter4dvARB, + InitProgramLocalParameter4fARB, + InitProgramLocalParameter4fvARB, + InitGetProgramEnvParameterdvARB, + InitGetProgramEnvParameterfvARB, + InitGetProgramLocalParameterdvARB, + InitGetProgramLocalParameterfvARB, + InitGetProgramivARB, + InitGetProgramStringARB, + InitGetVertexAttribdvARB, + InitGetVertexAttribfvARB, + InitGetVertexAttribivARB, + InitGetVertexAttribPointervARB, + InitIsProgramARB, + InitBindBufferARB, + InitDeleteBuffersARB, + InitGenBuffersARB, + InitIsBufferARB, + InitBufferDataARB, + InitBufferSubDataARB, + InitGetBufferSubDataARB, + InitMapBufferARB, + InitUnmapBufferARB, + InitGetBufferParameterivARB, + InitGetBufferPointervARB, + InitGenQueriesARB, + InitDeleteQueriesARB, + InitIsQueryARB, + InitBeginQueryARB, + InitEndQueryARB, + InitGetQueryivARB, + InitGetQueryObjectivARB, + InitGetQueryObjectuivARB, + InitDeleteObjectARB, + InitGetHandleARB, + InitDetachObjectARB, + InitCreateShaderObjectARB, + InitShaderSourceARB, + InitCompileShaderARB, + InitCreateProgramObjectARB, + InitAttachObjectARB, + InitLinkProgramARB, + InitUseProgramObjectARB, + InitValidateProgramARB, + InitUniform1fARB, + InitUniform2fARB, + InitUniform3fARB, + InitUniform4fARB, + InitUniform1iARB, + InitUniform2iARB, + InitUniform3iARB, + InitUniform4iARB, + InitUniform1fvARB, + InitUniform2fvARB, + InitUniform3fvARB, + InitUniform4fvARB, + InitUniform1ivARB, + InitUniform2ivARB, + InitUniform3ivARB, + InitUniform4ivARB, + InitUniformMatrix2fvARB, + InitUniformMatrix3fvARB, + InitUniformMatrix4fvARB, + InitGetObjectParameterfvARB, + InitGetObjectParameterivARB, + InitGetInfoLogARB, + InitGetAttachedObjectsARB, + InitGetUniformLocationARB, + InitGetActiveUniformARB, + InitGetUniformfvARB, + InitGetUniformivARB, + InitGetShaderSourceARB, + InitBindAttribLocationARB, + InitGetActiveAttribARB, + InitGetAttribLocationARB, + InitBlendColorEXT, + InitPolygonOffsetEXT, + InitTexImage3DEXT, + InitTexSubImage3DEXT, + InitGetTexFilterFuncSGIS, + InitTexFilterFuncSGIS, + InitTexSubImage1DEXT, + InitTexSubImage2DEXT, + InitCopyTexImage1DEXT, + InitCopyTexImage2DEXT, + InitCopyTexSubImage1DEXT, + InitCopyTexSubImage2DEXT, + InitCopyTexSubImage3DEXT, + InitGetHistogramEXT, + InitGetHistogramParameterfvEXT, + InitGetHistogramParameterivEXT, + InitGetMinmaxEXT, + InitGetMinmaxParameterfvEXT, + InitGetMinmaxParameterivEXT, + InitHistogramEXT, + InitMinmaxEXT, + InitResetHistogramEXT, + InitResetMinmaxEXT, + InitConvolutionFilter1DEXT, + InitConvolutionFilter2DEXT, + InitConvolutionParameterfEXT, + InitConvolutionParameterfvEXT, + InitConvolutionParameteriEXT, + InitConvolutionParameterivEXT, + InitCopyConvolutionFilter1DEXT, + InitCopyConvolutionFilter2DEXT, + InitGetConvolutionFilterEXT, + InitGetConvolutionParameterfvEXT, + InitGetConvolutionParameterivEXT, + InitGetSeparableFilterEXT, + InitSeparableFilter2DEXT, + InitColorTableSGI, + InitColorTableParameterfvSGI, + InitColorTableParameterivSGI, + InitCopyColorTableSGI, + InitGetColorTableSGI, + InitGetColorTableParameterfvSGI, + InitGetColorTableParameterivSGI, + InitPixelTexGenSGIX, + InitPixelTexGenParameteriSGIS, + InitPixelTexGenParameterivSGIS, + InitPixelTexGenParameterfSGIS, + InitPixelTexGenParameterfvSGIS, + InitGetPixelTexGenParameterivSGIS, + InitGetPixelTexGenParameterfvSGIS, + InitTexImage4DSGIS, + InitTexSubImage4DSGIS, + InitAreTexturesResidentEXT, + InitBindTextureEXT, + InitDeleteTexturesEXT, + InitGenTexturesEXT, + InitIsTextureEXT, + InitPrioritizeTexturesEXT, + InitDetailTexFuncSGIS, + InitGetDetailTexFuncSGIS, + InitSharpenTexFuncSGIS, + InitGetSharpenTexFuncSGIS, + InitSampleMaskSGIS, + InitSamplePatternSGIS, + InitArrayElementEXT, + InitColorPointerEXT, + InitDrawArraysEXT, + InitEdgeFlagPointerEXT, + InitGetPointervEXT, + InitIndexPointerEXT, + InitNormalPointerEXT, + InitTexCoordPointerEXT, + InitVertexPointerEXT, + InitBlendEquationEXT, + InitSpriteParameterfSGIX, + InitSpriteParameterfvSGIX, + InitSpriteParameteriSGIX, + InitSpriteParameterivSGIX, + InitPointParameterfEXT, + InitPointParameterfvEXT, + InitPointParameterfSGIS, + InitPointParameterfvSGIS, + InitGetInstrumentsSGIX, + InitInstrumentsBufferSGIX, + InitPollInstrumentsSGIX, + InitReadInstrumentsSGIX, + InitStartInstrumentsSGIX, + InitStopInstrumentsSGIX, + InitFrameZoomSGIX, + InitTagSampleBufferSGIX, + InitDeformationMap3dSGIX, + InitDeformationMap3fSGIX, + InitDeformSGIX, + InitLoadIdentityDeformationMapSGIX, + InitReferencePlaneSGIX, + InitFlushRasterSGIX, + InitFogFuncSGIS, + InitGetFogFuncSGIS, + InitImageTransformParameteriHP, + InitImageTransformParameterfHP, + InitImageTransformParameterivHP, + InitImageTransformParameterfvHP, + InitGetImageTransformParameterivHP, + InitGetImageTransformParameterfvHP, + InitColorSubTableEXT, + InitCopyColorSubTableEXT, + InitHintPGI, + InitColorTableEXT, + InitGetColorTableEXT, + InitGetColorTableParameterivEXT, + InitGetColorTableParameterfvEXT, + InitGetListParameterfvSGIX, + InitGetListParameterivSGIX, + InitListParameterfSGIX, + InitListParameterfvSGIX, + InitListParameteriSGIX, + InitListParameterivSGIX, + InitIndexMaterialEXT, + InitIndexFuncEXT, + InitLockArraysEXT, + InitUnlockArraysEXT, + InitCullParameterdvEXT, + InitCullParameterfvEXT, + InitFragmentColorMaterialSGIX, + InitFragmentLightfSGIX, + InitFragmentLightfvSGIX, + InitFragmentLightiSGIX, + InitFragmentLightivSGIX, + InitFragmentLightModelfSGIX, + InitFragmentLightModelfvSGIX, + InitFragmentLightModeliSGIX, + InitFragmentLightModelivSGIX, + InitFragmentMaterialfSGIX, + InitFragmentMaterialfvSGIX, + InitFragmentMaterialiSGIX, + InitFragmentMaterialivSGIX, + InitGetFragmentLightfvSGIX, + InitGetFragmentLightivSGIX, + InitGetFragmentMaterialfvSGIX, + InitGetFragmentMaterialivSGIX, + InitLightEnviSGIX, + InitDrawRangeElementsEXT, + InitApplyTextureEXT, + InitTextureLightEXT, + InitTextureMaterialEXT, + InitAsyncMarkerSGIX, + InitFinishAsyncSGIX, + InitPollAsyncSGIX, + InitGenAsyncMarkersSGIX, + InitDeleteAsyncMarkersSGIX, + InitIsAsyncMarkerSGIX, + InitVertexPointervINTEL, + InitNormalPointervINTEL, + InitColorPointervINTEL, + InitTexCoordPointervINTEL, + InitPixelTransformParameteriEXT, + InitPixelTransformParameterfEXT, + InitPixelTransformParameterivEXT, + InitPixelTransformParameterfvEXT, + InitSecondaryColor3bEXT, + InitSecondaryColor3bvEXT, + InitSecondaryColor3dEXT, + InitSecondaryColor3dvEXT, + InitSecondaryColor3fEXT, + InitSecondaryColor3fvEXT, + InitSecondaryColor3iEXT, + InitSecondaryColor3ivEXT, + InitSecondaryColor3sEXT, + InitSecondaryColor3svEXT, + InitSecondaryColor3ubEXT, + InitSecondaryColor3ubvEXT, + InitSecondaryColor3uiEXT, + InitSecondaryColor3uivEXT, + InitSecondaryColor3usEXT, + InitSecondaryColor3usvEXT, + InitSecondaryColorPointerEXT, + InitTextureNormalEXT, + InitMultiDrawArraysEXT, + InitMultiDrawElementsEXT, + InitFogCoordfEXT, + InitFogCoordfvEXT, + InitFogCoorddEXT, + InitFogCoorddvEXT, + InitFogCoordPointerEXT, + InitTangent3bEXT, + InitTangent3bvEXT, + InitTangent3dEXT, + InitTangent3dvEXT, + InitTangent3fEXT, + InitTangent3fvEXT, + InitTangent3iEXT, + InitTangent3ivEXT, + InitTangent3sEXT, + InitTangent3svEXT, + InitBinormal3bEXT, + InitBinormal3bvEXT, + InitBinormal3dEXT, + InitBinormal3dvEXT, + InitBinormal3fEXT, + InitBinormal3fvEXT, + InitBinormal3iEXT, + InitBinormal3ivEXT, + InitBinormal3sEXT, + InitBinormal3svEXT, + InitTangentPointerEXT, + InitBinormalPointerEXT, + InitFinishTextureSUNX, + InitGlobalAlphaFactorbSUN, + InitGlobalAlphaFactorsSUN, + InitGlobalAlphaFactoriSUN, + InitGlobalAlphaFactorfSUN, + InitGlobalAlphaFactordSUN, + InitGlobalAlphaFactorubSUN, + InitGlobalAlphaFactorusSUN, + InitGlobalAlphaFactoruiSUN, + InitReplacementCodeuiSUN, + InitReplacementCodeusSUN, + InitReplacementCodeubSUN, + InitReplacementCodeuivSUN, + InitReplacementCodeusvSUN, + InitReplacementCodeubvSUN, + InitReplacementCodePointerSUN, + InitColor4ubVertex2fSUN, + InitColor4ubVertex2fvSUN, + InitColor4ubVertex3fSUN, + InitColor4ubVertex3fvSUN, + InitColor3fVertex3fSUN, + InitColor3fVertex3fvSUN, + InitNormal3fVertex3fSUN, + InitNormal3fVertex3fvSUN, + InitColor4fNormal3fVertex3fSUN, + InitColor4fNormal3fVertex3fvSUN, + InitTexCoord2fVertex3fSUN, + InitTexCoord2fVertex3fvSUN, + InitTexCoord4fVertex4fSUN, + InitTexCoord4fVertex4fvSUN, + InitTexCoord2fColor4ubVertex3fSUN, + InitTexCoord2fColor4ubVertex3fvSUN, + InitTexCoord2fColor3fVertex3fSUN, + InitTexCoord2fColor3fVertex3fvSUN, + InitTexCoord2fNormal3fVertex3fSUN, + InitTexCoord2fNormal3fVertex3fvSUN, + InitTexCoord2fColor4fNormal3fVertex3fSUN, + InitTexCoord2fColor4fNormal3fVertex3fvSUN, + InitTexCoord4fColor4fNormal3fVertex4fSUN, + InitTexCoord4fColor4fNormal3fVertex4fvSUN, + InitReplacementCodeuiVertex3fSUN, + InitReplacementCodeuiVertex3fvSUN, + InitReplacementCodeuiColor4ubVertex3fSUN, + InitReplacementCodeuiColor4ubVertex3fvSUN, + InitReplacementCodeuiColor3fVertex3fSUN, + InitReplacementCodeuiColor3fVertex3fvSUN, + InitReplacementCodeuiNormal3fVertex3fSUN, + InitReplacementCodeuiNormal3fVertex3fvSUN, + InitReplacementCodeuiColor4fNormal3fVertex3fSUN, + InitReplacementCodeuiColor4fNormal3fVertex3fvSUN, + InitReplacementCodeuiTexCoord2fVertex3fSUN, + InitReplacementCodeuiTexCoord2fVertex3fvSUN, + InitReplacementCodeuiTexCoord2fNormal3fVertex3fSUN, + InitReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN, + InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN, + InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN, + InitBlendFuncSeparateEXT, + InitBlendFuncSeparateINGR, + InitVertexWeightfEXT, + InitVertexWeightfvEXT, + InitVertexWeightPointerEXT, + InitFlushVertexArrayRangeNV, + InitVertexArrayRangeNV, + InitCombinerParameterfvNV, + InitCombinerParameterfNV, + InitCombinerParameterivNV, + InitCombinerParameteriNV, + InitCombinerInputNV, + InitCombinerOutputNV, + InitFinalCombinerInputNV, + InitGetCombinerInputParameterfvNV, + InitGetCombinerInputParameterivNV, + InitGetCombinerOutputParameterfvNV, + InitGetCombinerOutputParameterivNV, + InitGetFinalCombinerInputParameterfvNV, + InitGetFinalCombinerInputParameterivNV, + InitResizeBuffersMESA, + InitWindowPos2dMESA, + InitWindowPos2dvMESA, + InitWindowPos2fMESA, + InitWindowPos2fvMESA, + InitWindowPos2iMESA, + InitWindowPos2ivMESA, + InitWindowPos2sMESA, + InitWindowPos2svMESA, + InitWindowPos3dMESA, + InitWindowPos3dvMESA, + InitWindowPos3fMESA, + InitWindowPos3fvMESA, + InitWindowPos3iMESA, + InitWindowPos3ivMESA, + InitWindowPos3sMESA, + InitWindowPos3svMESA, + InitWindowPos4dMESA, + InitWindowPos4dvMESA, + InitWindowPos4fMESA, + InitWindowPos4fvMESA, + InitWindowPos4iMESA, + InitWindowPos4ivMESA, + InitWindowPos4sMESA, + InitWindowPos4svMESA, + InitMultiModeDrawArraysIBM, + InitMultiModeDrawElementsIBM, + InitColorPointerListIBM, + InitSecondaryColorPointerListIBM, + InitEdgeFlagPointerListIBM, + InitFogCoordPointerListIBM, + InitIndexPointerListIBM, + InitNormalPointerListIBM, + InitTexCoordPointerListIBM, + InitVertexPointerListIBM, + InitTbufferMask3DFX, + InitSampleMaskEXT, + InitSamplePatternEXT, + InitTextureColorMaskSGIS, + InitIglooInterfaceSGIX, + InitDeleteFencesNV, + InitGenFencesNV, + InitIsFenceNV, + InitTestFenceNV, + InitGetFenceivNV, + InitFinishFenceNV, + InitSetFenceNV, + InitMapControlPointsNV, + InitMapParameterivNV, + InitMapParameterfvNV, + InitGetMapControlPointsNV, + InitGetMapParameterivNV, + InitGetMapParameterfvNV, + InitGetMapAttribParameterivNV, + InitGetMapAttribParameterfvNV, + InitEvalMapsNV, + InitCombinerStageParameterfvNV, + InitGetCombinerStageParameterfvNV, + InitAreProgramsResidentNV, + InitBindProgramNV, + InitDeleteProgramsNV, + InitExecuteProgramNV, + InitGenProgramsNV, + InitGetProgramParameterdvNV, + InitGetProgramParameterfvNV, + InitGetProgramivNV, + InitGetProgramStringNV, + InitGetTrackMatrixivNV, + InitGetVertexAttribdvNV, + InitGetVertexAttribfvNV, + InitGetVertexAttribivNV, + InitGetVertexAttribPointervNV, + InitIsProgramNV, + InitLoadProgramNV, + InitProgramParameter4dNV, + InitProgramParameter4dvNV, + InitProgramParameter4fNV, + InitProgramParameter4fvNV, + InitProgramParameters4dvNV, + InitProgramParameters4fvNV, + InitRequestResidentProgramsNV, + InitTrackMatrixNV, + InitVertexAttribPointerNV, + InitVertexAttrib1dNV, + InitVertexAttrib1dvNV, + InitVertexAttrib1fNV, + InitVertexAttrib1fvNV, + InitVertexAttrib1sNV, + InitVertexAttrib1svNV, + InitVertexAttrib2dNV, + InitVertexAttrib2dvNV, + InitVertexAttrib2fNV, + InitVertexAttrib2fvNV, + InitVertexAttrib2sNV, + InitVertexAttrib2svNV, + InitVertexAttrib3dNV, + InitVertexAttrib3dvNV, + InitVertexAttrib3fNV, + InitVertexAttrib3fvNV, + InitVertexAttrib3sNV, + InitVertexAttrib3svNV, + InitVertexAttrib4dNV, + InitVertexAttrib4dvNV, + InitVertexAttrib4fNV, + InitVertexAttrib4fvNV, + InitVertexAttrib4sNV, + InitVertexAttrib4svNV, + InitVertexAttrib4ubNV, + InitVertexAttrib4ubvNV, + InitVertexAttribs1dvNV, + InitVertexAttribs1fvNV, + InitVertexAttribs1svNV, + InitVertexAttribs2dvNV, + InitVertexAttribs2fvNV, + InitVertexAttribs2svNV, + InitVertexAttribs3dvNV, + InitVertexAttribs3fvNV, + InitVertexAttribs3svNV, + InitVertexAttribs4dvNV, + InitVertexAttribs4fvNV, + InitVertexAttribs4svNV, + InitVertexAttribs4ubvNV, + InitTexBumpParameterivATI, + InitTexBumpParameterfvATI, + InitGetTexBumpParameterivATI, + InitGetTexBumpParameterfvATI, + InitGenFragmentShadersATI, + InitBindFragmentShaderATI, + InitDeleteFragmentShaderATI, + InitBeginFragmentShaderATI, + InitEndFragmentShaderATI, + InitPassTexCoordATI, + InitSampleMapATI, + InitColorFragmentOp1ATI, + InitColorFragmentOp2ATI, + InitColorFragmentOp3ATI, + InitAlphaFragmentOp1ATI, + InitAlphaFragmentOp2ATI, + InitAlphaFragmentOp3ATI, + InitSetFragmentShaderConstantATI, + InitPNTrianglesiATI, + InitPNTrianglesfATI, + InitNewObjectBufferATI, + InitIsObjectBufferATI, + InitUpdateObjectBufferATI, + InitGetObjectBufferfvATI, + InitGetObjectBufferivATI, + InitFreeObjectBufferATI, + InitArrayObjectATI, + InitGetArrayObjectfvATI, + InitGetArrayObjectivATI, + InitVariantArrayObjectATI, + InitGetVariantArrayObjectfvATI, + InitGetVariantArrayObjectivATI, + InitBeginVertexShaderEXT, + InitEndVertexShaderEXT, + InitBindVertexShaderEXT, + InitGenVertexShadersEXT, + InitDeleteVertexShaderEXT, + InitShaderOp1EXT, + InitShaderOp2EXT, + InitShaderOp3EXT, + InitSwizzleEXT, + InitWriteMaskEXT, + InitInsertComponentEXT, + InitExtractComponentEXT, + InitGenSymbolsEXT, + InitSetInvariantEXT, + InitSetLocalConstantEXT, + InitVariantbvEXT, + InitVariantsvEXT, + InitVariantivEXT, + InitVariantfvEXT, + InitVariantdvEXT, + InitVariantubvEXT, + InitVariantusvEXT, + InitVariantuivEXT, + InitVariantPointerEXT, + InitEnableVariantClientStateEXT, + InitDisableVariantClientStateEXT, + InitBindLightParameterEXT, + InitBindMaterialParameterEXT, + InitBindTexGenParameterEXT, + InitBindTextureUnitParameterEXT, + InitBindParameterEXT, + InitIsVariantEnabledEXT, + InitGetVariantBooleanvEXT, + InitGetVariantIntegervEXT, + InitGetVariantFloatvEXT, + InitGetVariantPointervEXT, + InitGetInvariantBooleanvEXT, + InitGetInvariantIntegervEXT, + InitGetInvariantFloatvEXT, + InitGetLocalConstantBooleanvEXT, + InitGetLocalConstantIntegervEXT, + InitGetLocalConstantFloatvEXT, + InitVertexStream1sATI, + InitVertexStream1svATI, + InitVertexStream1iATI, + InitVertexStream1ivATI, + InitVertexStream1fATI, + InitVertexStream1fvATI, + InitVertexStream1dATI, + InitVertexStream1dvATI, + InitVertexStream2sATI, + InitVertexStream2svATI, + InitVertexStream2iATI, + InitVertexStream2ivATI, + InitVertexStream2fATI, + InitVertexStream2fvATI, + InitVertexStream2dATI, + InitVertexStream2dvATI, + InitVertexStream3sATI, + InitVertexStream3svATI, + InitVertexStream3iATI, + InitVertexStream3ivATI, + InitVertexStream3fATI, + InitVertexStream3fvATI, + InitVertexStream3dATI, + InitVertexStream3dvATI, + InitVertexStream4sATI, + InitVertexStream4svATI, + InitVertexStream4iATI, + InitVertexStream4ivATI, + InitVertexStream4fATI, + InitVertexStream4fvATI, + InitVertexStream4dATI, + InitVertexStream4dvATI, + InitNormalStream3bATI, + InitNormalStream3bvATI, + InitNormalStream3sATI, + InitNormalStream3svATI, + InitNormalStream3iATI, + InitNormalStream3ivATI, + InitNormalStream3fATI, + InitNormalStream3fvATI, + InitNormalStream3dATI, + InitNormalStream3dvATI, + InitClientActiveVertexStreamATI, + InitVertexBlendEnviATI, + InitVertexBlendEnvfATI, + InitElementPointerATI, + InitDrawElementArrayATI, + InitDrawRangeElementArrayATI, + InitDrawMeshArraysSUN, + InitGenOcclusionQueriesNV, + InitDeleteOcclusionQueriesNV, + InitIsOcclusionQueryNV, + InitBeginOcclusionQueryNV, + InitEndOcclusionQueryNV, + InitGetOcclusionQueryivNV, + InitGetOcclusionQueryuivNV, + InitPointParameteriNV, + InitPointParameterivNV, + InitActiveStencilFaceEXT, + InitElementPointerAPPLE, + InitDrawElementArrayAPPLE, + InitDrawRangeElementArrayAPPLE, + InitMultiDrawElementArrayAPPLE, + InitMultiDrawRangeElementArrayAPPLE, + InitGenFencesAPPLE, + InitDeleteFencesAPPLE, + InitSetFenceAPPLE, + InitIsFenceAPPLE, + InitTestFenceAPPLE, + InitFinishFenceAPPLE, + InitTestObjectAPPLE, + InitFinishObjectAPPLE, + InitBindVertexArrayAPPLE, + InitDeleteVertexArraysAPPLE, + InitGenVertexArraysAPPLE, + InitIsVertexArrayAPPLE, + InitVertexArrayRangeAPPLE, + InitFlushVertexArrayRangeAPPLE, + InitVertexArrayParameteriAPPLE, + InitDrawBuffersATI, + InitProgramNamedParameter4fNV, + InitProgramNamedParameter4dNV, + InitProgramNamedParameter4fvNV, + InitProgramNamedParameter4dvNV, + InitGetProgramNamedParameterfvNV, + InitGetProgramNamedParameterdvNV, + InitVertex2hNV, + InitVertex2hvNV, + InitVertex3hNV, + InitVertex3hvNV, + InitVertex4hNV, + InitVertex4hvNV, + InitNormal3hNV, + InitNormal3hvNV, + InitColor3hNV, + InitColor3hvNV, + InitColor4hNV, + InitColor4hvNV, + InitTexCoord1hNV, + InitTexCoord1hvNV, + InitTexCoord2hNV, + InitTexCoord2hvNV, + InitTexCoord3hNV, + InitTexCoord3hvNV, + InitTexCoord4hNV, + InitTexCoord4hvNV, + InitMultiTexCoord1hNV, + InitMultiTexCoord1hvNV, + InitMultiTexCoord2hNV, + InitMultiTexCoord2hvNV, + InitMultiTexCoord3hNV, + InitMultiTexCoord3hvNV, + InitMultiTexCoord4hNV, + InitMultiTexCoord4hvNV, + InitFogCoordhNV, + InitFogCoordhvNV, + InitSecondaryColor3hNV, + InitSecondaryColor3hvNV, + InitVertexWeighthNV, + InitVertexWeighthvNV, + InitVertexAttrib1hNV, + InitVertexAttrib1hvNV, + InitVertexAttrib2hNV, + InitVertexAttrib2hvNV, + InitVertexAttrib3hNV, + InitVertexAttrib3hvNV, + InitVertexAttrib4hNV, + InitVertexAttrib4hvNV, + InitVertexAttribs1hvNV, + InitVertexAttribs2hvNV, + InitVertexAttribs3hvNV, + InitVertexAttribs4hvNV, + InitPixelDataRangeNV, + InitFlushPixelDataRangeNV, + InitPrimitiveRestartNV, + InitPrimitiveRestartIndexNV, + InitMapObjectBufferATI, + InitUnmapObjectBufferATI, + InitStencilOpSeparateATI, + InitStencilFuncSeparateATI, + InitVertexAttribArrayObjectATI, + InitGetVertexAttribArrayObjectfvATI, + InitGetVertexAttribArrayObjectivATI, + InitDepthBoundsEXT, + InitBlendEquationSeparateEXT, + InitAddSwapHintRectWIN, +#ifdef _WIN32 + InitCreateBufferRegionARB, + InitDeleteBufferRegionARB, + InitSaveBufferRegionARB, + InitRestoreBufferRegionARB, + InitGetExtensionsStringARB, + InitGetPixelFormatAttribivARB, + InitGetPixelFormatAttribfvARB, + InitChoosePixelFormatARB, + InitMakeContextCurrentARB, + InitGetCurrentReadDCARB, + InitCreatePbufferARB, + InitGetPbufferDCARB, + InitReleasePbufferDCARB, + InitDestroyPbufferARB, + InitQueryPbufferARB, + InitBindTexImageARB, + InitReleaseTexImageARB, + InitSetPbufferAttribARB, + InitCreateDisplayColorTableEXT, + InitLoadDisplayColorTableEXT, + InitBindDisplayColorTableEXT, + InitDestroyDisplayColorTableEXT, + InitGetExtensionsStringEXT, + InitMakeContextCurrentEXT, + InitGetCurrentReadDCEXT, + InitCreatePbufferEXT, + InitGetPbufferDCEXT, + InitReleasePbufferDCEXT, + InitDestroyPbufferEXT, + InitQueryPbufferEXT, + InitGetPixelFormatAttribivEXT, + InitGetPixelFormatAttribfvEXT, + InitChoosePixelFormatEXT, + InitSwapIntervalEXT, + InitGetSwapIntervalEXT, + InitAllocateMemoryNV, + InitFreeMemoryNV, + InitGetSyncValuesOML, + InitGetMscRateOML, + InitSwapBuffersMscOML, + InitSwapLayerBuffersMscOML, + InitWaitForMscOML, + InitWaitForSbcOML, + InitGetDigitalVideoParametersI3D, + InitSetDigitalVideoParametersI3D, + InitGetGammaTableParametersI3D, + InitSetGammaTableParametersI3D, + InitGetGammaTableI3D, + InitSetGammaTableI3D, + InitEnableGenlockI3D, + InitDisableGenlockI3D, + InitIsEnabledGenlockI3D, + InitGenlockSourceI3D, + InitGetGenlockSourceI3D, + InitGenlockSourceEdgeI3D, + InitGetGenlockSourceEdgeI3D, + InitGenlockSampleRateI3D, + InitGetGenlockSampleRateI3D, + InitGenlockSourceDelayI3D, + InitGetGenlockSourceDelayI3D, + InitQueryGenlockMaxSourceDelayI3D, + InitCreateImageBufferI3D, + InitDestroyImageBufferI3D, + InitAssociateImageBufferEventsI3D, + InitReleaseImageBufferEventsI3D, + InitEnableFrameLockI3D, + InitDisableFrameLockI3D, + InitIsEnabledFrameLockI3D, + InitQueryFrameLockMasterI3D, + InitGetFrameUsageI3D, + InitBeginFrameTrackingI3D, + InitEndFrameTrackingI3D, + InitQueryFrameTrackingI3D, +#endif /* _WIN32 */ +}; diff --git a/plugins/zzogl-pg/opengl/glprocs.h b/plugins/zzogl-pg/opengl/glprocs.h new file mode 100644 index 0000000000..1df56f18db --- /dev/null +++ b/plugins/zzogl-pg/opengl/glprocs.h @@ -0,0 +1,2213 @@ +#ifndef _GLPROCS_H_ +#define _GLPROCS_H_ + +/* +** GLprocs utility for getting function addresses for OpenGL(R) 1.2, +** OpenGL 1.3, OpenGL 1.4, OpenGL 1.5 and OpenGL extension functions. +** +** Version: 1.1 +** +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +** +** Initial version of glprocs.{c,h} contributed by Intel(R) Corporation. +*/ + +#ifdef _WIN32 + #include + #include +#else + #include +#endif + +#ifndef _WIN32 /* non-Windows environment */ + #ifndef APIENTRY + #define APIENTRY + #endif + #ifdef __GNUC__ + #define _inline __inline__ + #else + #define _inline + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure of all OpenGL {1.2, 1.3, 1.4, 1.5}, GL extension procs.*/ + +typedef struct { + void (APIENTRY *BlendColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void (APIENTRY *BlendEquation) (GLenum mode); + void (APIENTRY *DrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + void (APIENTRY *ColorTable) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); + void (APIENTRY *ColorTableParameterfv) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ColorTableParameteriv) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyColorTable) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *GetColorTable) (GLenum target, GLenum format, GLenum type, GLvoid *table); + void (APIENTRY *GetColorTableParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetColorTableParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *ColorSubTable) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); + void (APIENTRY *CopyColorSubTable) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + void (APIENTRY *ConvolutionFilter1D) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionFilter2D) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionParameterf) (GLenum target, GLenum pname, GLfloat params); + void (APIENTRY *ConvolutionParameterfv) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ConvolutionParameteri) (GLenum target, GLenum pname, GLint params); + void (APIENTRY *ConvolutionParameteriv) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyConvolutionFilter1D) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *CopyConvolutionFilter2D) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *GetConvolutionFilter) (GLenum target, GLenum format, GLenum type, GLvoid *image); + void (APIENTRY *GetConvolutionParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetConvolutionParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetSeparableFilter) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); + void (APIENTRY *SeparableFilter2D) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + void (APIENTRY *GetHistogram) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetHistogramParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetHistogramParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetMinmax) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetMinmaxParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetMinmaxParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *Histogram) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); + void (APIENTRY *Minmax) (GLenum target, GLenum internalformat, GLboolean sink); + void (APIENTRY *ResetHistogram) (GLenum target); + void (APIENTRY *ResetMinmax) (GLenum target); + void (APIENTRY *TexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *CopyTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *ActiveTexture) (GLenum texture); + void (APIENTRY *ClientActiveTexture) (GLenum texture); + void (APIENTRY *MultiTexCoord1d) (GLenum target, GLdouble s); + void (APIENTRY *MultiTexCoord1dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord1f) (GLenum target, GLfloat s); + void (APIENTRY *MultiTexCoord1fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord1i) (GLenum target, GLint s); + void (APIENTRY *MultiTexCoord1iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord1s) (GLenum target, GLshort s); + void (APIENTRY *MultiTexCoord1sv) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord2d) (GLenum target, GLdouble s, GLdouble t); + void (APIENTRY *MultiTexCoord2dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord2f) (GLenum target, GLfloat s, GLfloat t); + void (APIENTRY *MultiTexCoord2fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord2i) (GLenum target, GLint s, GLint t); + void (APIENTRY *MultiTexCoord2iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord2s) (GLenum target, GLshort s, GLshort t); + void (APIENTRY *MultiTexCoord2sv) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord3d) (GLenum target, GLdouble s, GLdouble t, GLdouble r); + void (APIENTRY *MultiTexCoord3dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord3f) (GLenum target, GLfloat s, GLfloat t, GLfloat r); + void (APIENTRY *MultiTexCoord3fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord3i) (GLenum target, GLint s, GLint t, GLint r); + void (APIENTRY *MultiTexCoord3iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord3s) (GLenum target, GLshort s, GLshort t, GLshort r); + void (APIENTRY *MultiTexCoord3sv) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord4d) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); + void (APIENTRY *MultiTexCoord4dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord4f) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); + void (APIENTRY *MultiTexCoord4fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord4i) (GLenum target, GLint s, GLint t, GLint r, GLint q); + void (APIENTRY *MultiTexCoord4iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord4s) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); + void (APIENTRY *MultiTexCoord4sv) (GLenum target, const GLshort *v); + void (APIENTRY *LoadTransposeMatrixf) (const GLfloat *m); + void (APIENTRY *LoadTransposeMatrixd) (const GLdouble *m); + void (APIENTRY *MultTransposeMatrixf) (const GLfloat *m); + void (APIENTRY *MultTransposeMatrixd) (const GLdouble *m); + void (APIENTRY *SampleCoverage) (GLclampf value, GLboolean invert); + void (APIENTRY *CompressedTexImage3D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage1D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *GetCompressedTexImage) (GLenum target, GLint level, GLvoid *img); + void (APIENTRY *BlendFuncSeparate) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + void (APIENTRY *FogCoordf) (GLfloat coord); + void (APIENTRY *FogCoordfv) (const GLfloat *coord); + void (APIENTRY *FogCoordd) (GLdouble coord); + void (APIENTRY *FogCoorddv) (const GLdouble *coord); + void (APIENTRY *FogCoordPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *MultiDrawArrays) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); + void (APIENTRY *MultiDrawElements) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); + void (APIENTRY *PointParameterf) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfv) (GLenum pname, const GLfloat *params); + void (APIENTRY *PointParameteri) (GLenum pname, GLint param); + void (APIENTRY *PointParameteriv) (GLenum pname, const GLint *params); + void (APIENTRY *SecondaryColor3b) (GLbyte red, GLbyte green, GLbyte blue); + void (APIENTRY *SecondaryColor3bv) (const GLbyte *v); + void (APIENTRY *SecondaryColor3d) (GLdouble red, GLdouble green, GLdouble blue); + void (APIENTRY *SecondaryColor3dv) (const GLdouble *v); + void (APIENTRY *SecondaryColor3f) (GLfloat red, GLfloat green, GLfloat blue); + void (APIENTRY *SecondaryColor3fv) (const GLfloat *v); + void (APIENTRY *SecondaryColor3i) (GLint red, GLint green, GLint blue); + void (APIENTRY *SecondaryColor3iv) (const GLint *v); + void (APIENTRY *SecondaryColor3s) (GLshort red, GLshort green, GLshort blue); + void (APIENTRY *SecondaryColor3sv) (const GLshort *v); + void (APIENTRY *SecondaryColor3ub) (GLubyte red, GLubyte green, GLubyte blue); + void (APIENTRY *SecondaryColor3ubv) (const GLubyte *v); + void (APIENTRY *SecondaryColor3ui) (GLuint red, GLuint green, GLuint blue); + void (APIENTRY *SecondaryColor3uiv) (const GLuint *v); + void (APIENTRY *SecondaryColor3us) (GLushort red, GLushort green, GLushort blue); + void (APIENTRY *SecondaryColor3usv) (const GLushort *v); + void (APIENTRY *SecondaryColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *WindowPos2d) (GLdouble x, GLdouble y); + void (APIENTRY *WindowPos2dv) (const GLdouble *v); + void (APIENTRY *WindowPos2f) (GLfloat x, GLfloat y); + void (APIENTRY *WindowPos2fv) (const GLfloat *v); + void (APIENTRY *WindowPos2i) (GLint x, GLint y); + void (APIENTRY *WindowPos2iv) (const GLint *v); + void (APIENTRY *WindowPos2s) (GLshort x, GLshort y); + void (APIENTRY *WindowPos2sv) (const GLshort *v); + void (APIENTRY *WindowPos3d) (GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *WindowPos3dv) (const GLdouble *v); + void (APIENTRY *WindowPos3f) (GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *WindowPos3fv) (const GLfloat *v); + void (APIENTRY *WindowPos3i) (GLint x, GLint y, GLint z); + void (APIENTRY *WindowPos3iv) (const GLint *v); + void (APIENTRY *WindowPos3s) (GLshort x, GLshort y, GLshort z); + void (APIENTRY *WindowPos3sv) (const GLshort *v); + void (APIENTRY *GenQueries) (GLsizei n, GLuint *ids); + void (APIENTRY *DeleteQueries) (GLsizei n, const GLuint *ids); + GLboolean (APIENTRY *IsQuery) (GLuint id); + void (APIENTRY *BeginQuery) (GLenum target, GLuint id); + void (APIENTRY *EndQuery) (GLenum target); + void (APIENTRY *GetQueryiv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectiv) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectuiv) (GLuint id, GLenum pname, GLuint *params); + void (APIENTRY *BindBuffer) (GLenum target, GLuint buffer); + void (APIENTRY *DeleteBuffers) (GLsizei n, const GLuint *buffers); + void (APIENTRY *GenBuffers) (GLsizei n, GLuint *buffers); + GLboolean (APIENTRY *IsBuffer) (GLuint buffer); + void (APIENTRY *BufferData) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); + void (APIENTRY *BufferSubData) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); + void (APIENTRY *GetBufferSubData) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); + GLvoid* (APIENTRY *MapBuffer) (GLenum target, GLenum access); + GLboolean (APIENTRY *UnmapBuffer) (GLenum target); + void (APIENTRY *GetBufferParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetBufferPointerv) (GLenum target, GLenum pname, GLvoid* *params); + void (APIENTRY *ActiveTextureARB) (GLenum texture); + void (APIENTRY *ClientActiveTextureARB) (GLenum texture); + void (APIENTRY *MultiTexCoord1dARB) (GLenum target, GLdouble s); + void (APIENTRY *MultiTexCoord1dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord1fARB) (GLenum target, GLfloat s); + void (APIENTRY *MultiTexCoord1fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord1iARB) (GLenum target, GLint s); + void (APIENTRY *MultiTexCoord1ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord1sARB) (GLenum target, GLshort s); + void (APIENTRY *MultiTexCoord1svARB) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord2dARB) (GLenum target, GLdouble s, GLdouble t); + void (APIENTRY *MultiTexCoord2dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t); + void (APIENTRY *MultiTexCoord2fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord2iARB) (GLenum target, GLint s, GLint t); + void (APIENTRY *MultiTexCoord2ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord2sARB) (GLenum target, GLshort s, GLshort t); + void (APIENTRY *MultiTexCoord2svARB) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord3dARB) (GLenum target, GLdouble s, GLdouble t, GLdouble r); + void (APIENTRY *MultiTexCoord3dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord3fARB) (GLenum target, GLfloat s, GLfloat t, GLfloat r); + void (APIENTRY *MultiTexCoord3fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord3iARB) (GLenum target, GLint s, GLint t, GLint r); + void (APIENTRY *MultiTexCoord3ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord3sARB) (GLenum target, GLshort s, GLshort t, GLshort r); + void (APIENTRY *MultiTexCoord3svARB) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord4dARB) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); + void (APIENTRY *MultiTexCoord4dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord4fARB) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); + void (APIENTRY *MultiTexCoord4fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord4iARB) (GLenum target, GLint s, GLint t, GLint r, GLint q); + void (APIENTRY *MultiTexCoord4ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord4sARB) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); + void (APIENTRY *MultiTexCoord4svARB) (GLenum target, const GLshort *v); + void (APIENTRY *LoadTransposeMatrixfARB) (const GLfloat *m); + void (APIENTRY *LoadTransposeMatrixdARB) (const GLdouble *m); + void (APIENTRY *MultTransposeMatrixfARB) (const GLfloat *m); + void (APIENTRY *MultTransposeMatrixdARB) (const GLdouble *m); + void (APIENTRY *SampleCoverageARB) (GLclampf value, GLboolean invert); + void (APIENTRY *CompressedTexImage3DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage2DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage1DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage3DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage2DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage1DARB) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *GetCompressedTexImageARB) (GLenum target, GLint level, GLvoid *img); + void (APIENTRY *PointParameterfARB) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfvARB) (GLenum pname, const GLfloat *params); + void (APIENTRY *WeightbvARB) (GLint size, const GLbyte *weights); + void (APIENTRY *WeightsvARB) (GLint size, const GLshort *weights); + void (APIENTRY *WeightivARB) (GLint size, const GLint *weights); + void (APIENTRY *WeightfvARB) (GLint size, const GLfloat *weights); + void (APIENTRY *WeightdvARB) (GLint size, const GLdouble *weights); + void (APIENTRY *WeightubvARB) (GLint size, const GLubyte *weights); + void (APIENTRY *WeightusvARB) (GLint size, const GLushort *weights); + void (APIENTRY *WeightuivARB) (GLint size, const GLuint *weights); + void (APIENTRY *WeightPointerARB) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *VertexBlendARB) (GLint count); + void (APIENTRY *CurrentPaletteMatrixARB) (GLint index); + void (APIENTRY *MatrixIndexubvARB) (GLint size, const GLubyte *indices); + void (APIENTRY *MatrixIndexusvARB) (GLint size, const GLushort *indices); + void (APIENTRY *MatrixIndexuivARB) (GLint size, const GLuint *indices); + void (APIENTRY *MatrixIndexPointerARB) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *WindowPos2dARB) (GLdouble x, GLdouble y); + void (APIENTRY *WindowPos2dvARB) (const GLdouble *v); + void (APIENTRY *WindowPos2fARB) (GLfloat x, GLfloat y); + void (APIENTRY *WindowPos2fvARB) (const GLfloat *v); + void (APIENTRY *WindowPos2iARB) (GLint x, GLint y); + void (APIENTRY *WindowPos2ivARB) (const GLint *v); + void (APIENTRY *WindowPos2sARB) (GLshort x, GLshort y); + void (APIENTRY *WindowPos2svARB) (const GLshort *v); + void (APIENTRY *WindowPos3dARB) (GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *WindowPos3dvARB) (const GLdouble *v); + void (APIENTRY *WindowPos3fARB) (GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *WindowPos3fvARB) (const GLfloat *v); + void (APIENTRY *WindowPos3iARB) (GLint x, GLint y, GLint z); + void (APIENTRY *WindowPos3ivARB) (const GLint *v); + void (APIENTRY *WindowPos3sARB) (GLshort x, GLshort y, GLshort z); + void (APIENTRY *WindowPos3svARB) (const GLshort *v); + void (APIENTRY *VertexAttrib1dARB) (GLuint index, GLdouble x); + void (APIENTRY *VertexAttrib1dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib1fARB) (GLuint index, GLfloat x); + void (APIENTRY *VertexAttrib1fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib1sARB) (GLuint index, GLshort x); + void (APIENTRY *VertexAttrib1svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib2dARB) (GLuint index, GLdouble x, GLdouble y); + void (APIENTRY *VertexAttrib2dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib2fARB) (GLuint index, GLfloat x, GLfloat y); + void (APIENTRY *VertexAttrib2fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib2sARB) (GLuint index, GLshort x, GLshort y); + void (APIENTRY *VertexAttrib2svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib3dARB) (GLuint index, GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *VertexAttrib3dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib3fARB) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *VertexAttrib3fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib3sARB) (GLuint index, GLshort x, GLshort y, GLshort z); + void (APIENTRY *VertexAttrib3svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4NbvARB) (GLuint index, const GLbyte *v); + void (APIENTRY *VertexAttrib4NivARB) (GLuint index, const GLint *v); + void (APIENTRY *VertexAttrib4NsvARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4NubARB) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + void (APIENTRY *VertexAttrib4NubvARB) (GLuint index, const GLubyte *v); + void (APIENTRY *VertexAttrib4NuivARB) (GLuint index, const GLuint *v); + void (APIENTRY *VertexAttrib4NusvARB) (GLuint index, const GLushort *v); + void (APIENTRY *VertexAttrib4bvARB) (GLuint index, const GLbyte *v); + void (APIENTRY *VertexAttrib4dARB) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *VertexAttrib4dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib4fARB) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *VertexAttrib4fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib4ivARB) (GLuint index, const GLint *v); + void (APIENTRY *VertexAttrib4sARB) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *VertexAttrib4svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4ubvARB) (GLuint index, const GLubyte *v); + void (APIENTRY *VertexAttrib4uivARB) (GLuint index, const GLuint *v); + void (APIENTRY *VertexAttrib4usvARB) (GLuint index, const GLushort *v); + void (APIENTRY *VertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *EnableVertexAttribArrayARB) (GLuint index); + void (APIENTRY *DisableVertexAttribArrayARB) (GLuint index); + void (APIENTRY *ProgramStringARB) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); + void (APIENTRY *BindProgramARB) (GLenum target, GLuint program); + void (APIENTRY *DeleteProgramsARB) (GLsizei n, const GLuint *programs); + void (APIENTRY *GenProgramsARB) (GLsizei n, GLuint *programs); + void (APIENTRY *ProgramEnvParameter4dARB) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramEnvParameter4dvARB) (GLenum target, GLuint index, const GLdouble *params); + void (APIENTRY *ProgramEnvParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramEnvParameter4fvARB) (GLenum target, GLuint index, const GLfloat *params); + void (APIENTRY *ProgramLocalParameter4dARB) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramLocalParameter4dvARB) (GLenum target, GLuint index, const GLdouble *params); + void (APIENTRY *ProgramLocalParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramLocalParameter4fvARB) (GLenum target, GLuint index, const GLfloat *params); + void (APIENTRY *GetProgramEnvParameterdvARB) (GLenum target, GLuint index, GLdouble *params); + void (APIENTRY *GetProgramEnvParameterfvARB) (GLenum target, GLuint index, GLfloat *params); + void (APIENTRY *GetProgramLocalParameterdvARB) (GLenum target, GLuint index, GLdouble *params); + void (APIENTRY *GetProgramLocalParameterfvARB) (GLenum target, GLuint index, GLfloat *params); + void (APIENTRY *GetProgramivARB) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetProgramStringARB) (GLenum target, GLenum pname, GLvoid *string); + void (APIENTRY *GetVertexAttribdvARB) (GLuint index, GLenum pname, GLdouble *params); + void (APIENTRY *GetVertexAttribfvARB) (GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetVertexAttribivARB) (GLuint index, GLenum pname, GLint *params); + void (APIENTRY *GetVertexAttribPointervARB) (GLuint index, GLenum pname, GLvoid* *pointer); + GLboolean (APIENTRY *IsProgramARB) (GLuint program); + void (APIENTRY *BindBufferARB) (GLenum target, GLuint buffer); + void (APIENTRY *DeleteBuffersARB) (GLsizei n, const GLuint *buffers); + void (APIENTRY *GenBuffersARB) (GLsizei n, GLuint *buffers); + GLboolean (APIENTRY *IsBufferARB) (GLuint buffer); + void (APIENTRY *BufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); + void (APIENTRY *BufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); + void (APIENTRY *GetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); + GLvoid* (APIENTRY *MapBufferARB) (GLenum target, GLenum access); + GLboolean (APIENTRY *UnmapBufferARB) (GLenum target); + void (APIENTRY *GetBufferParameterivARB) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetBufferPointervARB) (GLenum target, GLenum pname, GLvoid* *params); + void (APIENTRY *GenQueriesARB) (GLsizei n, GLuint *ids); + void (APIENTRY *DeleteQueriesARB) (GLsizei n, const GLuint *ids); + GLboolean (APIENTRY *IsQueryARB) (GLuint id); + void (APIENTRY *BeginQueryARB) (GLenum target, GLuint id); + void (APIENTRY *EndQueryARB) (GLenum target); + void (APIENTRY *GetQueryivARB) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectivARB) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectuivARB) (GLuint id, GLenum pname, GLuint *params); + void (APIENTRY *DeleteObjectARB) (GLhandleARB obj); + GLhandleARB (APIENTRY *GetHandleARB) (GLenum pname); + void (APIENTRY *DetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj); + GLhandleARB (APIENTRY *CreateShaderObjectARB) (GLenum shaderType); + void (APIENTRY *ShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); + void (APIENTRY *CompileShaderARB) (GLhandleARB shaderObj); + GLhandleARB (APIENTRY *CreateProgramObjectARB) (void); + void (APIENTRY *AttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj); + void (APIENTRY *LinkProgramARB) (GLhandleARB programObj); + void (APIENTRY *UseProgramObjectARB) (GLhandleARB programObj); + void (APIENTRY *ValidateProgramARB) (GLhandleARB programObj); + void (APIENTRY *Uniform1fARB) (GLint location, GLfloat v0); + void (APIENTRY *Uniform2fARB) (GLint location, GLfloat v0, GLfloat v1); + void (APIENTRY *Uniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); + void (APIENTRY *Uniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + void (APIENTRY *Uniform1iARB) (GLint location, GLint v0); + void (APIENTRY *Uniform2iARB) (GLint location, GLint v0, GLint v1); + void (APIENTRY *Uniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2); + void (APIENTRY *Uniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); + void (APIENTRY *Uniform1fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform2fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform3fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform4fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform1ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *Uniform2ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *Uniform3ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *Uniform4ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *UniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void (APIENTRY *UniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void (APIENTRY *UniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void (APIENTRY *GetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat *params); + void (APIENTRY *GetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint *params); + void (APIENTRY *GetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); + void (APIENTRY *GetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); + GLint (APIENTRY *GetUniformLocationARB) (GLhandleARB programObj, const GLcharARB *name); + void (APIENTRY *GetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); + void (APIENTRY *GetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat *params); + void (APIENTRY *GetUniformivARB) (GLhandleARB programObj, GLint location, GLint *params); + void (APIENTRY *GetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); + void (APIENTRY *BindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB *name); + void (APIENTRY *GetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); + GLint (APIENTRY *GetAttribLocationARB) (GLhandleARB programObj, const GLcharARB *name); + void (APIENTRY *BlendColorEXT) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void (APIENTRY *PolygonOffsetEXT) (GLfloat factor, GLfloat bias); + void (APIENTRY *TexImage3DEXT) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage3DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *GetTexFilterFuncSGIS) (GLenum target, GLenum filter, GLfloat *weights); + void (APIENTRY *TexFilterFuncSGIS) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); + void (APIENTRY *TexSubImage1DEXT) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage2DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *CopyTexImage1DEXT) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); + void (APIENTRY *CopyTexImage2DEXT) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + void (APIENTRY *CopyTexSubImage1DEXT) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); + void (APIENTRY *CopyTexSubImage2DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *CopyTexSubImage3DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *GetHistogramEXT) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetHistogramParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetHistogramParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetMinmaxEXT) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetMinmaxParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetMinmaxParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *HistogramEXT) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); + void (APIENTRY *MinmaxEXT) (GLenum target, GLenum internalformat, GLboolean sink); + void (APIENTRY *ResetHistogramEXT) (GLenum target); + void (APIENTRY *ResetMinmaxEXT) (GLenum target); + void (APIENTRY *ConvolutionFilter1DEXT) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionFilter2DEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionParameterfEXT) (GLenum target, GLenum pname, GLfloat params); + void (APIENTRY *ConvolutionParameterfvEXT) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ConvolutionParameteriEXT) (GLenum target, GLenum pname, GLint params); + void (APIENTRY *ConvolutionParameterivEXT) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyConvolutionFilter1DEXT) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *CopyConvolutionFilter2DEXT) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *GetConvolutionFilterEXT) (GLenum target, GLenum format, GLenum type, GLvoid *image); + void (APIENTRY *GetConvolutionParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetConvolutionParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetSeparableFilterEXT) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); + void (APIENTRY *SeparableFilter2DEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + void (APIENTRY *ColorTableSGI) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); + void (APIENTRY *ColorTableParameterfvSGI) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ColorTableParameterivSGI) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyColorTableSGI) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *GetColorTableSGI) (GLenum target, GLenum format, GLenum type, GLvoid *table); + void (APIENTRY *GetColorTableParameterfvSGI) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetColorTableParameterivSGI) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *PixelTexGenSGIX) (GLenum mode); + void (APIENTRY *PixelTexGenParameteriSGIS) (GLenum pname, GLint param); + void (APIENTRY *PixelTexGenParameterivSGIS) (GLenum pname, const GLint *params); + void (APIENTRY *PixelTexGenParameterfSGIS) (GLenum pname, GLfloat param); + void (APIENTRY *PixelTexGenParameterfvSGIS) (GLenum pname, const GLfloat *params); + void (APIENTRY *GetPixelTexGenParameterivSGIS) (GLenum pname, GLint *params); + void (APIENTRY *GetPixelTexGenParameterfvSGIS) (GLenum pname, GLfloat *params); + void (APIENTRY *TexImage4DSGIS) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage4DSGIS) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); + GLboolean (APIENTRY *AreTexturesResidentEXT) (GLsizei n, const GLuint *textures, GLboolean *residences); + void (APIENTRY *BindTextureEXT) (GLenum target, GLuint texture); + void (APIENTRY *DeleteTexturesEXT) (GLsizei n, const GLuint *textures); + void (APIENTRY *GenTexturesEXT) (GLsizei n, GLuint *textures); + GLboolean (APIENTRY *IsTextureEXT) (GLuint texture); + void (APIENTRY *PrioritizeTexturesEXT) (GLsizei n, const GLuint *textures, const GLclampf *priorities); + void (APIENTRY *DetailTexFuncSGIS) (GLenum target, GLsizei n, const GLfloat *points); + void (APIENTRY *GetDetailTexFuncSGIS) (GLenum target, GLfloat *points); + void (APIENTRY *SharpenTexFuncSGIS) (GLenum target, GLsizei n, const GLfloat *points); + void (APIENTRY *GetSharpenTexFuncSGIS) (GLenum target, GLfloat *points); + void (APIENTRY *SampleMaskSGIS) (GLclampf value, GLboolean invert); + void (APIENTRY *SamplePatternSGIS) (GLenum pattern); + void (APIENTRY *ArrayElementEXT) (GLint i); + void (APIENTRY *ColorPointerEXT) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *DrawArraysEXT) (GLenum mode, GLint first, GLsizei count); + void (APIENTRY *EdgeFlagPointerEXT) (GLsizei stride, GLsizei count, const GLboolean *pointer); + void (APIENTRY *GetPointervEXT) (GLenum pname, GLvoid* *params); + void (APIENTRY *IndexPointerEXT) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *NormalPointerEXT) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *TexCoordPointerEXT) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *VertexPointerEXT) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *BlendEquationEXT) (GLenum mode); + void (APIENTRY *SpriteParameterfSGIX) (GLenum pname, GLfloat param); + void (APIENTRY *SpriteParameterfvSGIX) (GLenum pname, const GLfloat *params); + void (APIENTRY *SpriteParameteriSGIX) (GLenum pname, GLint param); + void (APIENTRY *SpriteParameterivSGIX) (GLenum pname, const GLint *params); + void (APIENTRY *PointParameterfEXT) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfvEXT) (GLenum pname, const GLfloat *params); + void (APIENTRY *PointParameterfSGIS) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfvSGIS) (GLenum pname, const GLfloat *params); + GLint (APIENTRY *GetInstrumentsSGIX) (void); + void (APIENTRY *InstrumentsBufferSGIX) (GLsizei size, GLint *buffer); + GLint (APIENTRY *PollInstrumentsSGIX) (GLint *marker_p); + void (APIENTRY *ReadInstrumentsSGIX) (GLint marker); + void (APIENTRY *StartInstrumentsSGIX) (void); + void (APIENTRY *StopInstrumentsSGIX) (GLint marker); + void (APIENTRY *FrameZoomSGIX) (GLint factor); + void (APIENTRY *TagSampleBufferSGIX) (void); + void (APIENTRY *DeformationMap3dSGIX) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); + void (APIENTRY *DeformationMap3fSGIX) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); + void (APIENTRY *DeformSGIX) (GLbitfield mask); + void (APIENTRY *LoadIdentityDeformationMapSGIX) (GLbitfield mask); + void (APIENTRY *ReferencePlaneSGIX) (const GLdouble *equation); + void (APIENTRY *FlushRasterSGIX) (void); + void (APIENTRY *FogFuncSGIS) (GLsizei n, const GLfloat *points); + void (APIENTRY *GetFogFuncSGIS) (GLfloat *points); + void (APIENTRY *ImageTransformParameteriHP) (GLenum target, GLenum pname, GLint param); + void (APIENTRY *ImageTransformParameterfHP) (GLenum target, GLenum pname, GLfloat param); + void (APIENTRY *ImageTransformParameterivHP) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *ImageTransformParameterfvHP) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *GetImageTransformParameterivHP) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetImageTransformParameterfvHP) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *ColorSubTableEXT) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); + void (APIENTRY *CopyColorSubTableEXT) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + void (APIENTRY *HintPGI) (GLenum target, GLint mode); + void (APIENTRY *ColorTableEXT) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); + void (APIENTRY *GetColorTableEXT) (GLenum target, GLenum format, GLenum type, GLvoid *data); + void (APIENTRY *GetColorTableParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetColorTableParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetListParameterfvSGIX) (GLuint list, GLenum pname, GLfloat *params); + void (APIENTRY *GetListParameterivSGIX) (GLuint list, GLenum pname, GLint *params); + void (APIENTRY *ListParameterfSGIX) (GLuint list, GLenum pname, GLfloat param); + void (APIENTRY *ListParameterfvSGIX) (GLuint list, GLenum pname, const GLfloat *params); + void (APIENTRY *ListParameteriSGIX) (GLuint list, GLenum pname, GLint param); + void (APIENTRY *ListParameterivSGIX) (GLuint list, GLenum pname, const GLint *params); + void (APIENTRY *IndexMaterialEXT) (GLenum face, GLenum mode); + void (APIENTRY *IndexFuncEXT) (GLenum func, GLclampf ref); + void (APIENTRY *LockArraysEXT) (GLint first, GLsizei count); + void (APIENTRY *UnlockArraysEXT) (void); + void (APIENTRY *CullParameterdvEXT) (GLenum pname, GLdouble *params); + void (APIENTRY *CullParameterfvEXT) (GLenum pname, GLfloat *params); + void (APIENTRY *FragmentColorMaterialSGIX) (GLenum face, GLenum mode); + void (APIENTRY *FragmentLightfSGIX) (GLenum light, GLenum pname, GLfloat param); + void (APIENTRY *FragmentLightfvSGIX) (GLenum light, GLenum pname, const GLfloat *params); + void (APIENTRY *FragmentLightiSGIX) (GLenum light, GLenum pname, GLint param); + void (APIENTRY *FragmentLightivSGIX) (GLenum light, GLenum pname, const GLint *params); + void (APIENTRY *FragmentLightModelfSGIX) (GLenum pname, GLfloat param); + void (APIENTRY *FragmentLightModelfvSGIX) (GLenum pname, const GLfloat *params); + void (APIENTRY *FragmentLightModeliSGIX) (GLenum pname, GLint param); + void (APIENTRY *FragmentLightModelivSGIX) (GLenum pname, const GLint *params); + void (APIENTRY *FragmentMaterialfSGIX) (GLenum face, GLenum pname, GLfloat param); + void (APIENTRY *FragmentMaterialfvSGIX) (GLenum face, GLenum pname, const GLfloat *params); + void (APIENTRY *FragmentMaterialiSGIX) (GLenum face, GLenum pname, GLint param); + void (APIENTRY *FragmentMaterialivSGIX) (GLenum face, GLenum pname, const GLint *params); + void (APIENTRY *GetFragmentLightfvSGIX) (GLenum light, GLenum pname, GLfloat *params); + void (APIENTRY *GetFragmentLightivSGIX) (GLenum light, GLenum pname, GLint *params); + void (APIENTRY *GetFragmentMaterialfvSGIX) (GLenum face, GLenum pname, GLfloat *params); + void (APIENTRY *GetFragmentMaterialivSGIX) (GLenum face, GLenum pname, GLint *params); + void (APIENTRY *LightEnviSGIX) (GLenum pname, GLint param); + void (APIENTRY *DrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + void (APIENTRY *ApplyTextureEXT) (GLenum mode); + void (APIENTRY *TextureLightEXT) (GLenum pname); + void (APIENTRY *TextureMaterialEXT) (GLenum face, GLenum mode); + void (APIENTRY *AsyncMarkerSGIX) (GLuint marker); + GLint (APIENTRY *FinishAsyncSGIX) (GLuint *markerp); + GLint (APIENTRY *PollAsyncSGIX) (GLuint *markerp); + GLuint (APIENTRY *GenAsyncMarkersSGIX) (GLsizei range); + void (APIENTRY *DeleteAsyncMarkersSGIX) (GLuint marker, GLsizei range); + GLboolean (APIENTRY *IsAsyncMarkerSGIX) (GLuint marker); + void (APIENTRY *VertexPointervINTEL) (GLint size, GLenum type, const GLvoid* *pointer); + void (APIENTRY *NormalPointervINTEL) (GLenum type, const GLvoid* *pointer); + void (APIENTRY *ColorPointervINTEL) (GLint size, GLenum type, const GLvoid* *pointer); + void (APIENTRY *TexCoordPointervINTEL) (GLint size, GLenum type, const GLvoid* *pointer); + void (APIENTRY *PixelTransformParameteriEXT) (GLenum target, GLenum pname, GLint param); + void (APIENTRY *PixelTransformParameterfEXT) (GLenum target, GLenum pname, GLfloat param); + void (APIENTRY *PixelTransformParameterivEXT) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *PixelTransformParameterfvEXT) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *SecondaryColor3bEXT) (GLbyte red, GLbyte green, GLbyte blue); + void (APIENTRY *SecondaryColor3bvEXT) (const GLbyte *v); + void (APIENTRY *SecondaryColor3dEXT) (GLdouble red, GLdouble green, GLdouble blue); + void (APIENTRY *SecondaryColor3dvEXT) (const GLdouble *v); + void (APIENTRY *SecondaryColor3fEXT) (GLfloat red, GLfloat green, GLfloat blue); + void (APIENTRY *SecondaryColor3fvEXT) (const GLfloat *v); + void (APIENTRY *SecondaryColor3iEXT) (GLint red, GLint green, GLint blue); + void (APIENTRY *SecondaryColor3ivEXT) (const GLint *v); + void (APIENTRY *SecondaryColor3sEXT) (GLshort red, GLshort green, GLshort blue); + void (APIENTRY *SecondaryColor3svEXT) (const GLshort *v); + void (APIENTRY *SecondaryColor3ubEXT) (GLubyte red, GLubyte green, GLubyte blue); + void (APIENTRY *SecondaryColor3ubvEXT) (const GLubyte *v); + void (APIENTRY *SecondaryColor3uiEXT) (GLuint red, GLuint green, GLuint blue); + void (APIENTRY *SecondaryColor3uivEXT) (const GLuint *v); + void (APIENTRY *SecondaryColor3usEXT) (GLushort red, GLushort green, GLushort blue); + void (APIENTRY *SecondaryColor3usvEXT) (const GLushort *v); + void (APIENTRY *SecondaryColorPointerEXT) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *TextureNormalEXT) (GLenum mode); + void (APIENTRY *MultiDrawArraysEXT) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); + void (APIENTRY *MultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); + void (APIENTRY *FogCoordfEXT) (GLfloat coord); + void (APIENTRY *FogCoordfvEXT) (const GLfloat *coord); + void (APIENTRY *FogCoorddEXT) (GLdouble coord); + void (APIENTRY *FogCoorddvEXT) (const GLdouble *coord); + void (APIENTRY *FogCoordPointerEXT) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *Tangent3bEXT) (GLbyte tx, GLbyte ty, GLbyte tz); + void (APIENTRY *Tangent3bvEXT) (const GLbyte *v); + void (APIENTRY *Tangent3dEXT) (GLdouble tx, GLdouble ty, GLdouble tz); + void (APIENTRY *Tangent3dvEXT) (const GLdouble *v); + void (APIENTRY *Tangent3fEXT) (GLfloat tx, GLfloat ty, GLfloat tz); + void (APIENTRY *Tangent3fvEXT) (const GLfloat *v); + void (APIENTRY *Tangent3iEXT) (GLint tx, GLint ty, GLint tz); + void (APIENTRY *Tangent3ivEXT) (const GLint *v); + void (APIENTRY *Tangent3sEXT) (GLshort tx, GLshort ty, GLshort tz); + void (APIENTRY *Tangent3svEXT) (const GLshort *v); + void (APIENTRY *Binormal3bEXT) (GLbyte bx, GLbyte by, GLbyte bz); + void (APIENTRY *Binormal3bvEXT) (const GLbyte *v); + void (APIENTRY *Binormal3dEXT) (GLdouble bx, GLdouble by, GLdouble bz); + void (APIENTRY *Binormal3dvEXT) (const GLdouble *v); + void (APIENTRY *Binormal3fEXT) (GLfloat bx, GLfloat by, GLfloat bz); + void (APIENTRY *Binormal3fvEXT) (const GLfloat *v); + void (APIENTRY *Binormal3iEXT) (GLint bx, GLint by, GLint bz); + void (APIENTRY *Binormal3ivEXT) (const GLint *v); + void (APIENTRY *Binormal3sEXT) (GLshort bx, GLshort by, GLshort bz); + void (APIENTRY *Binormal3svEXT) (const GLshort *v); + void (APIENTRY *TangentPointerEXT) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *BinormalPointerEXT) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *FinishTextureSUNX) (void); + void (APIENTRY *GlobalAlphaFactorbSUN) (GLbyte factor); + void (APIENTRY *GlobalAlphaFactorsSUN) (GLshort factor); + void (APIENTRY *GlobalAlphaFactoriSUN) (GLint factor); + void (APIENTRY *GlobalAlphaFactorfSUN) (GLfloat factor); + void (APIENTRY *GlobalAlphaFactordSUN) (GLdouble factor); + void (APIENTRY *GlobalAlphaFactorubSUN) (GLubyte factor); + void (APIENTRY *GlobalAlphaFactorusSUN) (GLushort factor); + void (APIENTRY *GlobalAlphaFactoruiSUN) (GLuint factor); + void (APIENTRY *ReplacementCodeuiSUN) (GLuint code); + void (APIENTRY *ReplacementCodeusSUN) (GLushort code); + void (APIENTRY *ReplacementCodeubSUN) (GLubyte code); + void (APIENTRY *ReplacementCodeuivSUN) (const GLuint *code); + void (APIENTRY *ReplacementCodeusvSUN) (const GLushort *code); + void (APIENTRY *ReplacementCodeubvSUN) (const GLubyte *code); + void (APIENTRY *ReplacementCodePointerSUN) (GLenum type, GLsizei stride, const GLvoid* *pointer); + void (APIENTRY *Color4ubVertex2fSUN) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); + void (APIENTRY *Color4ubVertex2fvSUN) (const GLubyte *c, const GLfloat *v); + void (APIENTRY *Color4ubVertex3fSUN) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Color4ubVertex3fvSUN) (const GLubyte *c, const GLfloat *v); + void (APIENTRY *Color3fVertex3fSUN) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Color3fVertex3fvSUN) (const GLfloat *c, const GLfloat *v); + void (APIENTRY *Normal3fVertex3fSUN) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Normal3fVertex3fvSUN) (const GLfloat *n, const GLfloat *v); + void (APIENTRY *Color4fNormal3fVertex3fSUN) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Color4fNormal3fVertex3fvSUN) (const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *TexCoord2fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fVertex3fvSUN) (const GLfloat *tc, const GLfloat *v); + void (APIENTRY *TexCoord4fVertex4fSUN) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *TexCoord4fVertex4fvSUN) (const GLfloat *tc, const GLfloat *v); + void (APIENTRY *TexCoord2fColor4ubVertex3fSUN) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fColor4ubVertex3fvSUN) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); + void (APIENTRY *TexCoord2fColor3fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fColor3fVertex3fvSUN) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); + void (APIENTRY *TexCoord2fNormal3fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fNormal3fVertex3fvSUN) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); + void (APIENTRY *TexCoord2fColor4fNormal3fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fColor4fNormal3fVertex3fvSUN) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *TexCoord4fColor4fNormal3fVertex4fSUN) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *TexCoord4fColor4fNormal3fVertex4fvSUN) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiVertex3fSUN) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiVertex3fvSUN) (const GLuint *rc, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiColor4ubVertex3fSUN) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiColor4ubVertex3fvSUN) (const GLuint *rc, const GLubyte *c, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiColor3fVertex3fSUN) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiColor3fVertex3fvSUN) (const GLuint *rc, const GLfloat *c, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiNormal3fVertex3fSUN) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiColor4fNormal3fVertex3fSUN) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiColor4fNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiTexCoord2fVertex3fSUN) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiTexCoord2fVertex3fvSUN) (const GLuint *rc, const GLfloat *tc, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *BlendFuncSeparateEXT) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + void (APIENTRY *BlendFuncSeparateINGR) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + void (APIENTRY *VertexWeightfEXT) (GLfloat weight); + void (APIENTRY *VertexWeightfvEXT) (const GLfloat *weight); + void (APIENTRY *VertexWeightPointerEXT) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *FlushVertexArrayRangeNV) (void); + void (APIENTRY *VertexArrayRangeNV) (GLsizei length, const GLvoid *pointer); + void (APIENTRY *CombinerParameterfvNV) (GLenum pname, const GLfloat *params); + void (APIENTRY *CombinerParameterfNV) (GLenum pname, GLfloat param); + void (APIENTRY *CombinerParameterivNV) (GLenum pname, const GLint *params); + void (APIENTRY *CombinerParameteriNV) (GLenum pname, GLint param); + void (APIENTRY *CombinerInputNV) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); + void (APIENTRY *CombinerOutputNV) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); + void (APIENTRY *FinalCombinerInputNV) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); + void (APIENTRY *GetCombinerInputParameterfvNV) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); + void (APIENTRY *GetCombinerInputParameterivNV) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); + void (APIENTRY *GetCombinerOutputParameterfvNV) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); + void (APIENTRY *GetCombinerOutputParameterivNV) (GLenum stage, GLenum portion, GLenum pname, GLint *params); + void (APIENTRY *GetFinalCombinerInputParameterfvNV) (GLenum variable, GLenum pname, GLfloat *params); + void (APIENTRY *GetFinalCombinerInputParameterivNV) (GLenum variable, GLenum pname, GLint *params); + void (APIENTRY *ResizeBuffersMESA) (void); + void (APIENTRY *WindowPos2dMESA) (GLdouble x, GLdouble y); + void (APIENTRY *WindowPos2dvMESA) (const GLdouble *v); + void (APIENTRY *WindowPos2fMESA) (GLfloat x, GLfloat y); + void (APIENTRY *WindowPos2fvMESA) (const GLfloat *v); + void (APIENTRY *WindowPos2iMESA) (GLint x, GLint y); + void (APIENTRY *WindowPos2ivMESA) (const GLint *v); + void (APIENTRY *WindowPos2sMESA) (GLshort x, GLshort y); + void (APIENTRY *WindowPos2svMESA) (const GLshort *v); + void (APIENTRY *WindowPos3dMESA) (GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *WindowPos3dvMESA) (const GLdouble *v); + void (APIENTRY *WindowPos3fMESA) (GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *WindowPos3fvMESA) (const GLfloat *v); + void (APIENTRY *WindowPos3iMESA) (GLint x, GLint y, GLint z); + void (APIENTRY *WindowPos3ivMESA) (const GLint *v); + void (APIENTRY *WindowPos3sMESA) (GLshort x, GLshort y, GLshort z); + void (APIENTRY *WindowPos3svMESA) (const GLshort *v); + void (APIENTRY *WindowPos4dMESA) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *WindowPos4dvMESA) (const GLdouble *v); + void (APIENTRY *WindowPos4fMESA) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *WindowPos4fvMESA) (const GLfloat *v); + void (APIENTRY *WindowPos4iMESA) (GLint x, GLint y, GLint z, GLint w); + void (APIENTRY *WindowPos4ivMESA) (const GLint *v); + void (APIENTRY *WindowPos4sMESA) (GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *WindowPos4svMESA) (const GLshort *v); + void (APIENTRY *MultiModeDrawArraysIBM) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); + void (APIENTRY *MultiModeDrawElementsIBM) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride); + void (APIENTRY *ColorPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *SecondaryColorPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *EdgeFlagPointerListIBM) (GLint stride, const GLboolean* *pointer, GLint ptrstride); + void (APIENTRY *FogCoordPointerListIBM) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *IndexPointerListIBM) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *NormalPointerListIBM) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *TexCoordPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *VertexPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *TbufferMask3DFX) (GLuint mask); + void (APIENTRY *SampleMaskEXT) (GLclampf value, GLboolean invert); + void (APIENTRY *SamplePatternEXT) (GLenum pattern); + void (APIENTRY *TextureColorMaskSGIS) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + void (APIENTRY *IglooInterfaceSGIX) (GLenum pname, const GLvoid *params); + void (APIENTRY *DeleteFencesNV) (GLsizei n, const GLuint *fences); + void (APIENTRY *GenFencesNV) (GLsizei n, GLuint *fences); + GLboolean (APIENTRY *IsFenceNV) (GLuint fence); + GLboolean (APIENTRY *TestFenceNV) (GLuint fence); + void (APIENTRY *GetFenceivNV) (GLuint fence, GLenum pname, GLint *params); + void (APIENTRY *FinishFenceNV) (GLuint fence); + void (APIENTRY *SetFenceNV) (GLuint fence, GLenum condition); + void (APIENTRY *MapControlPointsNV) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); + void (APIENTRY *MapParameterivNV) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *MapParameterfvNV) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *GetMapControlPointsNV) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); + void (APIENTRY *GetMapParameterivNV) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetMapParameterfvNV) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetMapAttribParameterivNV) (GLenum target, GLuint index, GLenum pname, GLint *params); + void (APIENTRY *GetMapAttribParameterfvNV) (GLenum target, GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *EvalMapsNV) (GLenum target, GLenum mode); + void (APIENTRY *CombinerStageParameterfvNV) (GLenum stage, GLenum pname, const GLfloat *params); + void (APIENTRY *GetCombinerStageParameterfvNV) (GLenum stage, GLenum pname, GLfloat *params); + GLboolean (APIENTRY *AreProgramsResidentNV) (GLsizei n, const GLuint *programs, GLboolean *residences); + void (APIENTRY *BindProgramNV) (GLenum target, GLuint id); + void (APIENTRY *DeleteProgramsNV) (GLsizei n, const GLuint *programs); + void (APIENTRY *ExecuteProgramNV) (GLenum target, GLuint id, const GLfloat *params); + void (APIENTRY *GenProgramsNV) (GLsizei n, GLuint *programs); + void (APIENTRY *GetProgramParameterdvNV) (GLenum target, GLuint index, GLenum pname, GLdouble *params); + void (APIENTRY *GetProgramParameterfvNV) (GLenum target, GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetProgramivNV) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetProgramStringNV) (GLuint id, GLenum pname, GLubyte *program); + void (APIENTRY *GetTrackMatrixivNV) (GLenum target, GLuint address, GLenum pname, GLint *params); + void (APIENTRY *GetVertexAttribdvNV) (GLuint index, GLenum pname, GLdouble *params); + void (APIENTRY *GetVertexAttribfvNV) (GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetVertexAttribivNV) (GLuint index, GLenum pname, GLint *params); + void (APIENTRY *GetVertexAttribPointervNV) (GLuint index, GLenum pname, GLvoid* *pointer); + GLboolean (APIENTRY *IsProgramNV) (GLuint id); + void (APIENTRY *LoadProgramNV) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); + void (APIENTRY *ProgramParameter4dNV) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramParameter4dvNV) (GLenum target, GLuint index, const GLdouble *v); + void (APIENTRY *ProgramParameter4fNV) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramParameter4fvNV) (GLenum target, GLuint index, const GLfloat *v); + void (APIENTRY *ProgramParameters4dvNV) (GLenum target, GLuint index, GLuint count, const GLdouble *v); + void (APIENTRY *ProgramParameters4fvNV) (GLenum target, GLuint index, GLuint count, const GLfloat *v); + void (APIENTRY *RequestResidentProgramsNV) (GLsizei n, const GLuint *programs); + void (APIENTRY *TrackMatrixNV) (GLenum target, GLuint address, GLenum matrix, GLenum transform); + void (APIENTRY *VertexAttribPointerNV) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *VertexAttrib1dNV) (GLuint index, GLdouble x); + void (APIENTRY *VertexAttrib1dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib1fNV) (GLuint index, GLfloat x); + void (APIENTRY *VertexAttrib1fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib1sNV) (GLuint index, GLshort x); + void (APIENTRY *VertexAttrib1svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib2dNV) (GLuint index, GLdouble x, GLdouble y); + void (APIENTRY *VertexAttrib2dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib2fNV) (GLuint index, GLfloat x, GLfloat y); + void (APIENTRY *VertexAttrib2fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib2sNV) (GLuint index, GLshort x, GLshort y); + void (APIENTRY *VertexAttrib2svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib3dNV) (GLuint index, GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *VertexAttrib3dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib3fNV) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *VertexAttrib3fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib3sNV) (GLuint index, GLshort x, GLshort y, GLshort z); + void (APIENTRY *VertexAttrib3svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4dNV) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *VertexAttrib4dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib4fNV) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *VertexAttrib4fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib4sNV) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *VertexAttrib4svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4ubNV) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + void (APIENTRY *VertexAttrib4ubvNV) (GLuint index, const GLubyte *v); + void (APIENTRY *VertexAttribs1dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs1fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs1svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs2dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs2fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs2svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs3dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs3fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs3svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs4dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs4fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs4svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs4ubvNV) (GLuint index, GLsizei count, const GLubyte *v); + void (APIENTRY *TexBumpParameterivATI) (GLenum pname, const GLint *param); + void (APIENTRY *TexBumpParameterfvATI) (GLenum pname, const GLfloat *param); + void (APIENTRY *GetTexBumpParameterivATI) (GLenum pname, GLint *param); + void (APIENTRY *GetTexBumpParameterfvATI) (GLenum pname, GLfloat *param); + GLuint (APIENTRY *GenFragmentShadersATI) (GLuint range); + void (APIENTRY *BindFragmentShaderATI) (GLuint id); + void (APIENTRY *DeleteFragmentShaderATI) (GLuint id); + void (APIENTRY *BeginFragmentShaderATI) (void); + void (APIENTRY *EndFragmentShaderATI) (void); + void (APIENTRY *PassTexCoordATI) (GLuint dst, GLuint coord, GLenum swizzle); + void (APIENTRY *SampleMapATI) (GLuint dst, GLuint interp, GLenum swizzle); + void (APIENTRY *ColorFragmentOp1ATI) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); + void (APIENTRY *ColorFragmentOp2ATI) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); + void (APIENTRY *ColorFragmentOp3ATI) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); + void (APIENTRY *AlphaFragmentOp1ATI) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); + void (APIENTRY *AlphaFragmentOp2ATI) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); + void (APIENTRY *AlphaFragmentOp3ATI) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); + void (APIENTRY *SetFragmentShaderConstantATI) (GLuint dst, const GLfloat *value); + void (APIENTRY *PNTrianglesiATI) (GLenum pname, GLint param); + void (APIENTRY *PNTrianglesfATI) (GLenum pname, GLfloat param); + GLuint (APIENTRY *NewObjectBufferATI) (GLsizei size, const GLvoid *pointer, GLenum usage); + GLboolean (APIENTRY *IsObjectBufferATI) (GLuint buffer); + void (APIENTRY *UpdateObjectBufferATI) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); + void (APIENTRY *GetObjectBufferfvATI) (GLuint buffer, GLenum pname, GLfloat *params); + void (APIENTRY *GetObjectBufferivATI) (GLuint buffer, GLenum pname, GLint *params); + void (APIENTRY *FreeObjectBufferATI) (GLuint buffer); + void (APIENTRY *ArrayObjectATI) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + void (APIENTRY *GetArrayObjectfvATI) (GLenum array, GLenum pname, GLfloat *params); + void (APIENTRY *GetArrayObjectivATI) (GLenum array, GLenum pname, GLint *params); + void (APIENTRY *VariantArrayObjectATI) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + void (APIENTRY *GetVariantArrayObjectfvATI) (GLuint id, GLenum pname, GLfloat *params); + void (APIENTRY *GetVariantArrayObjectivATI) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *BeginVertexShaderEXT) (void); + void (APIENTRY *EndVertexShaderEXT) (void); + void (APIENTRY *BindVertexShaderEXT) (GLuint id); + GLuint (APIENTRY *GenVertexShadersEXT) (GLuint range); + void (APIENTRY *DeleteVertexShaderEXT) (GLuint id); + void (APIENTRY *ShaderOp1EXT) (GLenum op, GLuint res, GLuint arg1); + void (APIENTRY *ShaderOp2EXT) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); + void (APIENTRY *ShaderOp3EXT) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); + void (APIENTRY *SwizzleEXT) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + void (APIENTRY *WriteMaskEXT) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + void (APIENTRY *InsertComponentEXT) (GLuint res, GLuint src, GLuint num); + void (APIENTRY *ExtractComponentEXT) (GLuint res, GLuint src, GLuint num); + GLuint (APIENTRY *GenSymbolsEXT) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); + void (APIENTRY *SetInvariantEXT) (GLuint id, GLenum type, const GLvoid *addr); + void (APIENTRY *SetLocalConstantEXT) (GLuint id, GLenum type, const GLvoid *addr); + void (APIENTRY *VariantbvEXT) (GLuint id, const GLbyte *addr); + void (APIENTRY *VariantsvEXT) (GLuint id, const GLshort *addr); + void (APIENTRY *VariantivEXT) (GLuint id, const GLint *addr); + void (APIENTRY *VariantfvEXT) (GLuint id, const GLfloat *addr); + void (APIENTRY *VariantdvEXT) (GLuint id, const GLdouble *addr); + void (APIENTRY *VariantubvEXT) (GLuint id, const GLubyte *addr); + void (APIENTRY *VariantusvEXT) (GLuint id, const GLushort *addr); + void (APIENTRY *VariantuivEXT) (GLuint id, const GLuint *addr); + void (APIENTRY *VariantPointerEXT) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr); + void (APIENTRY *EnableVariantClientStateEXT) (GLuint id); + void (APIENTRY *DisableVariantClientStateEXT) (GLuint id); + GLuint (APIENTRY *BindLightParameterEXT) (GLenum light, GLenum value); + GLuint (APIENTRY *BindMaterialParameterEXT) (GLenum face, GLenum value); + GLuint (APIENTRY *BindTexGenParameterEXT) (GLenum unit, GLenum coord, GLenum value); + GLuint (APIENTRY *BindTextureUnitParameterEXT) (GLenum unit, GLenum value); + GLuint (APIENTRY *BindParameterEXT) (GLenum value); + GLboolean (APIENTRY *IsVariantEnabledEXT) (GLuint id, GLenum cap); + void (APIENTRY *GetVariantBooleanvEXT) (GLuint id, GLenum value, GLboolean *data); + void (APIENTRY *GetVariantIntegervEXT) (GLuint id, GLenum value, GLint *data); + void (APIENTRY *GetVariantFloatvEXT) (GLuint id, GLenum value, GLfloat *data); + void (APIENTRY *GetVariantPointervEXT) (GLuint id, GLenum value, GLvoid* *data); + void (APIENTRY *GetInvariantBooleanvEXT) (GLuint id, GLenum value, GLboolean *data); + void (APIENTRY *GetInvariantIntegervEXT) (GLuint id, GLenum value, GLint *data); + void (APIENTRY *GetInvariantFloatvEXT) (GLuint id, GLenum value, GLfloat *data); + void (APIENTRY *GetLocalConstantBooleanvEXT) (GLuint id, GLenum value, GLboolean *data); + void (APIENTRY *GetLocalConstantIntegervEXT) (GLuint id, GLenum value, GLint *data); + void (APIENTRY *GetLocalConstantFloatvEXT) (GLuint id, GLenum value, GLfloat *data); + void (APIENTRY *VertexStream1sATI) (GLenum stream, GLshort x); + void (APIENTRY *VertexStream1svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream1iATI) (GLenum stream, GLint x); + void (APIENTRY *VertexStream1ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream1fATI) (GLenum stream, GLfloat x); + void (APIENTRY *VertexStream1fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream1dATI) (GLenum stream, GLdouble x); + void (APIENTRY *VertexStream1dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *VertexStream2sATI) (GLenum stream, GLshort x, GLshort y); + void (APIENTRY *VertexStream2svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream2iATI) (GLenum stream, GLint x, GLint y); + void (APIENTRY *VertexStream2ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream2fATI) (GLenum stream, GLfloat x, GLfloat y); + void (APIENTRY *VertexStream2fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream2dATI) (GLenum stream, GLdouble x, GLdouble y); + void (APIENTRY *VertexStream2dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *VertexStream3sATI) (GLenum stream, GLshort x, GLshort y, GLshort z); + void (APIENTRY *VertexStream3svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream3iATI) (GLenum stream, GLint x, GLint y, GLint z); + void (APIENTRY *VertexStream3ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream3fATI) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *VertexStream3fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream3dATI) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *VertexStream3dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *VertexStream4sATI) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *VertexStream4svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream4iATI) (GLenum stream, GLint x, GLint y, GLint z, GLint w); + void (APIENTRY *VertexStream4ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream4fATI) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *VertexStream4fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream4dATI) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *VertexStream4dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *NormalStream3bATI) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); + void (APIENTRY *NormalStream3bvATI) (GLenum stream, const GLbyte *coords); + void (APIENTRY *NormalStream3sATI) (GLenum stream, GLshort nx, GLshort ny, GLshort nz); + void (APIENTRY *NormalStream3svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *NormalStream3iATI) (GLenum stream, GLint nx, GLint ny, GLint nz); + void (APIENTRY *NormalStream3ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *NormalStream3fATI) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); + void (APIENTRY *NormalStream3fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *NormalStream3dATI) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); + void (APIENTRY *NormalStream3dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *ClientActiveVertexStreamATI) (GLenum stream); + void (APIENTRY *VertexBlendEnviATI) (GLenum pname, GLint param); + void (APIENTRY *VertexBlendEnvfATI) (GLenum pname, GLfloat param); + void (APIENTRY *ElementPointerATI) (GLenum type, const GLvoid *pointer); + void (APIENTRY *DrawElementArrayATI) (GLenum mode, GLsizei count); + void (APIENTRY *DrawRangeElementArrayATI) (GLenum mode, GLuint start, GLuint end, GLsizei count); + void (APIENTRY *DrawMeshArraysSUN) (GLenum mode, GLint first, GLsizei count, GLsizei width); + void (APIENTRY *GenOcclusionQueriesNV) (GLsizei n, GLuint *ids); + void (APIENTRY *DeleteOcclusionQueriesNV) (GLsizei n, const GLuint *ids); + GLboolean (APIENTRY *IsOcclusionQueryNV) (GLuint id); + void (APIENTRY *BeginOcclusionQueryNV) (GLuint id); + void (APIENTRY *EndOcclusionQueryNV) (void); + void (APIENTRY *GetOcclusionQueryivNV) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetOcclusionQueryuivNV) (GLuint id, GLenum pname, GLuint *params); + void (APIENTRY *PointParameteriNV) (GLenum pname, GLint param); + void (APIENTRY *PointParameterivNV) (GLenum pname, const GLint *params); + void (APIENTRY *ActiveStencilFaceEXT) (GLenum face); + void (APIENTRY *ElementPointerAPPLE) (GLenum type, const GLvoid *pointer); + void (APIENTRY *DrawElementArrayAPPLE) (GLenum mode, GLint first, GLsizei count); + void (APIENTRY *DrawRangeElementArrayAPPLE) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); + void (APIENTRY *MultiDrawElementArrayAPPLE) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); + void (APIENTRY *MultiDrawRangeElementArrayAPPLE) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); + void (APIENTRY *GenFencesAPPLE) (GLsizei n, GLuint *fences); + void (APIENTRY *DeleteFencesAPPLE) (GLsizei n, const GLuint *fences); + void (APIENTRY *SetFenceAPPLE) (GLuint fence); + GLboolean (APIENTRY *IsFenceAPPLE) (GLuint fence); + GLboolean (APIENTRY *TestFenceAPPLE) (GLuint fence); + void (APIENTRY *FinishFenceAPPLE) (GLuint fence); + GLboolean (APIENTRY *TestObjectAPPLE) (GLenum object, GLuint name); + void (APIENTRY *FinishObjectAPPLE) (GLenum object, GLint name); + void (APIENTRY *BindVertexArrayAPPLE) (GLuint array); + void (APIENTRY *DeleteVertexArraysAPPLE) (GLsizei n, const GLuint *arrays); + void (APIENTRY *GenVertexArraysAPPLE) (GLsizei n, const GLuint *arrays); + GLboolean (APIENTRY *IsVertexArrayAPPLE) (GLuint array); + void (APIENTRY *VertexArrayRangeAPPLE) (GLsizei length, GLvoid *pointer); + void (APIENTRY *FlushVertexArrayRangeAPPLE) (GLsizei length, GLvoid *pointer); + void (APIENTRY *VertexArrayParameteriAPPLE) (GLenum pname, GLint param); + void (APIENTRY *DrawBuffersATI) (GLsizei n, const GLenum *bufs); + void (APIENTRY *ProgramNamedParameter4fNV) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramNamedParameter4dNV) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramNamedParameter4fvNV) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); + void (APIENTRY *ProgramNamedParameter4dvNV) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); + void (APIENTRY *GetProgramNamedParameterfvNV) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); + void (APIENTRY *GetProgramNamedParameterdvNV) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); + void (APIENTRY *Vertex2hNV) (GLhalfNV x, GLhalfNV y); + void (APIENTRY *Vertex2hvNV) (const GLhalfNV *v); + void (APIENTRY *Vertex3hNV) (GLhalfNV x, GLhalfNV y, GLhalfNV z); + void (APIENTRY *Vertex3hvNV) (const GLhalfNV *v); + void (APIENTRY *Vertex4hNV) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); + void (APIENTRY *Vertex4hvNV) (const GLhalfNV *v); + void (APIENTRY *Normal3hNV) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); + void (APIENTRY *Normal3hvNV) (const GLhalfNV *v); + void (APIENTRY *Color3hNV) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); + void (APIENTRY *Color3hvNV) (const GLhalfNV *v); + void (APIENTRY *Color4hNV) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); + void (APIENTRY *Color4hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord1hNV) (GLhalfNV s); + void (APIENTRY *TexCoord1hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord2hNV) (GLhalfNV s, GLhalfNV t); + void (APIENTRY *TexCoord2hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord3hNV) (GLhalfNV s, GLhalfNV t, GLhalfNV r); + void (APIENTRY *TexCoord3hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord4hNV) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); + void (APIENTRY *TexCoord4hvNV) (const GLhalfNV *v); + void (APIENTRY *MultiTexCoord1hNV) (GLenum target, GLhalfNV s); + void (APIENTRY *MultiTexCoord1hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *MultiTexCoord2hNV) (GLenum target, GLhalfNV s, GLhalfNV t); + void (APIENTRY *MultiTexCoord2hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *MultiTexCoord3hNV) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); + void (APIENTRY *MultiTexCoord3hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *MultiTexCoord4hNV) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); + void (APIENTRY *MultiTexCoord4hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *FogCoordhNV) (GLhalfNV fog); + void (APIENTRY *FogCoordhvNV) (const GLhalfNV *fog); + void (APIENTRY *SecondaryColor3hNV) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); + void (APIENTRY *SecondaryColor3hvNV) (const GLhalfNV *v); + void (APIENTRY *VertexWeighthNV) (GLhalfNV weight); + void (APIENTRY *VertexWeighthvNV) (const GLhalfNV *weight); + void (APIENTRY *VertexAttrib1hNV) (GLuint index, GLhalfNV x); + void (APIENTRY *VertexAttrib1hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttrib2hNV) (GLuint index, GLhalfNV x, GLhalfNV y); + void (APIENTRY *VertexAttrib2hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttrib3hNV) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); + void (APIENTRY *VertexAttrib3hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttrib4hNV) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); + void (APIENTRY *VertexAttrib4hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttribs1hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *VertexAttribs2hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *VertexAttribs3hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *VertexAttribs4hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *PixelDataRangeNV) (GLenum target, GLsizei length, GLvoid *pointer); + void (APIENTRY *FlushPixelDataRangeNV) (GLenum target); + void (APIENTRY *PrimitiveRestartNV) (void); + void (APIENTRY *PrimitiveRestartIndexNV) (GLuint index); + GLvoid* (APIENTRY *MapObjectBufferATI) (GLuint buffer); + void (APIENTRY *UnmapObjectBufferATI) (GLuint buffer); + void (APIENTRY *StencilOpSeparateATI) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + void (APIENTRY *StencilFuncSeparateATI) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); + void (APIENTRY *VertexAttribArrayObjectATI) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); + void (APIENTRY *GetVertexAttribArrayObjectfvATI) (GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetVertexAttribArrayObjectivATI) (GLuint index, GLenum pname, GLint *params); + void (APIENTRY *DepthBoundsEXT) (GLclampd zmin, GLclampd zmax); + void (APIENTRY *BlendEquationSeparateEXT) (GLenum modeRGB, GLenum modeAlpha); + void (APIENTRY *AddSwapHintRectWIN) (GLint x, GLint y, GLsizei width, GLsizei height); +#ifdef _WIN32 + HANDLE (WINAPI *CreateBufferRegionARB) (HDC hDC, int iLayerPlane, UINT uType); + VOID (WINAPI *DeleteBufferRegionARB) (HANDLE hRegion); + BOOL (WINAPI *SaveBufferRegionARB) (HANDLE hRegion, int x, int y, int width, int height); + BOOL (WINAPI *RestoreBufferRegionARB) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); + const int (WINAPI *GetExtensionsStringARB) (HDC hdc); + BOOL (WINAPI *GetPixelFormatAttribivARB) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); + BOOL (WINAPI *GetPixelFormatAttribfvARB) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); + BOOL (WINAPI *ChoosePixelFormatARB) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); + BOOL (WINAPI *MakeContextCurrentARB) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + HDC (WINAPI *GetCurrentReadDCARB) (void); + HPBUFFERARB (WINAPI *CreatePbufferARB) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); + HDC (WINAPI *GetPbufferDCARB) (HPBUFFERARB hPbuffer); + int (WINAPI *ReleasePbufferDCARB) (HPBUFFERARB hPbuffer, HDC hDC); + BOOL (WINAPI *DestroyPbufferARB) (HPBUFFERARB hPbuffer); + BOOL (WINAPI *QueryPbufferARB) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); + BOOL (WINAPI *BindTexImageARB) (HPBUFFERARB hPbuffer, int iBuffer); + BOOL (WINAPI *ReleaseTexImageARB) (HPBUFFERARB hPbuffer, int iBuffer); + BOOL (WINAPI *SetPbufferAttribARB) (HPBUFFERARB hPbuffer, const int *piAttribList); + GLboolean (WINAPI *CreateDisplayColorTableEXT) (GLushort id); + GLboolean (WINAPI *LoadDisplayColorTableEXT) (const GLushort *table, GLuint length); + GLboolean (WINAPI *BindDisplayColorTableEXT) (GLushort id); + VOID (WINAPI *DestroyDisplayColorTableEXT) (GLushort id); + const int (WINAPI *GetExtensionsStringEXT) (void); + BOOL (WINAPI *MakeContextCurrentEXT) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + HDC (WINAPI *GetCurrentReadDCEXT) (void); + HPBUFFEREXT (WINAPI *CreatePbufferEXT) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); + HDC (WINAPI *GetPbufferDCEXT) (HPBUFFEREXT hPbuffer); + int (WINAPI *ReleasePbufferDCEXT) (HPBUFFEREXT hPbuffer, HDC hDC); + BOOL (WINAPI *DestroyPbufferEXT) (HPBUFFEREXT hPbuffer); + BOOL (WINAPI *QueryPbufferEXT) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); + BOOL (WINAPI *GetPixelFormatAttribivEXT) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); + BOOL (WINAPI *GetPixelFormatAttribfvEXT) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); + BOOL (WINAPI *ChoosePixelFormatEXT) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); + BOOL (WINAPI *SwapIntervalEXT) (int interval); + int (WINAPI *GetSwapIntervalEXT) (void); + void* (WINAPI *AllocateMemoryNV) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); + void (WINAPI *FreeMemoryNV) (void); + BOOL (WINAPI *GetSyncValuesOML) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); + BOOL (WINAPI *GetMscRateOML) (HDC hdc, INT32 *numerator, INT32 *denominator); + INT64 (WINAPI *SwapBuffersMscOML) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); + INT64 (WINAPI *SwapLayerBuffersMscOML) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); + BOOL (WINAPI *WaitForMscOML) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); + BOOL (WINAPI *WaitForSbcOML) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); + BOOL (WINAPI *GetDigitalVideoParametersI3D) (HDC hDC, int iAttribute, int *piValue); + BOOL (WINAPI *SetDigitalVideoParametersI3D) (HDC hDC, int iAttribute, const int *piValue); + BOOL (WINAPI *GetGammaTableParametersI3D) (HDC hDC, int iAttribute, int *piValue); + BOOL (WINAPI *SetGammaTableParametersI3D) (HDC hDC, int iAttribute, const int *piValue); + BOOL (WINAPI *GetGammaTableI3D) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); + BOOL (WINAPI *SetGammaTableI3D) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); + BOOL (WINAPI *EnableGenlockI3D) (HDC hDC); + BOOL (WINAPI *DisableGenlockI3D) (HDC hDC); + BOOL (WINAPI *IsEnabledGenlockI3D) (HDC hDC, BOOL *pFlag); + BOOL (WINAPI *GenlockSourceI3D) (HDC hDC, UINT uSource); + BOOL (WINAPI *GetGenlockSourceI3D) (HDC hDC, UINT *uSource); + BOOL (WINAPI *GenlockSourceEdgeI3D) (HDC hDC, UINT uEdge); + BOOL (WINAPI *GetGenlockSourceEdgeI3D) (HDC hDC, UINT *uEdge); + BOOL (WINAPI *GenlockSampleRateI3D) (HDC hDC, UINT uRate); + BOOL (WINAPI *GetGenlockSampleRateI3D) (HDC hDC, UINT *uRate); + BOOL (WINAPI *GenlockSourceDelayI3D) (HDC hDC, UINT uDelay); + BOOL (WINAPI *GetGenlockSourceDelayI3D) (HDC hDC, UINT *uDelay); + BOOL (WINAPI *QueryGenlockMaxSourceDelayI3D) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); + LPVOID (WINAPI *CreateImageBufferI3D) (HDC hDC, DWORD dwSize, UINT uFlags); + BOOL (WINAPI *DestroyImageBufferI3D) (HDC hDC, LPVOID pAddress); + BOOL (WINAPI *AssociateImageBufferEventsI3D) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); + BOOL (WINAPI *ReleaseImageBufferEventsI3D) (HDC hDC, const LPVOID *pAddress, UINT count); + BOOL (WINAPI *EnableFrameLockI3D) (void); + BOOL (WINAPI *DisableFrameLockI3D) (void); + BOOL (WINAPI *IsEnabledFrameLockI3D) (BOOL *pFlag); + BOOL (WINAPI *QueryFrameLockMasterI3D) (BOOL *pFlag); + BOOL (WINAPI *GetFrameUsageI3D) (float *pUsage); + BOOL (WINAPI *BeginFrameTrackingI3D) (void); + BOOL (WINAPI *EndFrameTrackingI3D) (void); + BOOL (WINAPI *QueryFrameTrackingI3D) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); +#endif /* _WIN32 */ +} _GLextensionProcs; + +#define glBlendColor (_GET_TLS_PROCTABLE()->BlendColor) +#define glBlendEquation (_GET_TLS_PROCTABLE()->BlendEquation) +#define glDrawRangeElements (_GET_TLS_PROCTABLE()->DrawRangeElements) +#define glColorTable (_GET_TLS_PROCTABLE()->ColorTable) +#define glColorTableParameterfv (_GET_TLS_PROCTABLE()->ColorTableParameterfv) +#define glColorTableParameteriv (_GET_TLS_PROCTABLE()->ColorTableParameteriv) +#define glCopyColorTable (_GET_TLS_PROCTABLE()->CopyColorTable) +#define glGetColorTable (_GET_TLS_PROCTABLE()->GetColorTable) +#define glGetColorTableParameterfv (_GET_TLS_PROCTABLE()->GetColorTableParameterfv) +#define glGetColorTableParameteriv (_GET_TLS_PROCTABLE()->GetColorTableParameteriv) +#define glColorSubTable (_GET_TLS_PROCTABLE()->ColorSubTable) +#define glCopyColorSubTable (_GET_TLS_PROCTABLE()->CopyColorSubTable) +#define glConvolutionFilter1D (_GET_TLS_PROCTABLE()->ConvolutionFilter1D) +#define glConvolutionFilter2D (_GET_TLS_PROCTABLE()->ConvolutionFilter2D) +#define glConvolutionParameterf (_GET_TLS_PROCTABLE()->ConvolutionParameterf) +#define glConvolutionParameterfv (_GET_TLS_PROCTABLE()->ConvolutionParameterfv) +#define glConvolutionParameteri (_GET_TLS_PROCTABLE()->ConvolutionParameteri) +#define glConvolutionParameteriv (_GET_TLS_PROCTABLE()->ConvolutionParameteriv) +#define glCopyConvolutionFilter1D (_GET_TLS_PROCTABLE()->CopyConvolutionFilter1D) +#define glCopyConvolutionFilter2D (_GET_TLS_PROCTABLE()->CopyConvolutionFilter2D) +#define glGetConvolutionFilter (_GET_TLS_PROCTABLE()->GetConvolutionFilter) +#define glGetConvolutionParameterfv (_GET_TLS_PROCTABLE()->GetConvolutionParameterfv) +#define glGetConvolutionParameteriv (_GET_TLS_PROCTABLE()->GetConvolutionParameteriv) +#define glGetSeparableFilter (_GET_TLS_PROCTABLE()->GetSeparableFilter) +#define glSeparableFilter2D (_GET_TLS_PROCTABLE()->SeparableFilter2D) +#define glGetHistogram (_GET_TLS_PROCTABLE()->GetHistogram) +#define glGetHistogramParameterfv (_GET_TLS_PROCTABLE()->GetHistogramParameterfv) +#define glGetHistogramParameteriv (_GET_TLS_PROCTABLE()->GetHistogramParameteriv) +#define glGetMinmax (_GET_TLS_PROCTABLE()->GetMinmax) +#define glGetMinmaxParameterfv (_GET_TLS_PROCTABLE()->GetMinmaxParameterfv) +#define glGetMinmaxParameteriv (_GET_TLS_PROCTABLE()->GetMinmaxParameteriv) +#define glHistogram (_GET_TLS_PROCTABLE()->Histogram) +#define glMinmax (_GET_TLS_PROCTABLE()->Minmax) +#define glResetHistogram (_GET_TLS_PROCTABLE()->ResetHistogram) +#define glResetMinmax (_GET_TLS_PROCTABLE()->ResetMinmax) +#define glTexImage3D (_GET_TLS_PROCTABLE()->TexImage3D) +#define glTexSubImage3D (_GET_TLS_PROCTABLE()->TexSubImage3D) +#define glCopyTexSubImage3D (_GET_TLS_PROCTABLE()->CopyTexSubImage3D) +#define glActiveTexture (_GET_TLS_PROCTABLE()->ActiveTexture) +#define glClientActiveTexture (_GET_TLS_PROCTABLE()->ClientActiveTexture) +#define glMultiTexCoord1d (_GET_TLS_PROCTABLE()->MultiTexCoord1d) +#define glMultiTexCoord1dv (_GET_TLS_PROCTABLE()->MultiTexCoord1dv) +#define glMultiTexCoord1f (_GET_TLS_PROCTABLE()->MultiTexCoord1f) +#define glMultiTexCoord1fv (_GET_TLS_PROCTABLE()->MultiTexCoord1fv) +#define glMultiTexCoord1i (_GET_TLS_PROCTABLE()->MultiTexCoord1i) +#define glMultiTexCoord1iv (_GET_TLS_PROCTABLE()->MultiTexCoord1iv) +#define glMultiTexCoord1s (_GET_TLS_PROCTABLE()->MultiTexCoord1s) +#define glMultiTexCoord1sv (_GET_TLS_PROCTABLE()->MultiTexCoord1sv) +#define glMultiTexCoord2d (_GET_TLS_PROCTABLE()->MultiTexCoord2d) +#define glMultiTexCoord2dv (_GET_TLS_PROCTABLE()->MultiTexCoord2dv) +#define glMultiTexCoord2f (_GET_TLS_PROCTABLE()->MultiTexCoord2f) +#define glMultiTexCoord2fv (_GET_TLS_PROCTABLE()->MultiTexCoord2fv) +#define glMultiTexCoord2i (_GET_TLS_PROCTABLE()->MultiTexCoord2i) +#define glMultiTexCoord2iv (_GET_TLS_PROCTABLE()->MultiTexCoord2iv) +#define glMultiTexCoord2s (_GET_TLS_PROCTABLE()->MultiTexCoord2s) +#define glMultiTexCoord2sv (_GET_TLS_PROCTABLE()->MultiTexCoord2sv) +#define glMultiTexCoord3d (_GET_TLS_PROCTABLE()->MultiTexCoord3d) +#define glMultiTexCoord3dv (_GET_TLS_PROCTABLE()->MultiTexCoord3dv) +#define glMultiTexCoord3f (_GET_TLS_PROCTABLE()->MultiTexCoord3f) +#define glMultiTexCoord3fv (_GET_TLS_PROCTABLE()->MultiTexCoord3fv) +#define glMultiTexCoord3i (_GET_TLS_PROCTABLE()->MultiTexCoord3i) +#define glMultiTexCoord3iv (_GET_TLS_PROCTABLE()->MultiTexCoord3iv) +#define glMultiTexCoord3s (_GET_TLS_PROCTABLE()->MultiTexCoord3s) +#define glMultiTexCoord3sv (_GET_TLS_PROCTABLE()->MultiTexCoord3sv) +#define glMultiTexCoord4d (_GET_TLS_PROCTABLE()->MultiTexCoord4d) +#define glMultiTexCoord4dv (_GET_TLS_PROCTABLE()->MultiTexCoord4dv) +#define glMultiTexCoord4f (_GET_TLS_PROCTABLE()->MultiTexCoord4f) +#define glMultiTexCoord4fv (_GET_TLS_PROCTABLE()->MultiTexCoord4fv) +#define glMultiTexCoord4i (_GET_TLS_PROCTABLE()->MultiTexCoord4i) +#define glMultiTexCoord4iv (_GET_TLS_PROCTABLE()->MultiTexCoord4iv) +#define glMultiTexCoord4s (_GET_TLS_PROCTABLE()->MultiTexCoord4s) +#define glMultiTexCoord4sv (_GET_TLS_PROCTABLE()->MultiTexCoord4sv) +#define glLoadTransposeMatrixf (_GET_TLS_PROCTABLE()->LoadTransposeMatrixf) +#define glLoadTransposeMatrixd (_GET_TLS_PROCTABLE()->LoadTransposeMatrixd) +#define glMultTransposeMatrixf (_GET_TLS_PROCTABLE()->MultTransposeMatrixf) +#define glMultTransposeMatrixd (_GET_TLS_PROCTABLE()->MultTransposeMatrixd) +#define glSampleCoverage (_GET_TLS_PROCTABLE()->SampleCoverage) +#define glCompressedTexImage3D (_GET_TLS_PROCTABLE()->CompressedTexImage3D) +#define glCompressedTexImage2D (_GET_TLS_PROCTABLE()->CompressedTexImage2D) +#define glCompressedTexImage1D (_GET_TLS_PROCTABLE()->CompressedTexImage1D) +#define glCompressedTexSubImage3D (_GET_TLS_PROCTABLE()->CompressedTexSubImage3D) +#define glCompressedTexSubImage2D (_GET_TLS_PROCTABLE()->CompressedTexSubImage2D) +#define glCompressedTexSubImage1D (_GET_TLS_PROCTABLE()->CompressedTexSubImage1D) +#define glGetCompressedTexImage (_GET_TLS_PROCTABLE()->GetCompressedTexImage) +#define glBlendFuncSeparate (_GET_TLS_PROCTABLE()->BlendFuncSeparate) +#define glFogCoordf (_GET_TLS_PROCTABLE()->FogCoordf) +#define glFogCoordfv (_GET_TLS_PROCTABLE()->FogCoordfv) +#define glFogCoordd (_GET_TLS_PROCTABLE()->FogCoordd) +#define glFogCoorddv (_GET_TLS_PROCTABLE()->FogCoorddv) +#define glFogCoordPointer (_GET_TLS_PROCTABLE()->FogCoordPointer) +#define glMultiDrawArrays (_GET_TLS_PROCTABLE()->MultiDrawArrays) +#define glMultiDrawElements (_GET_TLS_PROCTABLE()->MultiDrawElements) +#define glPointParameterf (_GET_TLS_PROCTABLE()->PointParameterf) +#define glPointParameterfv (_GET_TLS_PROCTABLE()->PointParameterfv) +#define glPointParameteri (_GET_TLS_PROCTABLE()->PointParameteri) +#define glPointParameteriv (_GET_TLS_PROCTABLE()->PointParameteriv) +#define glSecondaryColor3b (_GET_TLS_PROCTABLE()->SecondaryColor3b) +#define glSecondaryColor3bv (_GET_TLS_PROCTABLE()->SecondaryColor3bv) +#define glSecondaryColor3d (_GET_TLS_PROCTABLE()->SecondaryColor3d) +#define glSecondaryColor3dv (_GET_TLS_PROCTABLE()->SecondaryColor3dv) +#define glSecondaryColor3f (_GET_TLS_PROCTABLE()->SecondaryColor3f) +#define glSecondaryColor3fv (_GET_TLS_PROCTABLE()->SecondaryColor3fv) +#define glSecondaryColor3i (_GET_TLS_PROCTABLE()->SecondaryColor3i) +#define glSecondaryColor3iv (_GET_TLS_PROCTABLE()->SecondaryColor3iv) +#define glSecondaryColor3s (_GET_TLS_PROCTABLE()->SecondaryColor3s) +#define glSecondaryColor3sv (_GET_TLS_PROCTABLE()->SecondaryColor3sv) +#define glSecondaryColor3ub (_GET_TLS_PROCTABLE()->SecondaryColor3ub) +#define glSecondaryColor3ubv (_GET_TLS_PROCTABLE()->SecondaryColor3ubv) +#define glSecondaryColor3ui (_GET_TLS_PROCTABLE()->SecondaryColor3ui) +#define glSecondaryColor3uiv (_GET_TLS_PROCTABLE()->SecondaryColor3uiv) +#define glSecondaryColor3us (_GET_TLS_PROCTABLE()->SecondaryColor3us) +#define glSecondaryColor3usv (_GET_TLS_PROCTABLE()->SecondaryColor3usv) +#define glSecondaryColorPointer (_GET_TLS_PROCTABLE()->SecondaryColorPointer) +#define glWindowPos2d (_GET_TLS_PROCTABLE()->WindowPos2d) +#define glWindowPos2dv (_GET_TLS_PROCTABLE()->WindowPos2dv) +#define glWindowPos2f (_GET_TLS_PROCTABLE()->WindowPos2f) +#define glWindowPos2fv (_GET_TLS_PROCTABLE()->WindowPos2fv) +#define glWindowPos2i (_GET_TLS_PROCTABLE()->WindowPos2i) +#define glWindowPos2iv (_GET_TLS_PROCTABLE()->WindowPos2iv) +#define glWindowPos2s (_GET_TLS_PROCTABLE()->WindowPos2s) +#define glWindowPos2sv (_GET_TLS_PROCTABLE()->WindowPos2sv) +#define glWindowPos3d (_GET_TLS_PROCTABLE()->WindowPos3d) +#define glWindowPos3dv (_GET_TLS_PROCTABLE()->WindowPos3dv) +#define glWindowPos3f (_GET_TLS_PROCTABLE()->WindowPos3f) +#define glWindowPos3fv (_GET_TLS_PROCTABLE()->WindowPos3fv) +#define glWindowPos3i (_GET_TLS_PROCTABLE()->WindowPos3i) +#define glWindowPos3iv (_GET_TLS_PROCTABLE()->WindowPos3iv) +#define glWindowPos3s (_GET_TLS_PROCTABLE()->WindowPos3s) +#define glWindowPos3sv (_GET_TLS_PROCTABLE()->WindowPos3sv) +#define glGenQueries (_GET_TLS_PROCTABLE()->GenQueries) +#define glDeleteQueries (_GET_TLS_PROCTABLE()->DeleteQueries) +#define glIsQuery (_GET_TLS_PROCTABLE()->IsQuery) +#define glBeginQuery (_GET_TLS_PROCTABLE()->BeginQuery) +#define glEndQuery (_GET_TLS_PROCTABLE()->EndQuery) +#define glGetQueryiv (_GET_TLS_PROCTABLE()->GetQueryiv) +#define glGetQueryObjectiv (_GET_TLS_PROCTABLE()->GetQueryObjectiv) +#define glGetQueryObjectuiv (_GET_TLS_PROCTABLE()->GetQueryObjectuiv) +#define glBindBuffer (_GET_TLS_PROCTABLE()->BindBuffer) +#define glDeleteBuffers (_GET_TLS_PROCTABLE()->DeleteBuffers) +#define glGenBuffers (_GET_TLS_PROCTABLE()->GenBuffers) +#define glIsBuffer (_GET_TLS_PROCTABLE()->IsBuffer) +#define glBufferData (_GET_TLS_PROCTABLE()->BufferData) +#define glBufferSubData (_GET_TLS_PROCTABLE()->BufferSubData) +#define glGetBufferSubData (_GET_TLS_PROCTABLE()->GetBufferSubData) +#define glMapBuffer (_GET_TLS_PROCTABLE()->MapBuffer) +#define glUnmapBuffer (_GET_TLS_PROCTABLE()->UnmapBuffer) +#define glGetBufferParameteriv (_GET_TLS_PROCTABLE()->GetBufferParameteriv) +#define glGetBufferPointerv (_GET_TLS_PROCTABLE()->GetBufferPointerv) +#define glActiveTextureARB (_GET_TLS_PROCTABLE()->ActiveTextureARB) +#define glClientActiveTextureARB (_GET_TLS_PROCTABLE()->ClientActiveTextureARB) +#define glMultiTexCoord1dARB (_GET_TLS_PROCTABLE()->MultiTexCoord1dARB) +#define glMultiTexCoord1dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord1dvARB) +#define glMultiTexCoord1fARB (_GET_TLS_PROCTABLE()->MultiTexCoord1fARB) +#define glMultiTexCoord1fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord1fvARB) +#define glMultiTexCoord1iARB (_GET_TLS_PROCTABLE()->MultiTexCoord1iARB) +#define glMultiTexCoord1ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord1ivARB) +#define glMultiTexCoord1sARB (_GET_TLS_PROCTABLE()->MultiTexCoord1sARB) +#define glMultiTexCoord1svARB (_GET_TLS_PROCTABLE()->MultiTexCoord1svARB) +#define glMultiTexCoord2dARB (_GET_TLS_PROCTABLE()->MultiTexCoord2dARB) +#define glMultiTexCoord2dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord2dvARB) +#define glMultiTexCoord2fARB (_GET_TLS_PROCTABLE()->MultiTexCoord2fARB) +#define glMultiTexCoord2fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord2fvARB) +#define glMultiTexCoord2iARB (_GET_TLS_PROCTABLE()->MultiTexCoord2iARB) +#define glMultiTexCoord2ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord2ivARB) +#define glMultiTexCoord2sARB (_GET_TLS_PROCTABLE()->MultiTexCoord2sARB) +#define glMultiTexCoord2svARB (_GET_TLS_PROCTABLE()->MultiTexCoord2svARB) +#define glMultiTexCoord3dARB (_GET_TLS_PROCTABLE()->MultiTexCoord3dARB) +#define glMultiTexCoord3dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord3dvARB) +#define glMultiTexCoord3fARB (_GET_TLS_PROCTABLE()->MultiTexCoord3fARB) +#define glMultiTexCoord3fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord3fvARB) +#define glMultiTexCoord3iARB (_GET_TLS_PROCTABLE()->MultiTexCoord3iARB) +#define glMultiTexCoord3ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord3ivARB) +#define glMultiTexCoord3sARB (_GET_TLS_PROCTABLE()->MultiTexCoord3sARB) +#define glMultiTexCoord3svARB (_GET_TLS_PROCTABLE()->MultiTexCoord3svARB) +#define glMultiTexCoord4dARB (_GET_TLS_PROCTABLE()->MultiTexCoord4dARB) +#define glMultiTexCoord4dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord4dvARB) +#define glMultiTexCoord4fARB (_GET_TLS_PROCTABLE()->MultiTexCoord4fARB) +#define glMultiTexCoord4fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord4fvARB) +#define glMultiTexCoord4iARB (_GET_TLS_PROCTABLE()->MultiTexCoord4iARB) +#define glMultiTexCoord4ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord4ivARB) +#define glMultiTexCoord4sARB (_GET_TLS_PROCTABLE()->MultiTexCoord4sARB) +#define glMultiTexCoord4svARB (_GET_TLS_PROCTABLE()->MultiTexCoord4svARB) +#define glLoadTransposeMatrixfARB (_GET_TLS_PROCTABLE()->LoadTransposeMatrixfARB) +#define glLoadTransposeMatrixdARB (_GET_TLS_PROCTABLE()->LoadTransposeMatrixdARB) +#define glMultTransposeMatrixfARB (_GET_TLS_PROCTABLE()->MultTransposeMatrixfARB) +#define glMultTransposeMatrixdARB (_GET_TLS_PROCTABLE()->MultTransposeMatrixdARB) +#define glSampleCoverageARB (_GET_TLS_PROCTABLE()->SampleCoverageARB) +#define glCompressedTexImage3DARB (_GET_TLS_PROCTABLE()->CompressedTexImage3DARB) +#define glCompressedTexImage2DARB (_GET_TLS_PROCTABLE()->CompressedTexImage2DARB) +#define glCompressedTexImage1DARB (_GET_TLS_PROCTABLE()->CompressedTexImage1DARB) +#define glCompressedTexSubImage3DARB (_GET_TLS_PROCTABLE()->CompressedTexSubImage3DARB) +#define glCompressedTexSubImage2DARB (_GET_TLS_PROCTABLE()->CompressedTexSubImage2DARB) +#define glCompressedTexSubImage1DARB (_GET_TLS_PROCTABLE()->CompressedTexSubImage1DARB) +#define glGetCompressedTexImageARB (_GET_TLS_PROCTABLE()->GetCompressedTexImageARB) +#define glPointParameterfARB (_GET_TLS_PROCTABLE()->PointParameterfARB) +#define glPointParameterfvARB (_GET_TLS_PROCTABLE()->PointParameterfvARB) +#define glWeightbvARB (_GET_TLS_PROCTABLE()->WeightbvARB) +#define glWeightsvARB (_GET_TLS_PROCTABLE()->WeightsvARB) +#define glWeightivARB (_GET_TLS_PROCTABLE()->WeightivARB) +#define glWeightfvARB (_GET_TLS_PROCTABLE()->WeightfvARB) +#define glWeightdvARB (_GET_TLS_PROCTABLE()->WeightdvARB) +#define glWeightubvARB (_GET_TLS_PROCTABLE()->WeightubvARB) +#define glWeightusvARB (_GET_TLS_PROCTABLE()->WeightusvARB) +#define glWeightuivARB (_GET_TLS_PROCTABLE()->WeightuivARB) +#define glWeightPointerARB (_GET_TLS_PROCTABLE()->WeightPointerARB) +#define glVertexBlendARB (_GET_TLS_PROCTABLE()->VertexBlendARB) +#define glCurrentPaletteMatrixARB (_GET_TLS_PROCTABLE()->CurrentPaletteMatrixARB) +#define glMatrixIndexubvARB (_GET_TLS_PROCTABLE()->MatrixIndexubvARB) +#define glMatrixIndexusvARB (_GET_TLS_PROCTABLE()->MatrixIndexusvARB) +#define glMatrixIndexuivARB (_GET_TLS_PROCTABLE()->MatrixIndexuivARB) +#define glMatrixIndexPointerARB (_GET_TLS_PROCTABLE()->MatrixIndexPointerARB) +#define glWindowPos2dARB (_GET_TLS_PROCTABLE()->WindowPos2dARB) +#define glWindowPos2dvARB (_GET_TLS_PROCTABLE()->WindowPos2dvARB) +#define glWindowPos2fARB (_GET_TLS_PROCTABLE()->WindowPos2fARB) +#define glWindowPos2fvARB (_GET_TLS_PROCTABLE()->WindowPos2fvARB) +#define glWindowPos2iARB (_GET_TLS_PROCTABLE()->WindowPos2iARB) +#define glWindowPos2ivARB (_GET_TLS_PROCTABLE()->WindowPos2ivARB) +#define glWindowPos2sARB (_GET_TLS_PROCTABLE()->WindowPos2sARB) +#define glWindowPos2svARB (_GET_TLS_PROCTABLE()->WindowPos2svARB) +#define glWindowPos3dARB (_GET_TLS_PROCTABLE()->WindowPos3dARB) +#define glWindowPos3dvARB (_GET_TLS_PROCTABLE()->WindowPos3dvARB) +#define glWindowPos3fARB (_GET_TLS_PROCTABLE()->WindowPos3fARB) +#define glWindowPos3fvARB (_GET_TLS_PROCTABLE()->WindowPos3fvARB) +#define glWindowPos3iARB (_GET_TLS_PROCTABLE()->WindowPos3iARB) +#define glWindowPos3ivARB (_GET_TLS_PROCTABLE()->WindowPos3ivARB) +#define glWindowPos3sARB (_GET_TLS_PROCTABLE()->WindowPos3sARB) +#define glWindowPos3svARB (_GET_TLS_PROCTABLE()->WindowPos3svARB) +#define glVertexAttrib1dARB (_GET_TLS_PROCTABLE()->VertexAttrib1dARB) +#define glVertexAttrib1dvARB (_GET_TLS_PROCTABLE()->VertexAttrib1dvARB) +#define glVertexAttrib1fARB (_GET_TLS_PROCTABLE()->VertexAttrib1fARB) +#define glVertexAttrib1fvARB (_GET_TLS_PROCTABLE()->VertexAttrib1fvARB) +#define glVertexAttrib1sARB (_GET_TLS_PROCTABLE()->VertexAttrib1sARB) +#define glVertexAttrib1svARB (_GET_TLS_PROCTABLE()->VertexAttrib1svARB) +#define glVertexAttrib2dARB (_GET_TLS_PROCTABLE()->VertexAttrib2dARB) +#define glVertexAttrib2dvARB (_GET_TLS_PROCTABLE()->VertexAttrib2dvARB) +#define glVertexAttrib2fARB (_GET_TLS_PROCTABLE()->VertexAttrib2fARB) +#define glVertexAttrib2fvARB (_GET_TLS_PROCTABLE()->VertexAttrib2fvARB) +#define glVertexAttrib2sARB (_GET_TLS_PROCTABLE()->VertexAttrib2sARB) +#define glVertexAttrib2svARB (_GET_TLS_PROCTABLE()->VertexAttrib2svARB) +#define glVertexAttrib3dARB (_GET_TLS_PROCTABLE()->VertexAttrib3dARB) +#define glVertexAttrib3dvARB (_GET_TLS_PROCTABLE()->VertexAttrib3dvARB) +#define glVertexAttrib3fARB (_GET_TLS_PROCTABLE()->VertexAttrib3fARB) +#define glVertexAttrib3fvARB (_GET_TLS_PROCTABLE()->VertexAttrib3fvARB) +#define glVertexAttrib3sARB (_GET_TLS_PROCTABLE()->VertexAttrib3sARB) +#define glVertexAttrib3svARB (_GET_TLS_PROCTABLE()->VertexAttrib3svARB) +#define glVertexAttrib4NbvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NbvARB) +#define glVertexAttrib4NivARB (_GET_TLS_PROCTABLE()->VertexAttrib4NivARB) +#define glVertexAttrib4NsvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NsvARB) +#define glVertexAttrib4NubARB (_GET_TLS_PROCTABLE()->VertexAttrib4NubARB) +#define glVertexAttrib4NubvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NubvARB) +#define glVertexAttrib4NuivARB (_GET_TLS_PROCTABLE()->VertexAttrib4NuivARB) +#define glVertexAttrib4NusvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NusvARB) +#define glVertexAttrib4bvARB (_GET_TLS_PROCTABLE()->VertexAttrib4bvARB) +#define glVertexAttrib4dARB (_GET_TLS_PROCTABLE()->VertexAttrib4dARB) +#define glVertexAttrib4dvARB (_GET_TLS_PROCTABLE()->VertexAttrib4dvARB) +#define glVertexAttrib4fARB (_GET_TLS_PROCTABLE()->VertexAttrib4fARB) +#define glVertexAttrib4fvARB (_GET_TLS_PROCTABLE()->VertexAttrib4fvARB) +#define glVertexAttrib4ivARB (_GET_TLS_PROCTABLE()->VertexAttrib4ivARB) +#define glVertexAttrib4sARB (_GET_TLS_PROCTABLE()->VertexAttrib4sARB) +#define glVertexAttrib4svARB (_GET_TLS_PROCTABLE()->VertexAttrib4svARB) +#define glVertexAttrib4ubvARB (_GET_TLS_PROCTABLE()->VertexAttrib4ubvARB) +#define glVertexAttrib4uivARB (_GET_TLS_PROCTABLE()->VertexAttrib4uivARB) +#define glVertexAttrib4usvARB (_GET_TLS_PROCTABLE()->VertexAttrib4usvARB) +#define glVertexAttribPointerARB (_GET_TLS_PROCTABLE()->VertexAttribPointerARB) +#define glEnableVertexAttribArrayARB (_GET_TLS_PROCTABLE()->EnableVertexAttribArrayARB) +#define glDisableVertexAttribArrayARB (_GET_TLS_PROCTABLE()->DisableVertexAttribArrayARB) +#define glProgramStringARB (_GET_TLS_PROCTABLE()->ProgramStringARB) +#define glBindProgramARB (_GET_TLS_PROCTABLE()->BindProgramARB) +#define glDeleteProgramsARB (_GET_TLS_PROCTABLE()->DeleteProgramsARB) +#define glGenProgramsARB (_GET_TLS_PROCTABLE()->GenProgramsARB) +#define glProgramEnvParameter4dARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4dARB) +#define glProgramEnvParameter4dvARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4dvARB) +#define glProgramEnvParameter4fARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4fARB) +#define glProgramEnvParameter4fvARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4fvARB) +#define glProgramLocalParameter4dARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4dARB) +#define glProgramLocalParameter4dvARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4dvARB) +#define glProgramLocalParameter4fARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4fARB) +#define glProgramLocalParameter4fvARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4fvARB) +#define glGetProgramEnvParameterdvARB (_GET_TLS_PROCTABLE()->GetProgramEnvParameterdvARB) +#define glGetProgramEnvParameterfvARB (_GET_TLS_PROCTABLE()->GetProgramEnvParameterfvARB) +#define glGetProgramLocalParameterdvARB (_GET_TLS_PROCTABLE()->GetProgramLocalParameterdvARB) +#define glGetProgramLocalParameterfvARB (_GET_TLS_PROCTABLE()->GetProgramLocalParameterfvARB) +#define glGetProgramivARB (_GET_TLS_PROCTABLE()->GetProgramivARB) +#define glGetProgramStringARB (_GET_TLS_PROCTABLE()->GetProgramStringARB) +#define glGetVertexAttribdvARB (_GET_TLS_PROCTABLE()->GetVertexAttribdvARB) +#define glGetVertexAttribfvARB (_GET_TLS_PROCTABLE()->GetVertexAttribfvARB) +#define glGetVertexAttribivARB (_GET_TLS_PROCTABLE()->GetVertexAttribivARB) +#define glGetVertexAttribPointervARB (_GET_TLS_PROCTABLE()->GetVertexAttribPointervARB) +#define glIsProgramARB (_GET_TLS_PROCTABLE()->IsProgramARB) +#define glBindBufferARB (_GET_TLS_PROCTABLE()->BindBufferARB) +#define glDeleteBuffersARB (_GET_TLS_PROCTABLE()->DeleteBuffersARB) +#define glGenBuffersARB (_GET_TLS_PROCTABLE()->GenBuffersARB) +#define glIsBufferARB (_GET_TLS_PROCTABLE()->IsBufferARB) +#define glBufferDataARB (_GET_TLS_PROCTABLE()->BufferDataARB) +#define glBufferSubDataARB (_GET_TLS_PROCTABLE()->BufferSubDataARB) +#define glGetBufferSubDataARB (_GET_TLS_PROCTABLE()->GetBufferSubDataARB) +#define glMapBufferARB (_GET_TLS_PROCTABLE()->MapBufferARB) +#define glUnmapBufferARB (_GET_TLS_PROCTABLE()->UnmapBufferARB) +#define glGetBufferParameterivARB (_GET_TLS_PROCTABLE()->GetBufferParameterivARB) +#define glGetBufferPointervARB (_GET_TLS_PROCTABLE()->GetBufferPointervARB) +#define glGenQueriesARB (_GET_TLS_PROCTABLE()->GenQueriesARB) +#define glDeleteQueriesARB (_GET_TLS_PROCTABLE()->DeleteQueriesARB) +#define glIsQueryARB (_GET_TLS_PROCTABLE()->IsQueryARB) +#define glBeginQueryARB (_GET_TLS_PROCTABLE()->BeginQueryARB) +#define glEndQueryARB (_GET_TLS_PROCTABLE()->EndQueryARB) +#define glGetQueryivARB (_GET_TLS_PROCTABLE()->GetQueryivARB) +#define glGetQueryObjectivARB (_GET_TLS_PROCTABLE()->GetQueryObjectivARB) +#define glGetQueryObjectuivARB (_GET_TLS_PROCTABLE()->GetQueryObjectuivARB) +#define glDeleteObjectARB (_GET_TLS_PROCTABLE()->DeleteObjectARB) +#define glGetHandleARB (_GET_TLS_PROCTABLE()->GetHandleARB) +#define glDetachObjectARB (_GET_TLS_PROCTABLE()->DetachObjectARB) +#define glCreateShaderObjectARB (_GET_TLS_PROCTABLE()->CreateShaderObjectARB) +#define glShaderSourceARB (_GET_TLS_PROCTABLE()->ShaderSourceARB) +#define glCompileShaderARB (_GET_TLS_PROCTABLE()->CompileShaderARB) +#define glCreateProgramObjectARB (_GET_TLS_PROCTABLE()->CreateProgramObjectARB) +#define glAttachObjectARB (_GET_TLS_PROCTABLE()->AttachObjectARB) +#define glLinkProgramARB (_GET_TLS_PROCTABLE()->LinkProgramARB) +#define glUseProgramObjectARB (_GET_TLS_PROCTABLE()->UseProgramObjectARB) +#define glValidateProgramARB (_GET_TLS_PROCTABLE()->ValidateProgramARB) +#define glUniform1fARB (_GET_TLS_PROCTABLE()->Uniform1fARB) +#define glUniform2fARB (_GET_TLS_PROCTABLE()->Uniform2fARB) +#define glUniform3fARB (_GET_TLS_PROCTABLE()->Uniform3fARB) +#define glUniform4fARB (_GET_TLS_PROCTABLE()->Uniform4fARB) +#define glUniform1iARB (_GET_TLS_PROCTABLE()->Uniform1iARB) +#define glUniform2iARB (_GET_TLS_PROCTABLE()->Uniform2iARB) +#define glUniform3iARB (_GET_TLS_PROCTABLE()->Uniform3iARB) +#define glUniform4iARB (_GET_TLS_PROCTABLE()->Uniform4iARB) +#define glUniform1fvARB (_GET_TLS_PROCTABLE()->Uniform1fvARB) +#define glUniform2fvARB (_GET_TLS_PROCTABLE()->Uniform2fvARB) +#define glUniform3fvARB (_GET_TLS_PROCTABLE()->Uniform3fvARB) +#define glUniform4fvARB (_GET_TLS_PROCTABLE()->Uniform4fvARB) +#define glUniform1ivARB (_GET_TLS_PROCTABLE()->Uniform1ivARB) +#define glUniform2ivARB (_GET_TLS_PROCTABLE()->Uniform2ivARB) +#define glUniform3ivARB (_GET_TLS_PROCTABLE()->Uniform3ivARB) +#define glUniform4ivARB (_GET_TLS_PROCTABLE()->Uniform4ivARB) +#define glUniformMatrix2fvARB (_GET_TLS_PROCTABLE()->UniformMatrix2fvARB) +#define glUniformMatrix3fvARB (_GET_TLS_PROCTABLE()->UniformMatrix3fvARB) +#define glUniformMatrix4fvARB (_GET_TLS_PROCTABLE()->UniformMatrix4fvARB) +#define glGetObjectParameterfvARB (_GET_TLS_PROCTABLE()->GetObjectParameterfvARB) +#define glGetObjectParameterivARB (_GET_TLS_PROCTABLE()->GetObjectParameterivARB) +#define glGetInfoLogARB (_GET_TLS_PROCTABLE()->GetInfoLogARB) +#define glGetAttachedObjectsARB (_GET_TLS_PROCTABLE()->GetAttachedObjectsARB) +#define glGetUniformLocationARB (_GET_TLS_PROCTABLE()->GetUniformLocationARB) +#define glGetActiveUniformARB (_GET_TLS_PROCTABLE()->GetActiveUniformARB) +#define glGetUniformfvARB (_GET_TLS_PROCTABLE()->GetUniformfvARB) +#define glGetUniformivARB (_GET_TLS_PROCTABLE()->GetUniformivARB) +#define glGetShaderSourceARB (_GET_TLS_PROCTABLE()->GetShaderSourceARB) +#define glBindAttribLocationARB (_GET_TLS_PROCTABLE()->BindAttribLocationARB) +#define glGetActiveAttribARB (_GET_TLS_PROCTABLE()->GetActiveAttribARB) +#define glGetAttribLocationARB (_GET_TLS_PROCTABLE()->GetAttribLocationARB) +#define glBlendColorEXT (_GET_TLS_PROCTABLE()->BlendColorEXT) +#define glPolygonOffsetEXT (_GET_TLS_PROCTABLE()->PolygonOffsetEXT) +#define glTexImage3DEXT (_GET_TLS_PROCTABLE()->TexImage3DEXT) +#define glTexSubImage3DEXT (_GET_TLS_PROCTABLE()->TexSubImage3DEXT) +#define glGetTexFilterFuncSGIS (_GET_TLS_PROCTABLE()->GetTexFilterFuncSGIS) +#define glTexFilterFuncSGIS (_GET_TLS_PROCTABLE()->TexFilterFuncSGIS) +#define glTexSubImage1DEXT (_GET_TLS_PROCTABLE()->TexSubImage1DEXT) +#define glTexSubImage2DEXT (_GET_TLS_PROCTABLE()->TexSubImage2DEXT) +#define glCopyTexImage1DEXT (_GET_TLS_PROCTABLE()->CopyTexImage1DEXT) +#define glCopyTexImage2DEXT (_GET_TLS_PROCTABLE()->CopyTexImage2DEXT) +#define glCopyTexSubImage1DEXT (_GET_TLS_PROCTABLE()->CopyTexSubImage1DEXT) +#define glCopyTexSubImage2DEXT (_GET_TLS_PROCTABLE()->CopyTexSubImage2DEXT) +#define glCopyTexSubImage3DEXT (_GET_TLS_PROCTABLE()->CopyTexSubImage3DEXT) +#define glGetHistogramEXT (_GET_TLS_PROCTABLE()->GetHistogramEXT) +#define glGetHistogramParameterfvEXT (_GET_TLS_PROCTABLE()->GetHistogramParameterfvEXT) +#define glGetHistogramParameterivEXT (_GET_TLS_PROCTABLE()->GetHistogramParameterivEXT) +#define glGetMinmaxEXT (_GET_TLS_PROCTABLE()->GetMinmaxEXT) +#define glGetMinmaxParameterfvEXT (_GET_TLS_PROCTABLE()->GetMinmaxParameterfvEXT) +#define glGetMinmaxParameterivEXT (_GET_TLS_PROCTABLE()->GetMinmaxParameterivEXT) +#define glHistogramEXT (_GET_TLS_PROCTABLE()->HistogramEXT) +#define glMinmaxEXT (_GET_TLS_PROCTABLE()->MinmaxEXT) +#define glResetHistogramEXT (_GET_TLS_PROCTABLE()->ResetHistogramEXT) +#define glResetMinmaxEXT (_GET_TLS_PROCTABLE()->ResetMinmaxEXT) +#define glConvolutionFilter1DEXT (_GET_TLS_PROCTABLE()->ConvolutionFilter1DEXT) +#define glConvolutionFilter2DEXT (_GET_TLS_PROCTABLE()->ConvolutionFilter2DEXT) +#define glConvolutionParameterfEXT (_GET_TLS_PROCTABLE()->ConvolutionParameterfEXT) +#define glConvolutionParameterfvEXT (_GET_TLS_PROCTABLE()->ConvolutionParameterfvEXT) +#define glConvolutionParameteriEXT (_GET_TLS_PROCTABLE()->ConvolutionParameteriEXT) +#define glConvolutionParameterivEXT (_GET_TLS_PROCTABLE()->ConvolutionParameterivEXT) +#define glCopyConvolutionFilter1DEXT (_GET_TLS_PROCTABLE()->CopyConvolutionFilter1DEXT) +#define glCopyConvolutionFilter2DEXT (_GET_TLS_PROCTABLE()->CopyConvolutionFilter2DEXT) +#define glGetConvolutionFilterEXT (_GET_TLS_PROCTABLE()->GetConvolutionFilterEXT) +#define glGetConvolutionParameterfvEXT (_GET_TLS_PROCTABLE()->GetConvolutionParameterfvEXT) +#define glGetConvolutionParameterivEXT (_GET_TLS_PROCTABLE()->GetConvolutionParameterivEXT) +#define glGetSeparableFilterEXT (_GET_TLS_PROCTABLE()->GetSeparableFilterEXT) +#define glSeparableFilter2DEXT (_GET_TLS_PROCTABLE()->SeparableFilter2DEXT) +#define glColorTableSGI (_GET_TLS_PROCTABLE()->ColorTableSGI) +#define glColorTableParameterfvSGI (_GET_TLS_PROCTABLE()->ColorTableParameterfvSGI) +#define glColorTableParameterivSGI (_GET_TLS_PROCTABLE()->ColorTableParameterivSGI) +#define glCopyColorTableSGI (_GET_TLS_PROCTABLE()->CopyColorTableSGI) +#define glGetColorTableSGI (_GET_TLS_PROCTABLE()->GetColorTableSGI) +#define glGetColorTableParameterfvSGI (_GET_TLS_PROCTABLE()->GetColorTableParameterfvSGI) +#define glGetColorTableParameterivSGI (_GET_TLS_PROCTABLE()->GetColorTableParameterivSGI) +#define glPixelTexGenSGIX (_GET_TLS_PROCTABLE()->PixelTexGenSGIX) +#define glPixelTexGenParameteriSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameteriSGIS) +#define glPixelTexGenParameterivSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameterivSGIS) +#define glPixelTexGenParameterfSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameterfSGIS) +#define glPixelTexGenParameterfvSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameterfvSGIS) +#define glGetPixelTexGenParameterivSGIS (_GET_TLS_PROCTABLE()->GetPixelTexGenParameterivSGIS) +#define glGetPixelTexGenParameterfvSGIS (_GET_TLS_PROCTABLE()->GetPixelTexGenParameterfvSGIS) +#define glTexImage4DSGIS (_GET_TLS_PROCTABLE()->TexImage4DSGIS) +#define glTexSubImage4DSGIS (_GET_TLS_PROCTABLE()->TexSubImage4DSGIS) +#define glAreTexturesResidentEXT (_GET_TLS_PROCTABLE()->AreTexturesResidentEXT) +#define glBindTextureEXT (_GET_TLS_PROCTABLE()->BindTextureEXT) +#define glDeleteTexturesEXT (_GET_TLS_PROCTABLE()->DeleteTexturesEXT) +#define glGenTexturesEXT (_GET_TLS_PROCTABLE()->GenTexturesEXT) +#define glIsTextureEXT (_GET_TLS_PROCTABLE()->IsTextureEXT) +#define glPrioritizeTexturesEXT (_GET_TLS_PROCTABLE()->PrioritizeTexturesEXT) +#define glDetailTexFuncSGIS (_GET_TLS_PROCTABLE()->DetailTexFuncSGIS) +#define glGetDetailTexFuncSGIS (_GET_TLS_PROCTABLE()->GetDetailTexFuncSGIS) +#define glSharpenTexFuncSGIS (_GET_TLS_PROCTABLE()->SharpenTexFuncSGIS) +#define glGetSharpenTexFuncSGIS (_GET_TLS_PROCTABLE()->GetSharpenTexFuncSGIS) +#define glSampleMaskSGIS (_GET_TLS_PROCTABLE()->SampleMaskSGIS) +#define glSamplePatternSGIS (_GET_TLS_PROCTABLE()->SamplePatternSGIS) +#define glArrayElementEXT (_GET_TLS_PROCTABLE()->ArrayElementEXT) +#define glColorPointerEXT (_GET_TLS_PROCTABLE()->ColorPointerEXT) +#define glDrawArraysEXT (_GET_TLS_PROCTABLE()->DrawArraysEXT) +#define glEdgeFlagPointerEXT (_GET_TLS_PROCTABLE()->EdgeFlagPointerEXT) +#define glGetPointervEXT (_GET_TLS_PROCTABLE()->GetPointervEXT) +#define glIndexPointerEXT (_GET_TLS_PROCTABLE()->IndexPointerEXT) +#define glNormalPointerEXT (_GET_TLS_PROCTABLE()->NormalPointerEXT) +#define glTexCoordPointerEXT (_GET_TLS_PROCTABLE()->TexCoordPointerEXT) +#define glVertexPointerEXT (_GET_TLS_PROCTABLE()->VertexPointerEXT) +#define glBlendEquationEXT (_GET_TLS_PROCTABLE()->BlendEquationEXT) +#define glSpriteParameterfSGIX (_GET_TLS_PROCTABLE()->SpriteParameterfSGIX) +#define glSpriteParameterfvSGIX (_GET_TLS_PROCTABLE()->SpriteParameterfvSGIX) +#define glSpriteParameteriSGIX (_GET_TLS_PROCTABLE()->SpriteParameteriSGIX) +#define glSpriteParameterivSGIX (_GET_TLS_PROCTABLE()->SpriteParameterivSGIX) +#define glPointParameterfEXT (_GET_TLS_PROCTABLE()->PointParameterfEXT) +#define glPointParameterfvEXT (_GET_TLS_PROCTABLE()->PointParameterfvEXT) +#define glPointParameterfSGIS (_GET_TLS_PROCTABLE()->PointParameterfSGIS) +#define glPointParameterfvSGIS (_GET_TLS_PROCTABLE()->PointParameterfvSGIS) +#define glGetInstrumentsSGIX (_GET_TLS_PROCTABLE()->GetInstrumentsSGIX) +#define glInstrumentsBufferSGIX (_GET_TLS_PROCTABLE()->InstrumentsBufferSGIX) +#define glPollInstrumentsSGIX (_GET_TLS_PROCTABLE()->PollInstrumentsSGIX) +#define glReadInstrumentsSGIX (_GET_TLS_PROCTABLE()->ReadInstrumentsSGIX) +#define glStartInstrumentsSGIX (_GET_TLS_PROCTABLE()->StartInstrumentsSGIX) +#define glStopInstrumentsSGIX (_GET_TLS_PROCTABLE()->StopInstrumentsSGIX) +#define glFrameZoomSGIX (_GET_TLS_PROCTABLE()->FrameZoomSGIX) +#define glTagSampleBufferSGIX (_GET_TLS_PROCTABLE()->TagSampleBufferSGIX) +#define glDeformationMap3dSGIX (_GET_TLS_PROCTABLE()->DeformationMap3dSGIX) +#define glDeformationMap3fSGIX (_GET_TLS_PROCTABLE()->DeformationMap3fSGIX) +#define glDeformSGIX (_GET_TLS_PROCTABLE()->DeformSGIX) +#define glLoadIdentityDeformationMapSGIX (_GET_TLS_PROCTABLE()->LoadIdentityDeformationMapSGIX) +#define glReferencePlaneSGIX (_GET_TLS_PROCTABLE()->ReferencePlaneSGIX) +#define glFlushRasterSGIX (_GET_TLS_PROCTABLE()->FlushRasterSGIX) +#define glFogFuncSGIS (_GET_TLS_PROCTABLE()->FogFuncSGIS) +#define glGetFogFuncSGIS (_GET_TLS_PROCTABLE()->GetFogFuncSGIS) +#define glImageTransformParameteriHP (_GET_TLS_PROCTABLE()->ImageTransformParameteriHP) +#define glImageTransformParameterfHP (_GET_TLS_PROCTABLE()->ImageTransformParameterfHP) +#define glImageTransformParameterivHP (_GET_TLS_PROCTABLE()->ImageTransformParameterivHP) +#define glImageTransformParameterfvHP (_GET_TLS_PROCTABLE()->ImageTransformParameterfvHP) +#define glGetImageTransformParameterivHP (_GET_TLS_PROCTABLE()->GetImageTransformParameterivHP) +#define glGetImageTransformParameterfvHP (_GET_TLS_PROCTABLE()->GetImageTransformParameterfvHP) +#define glColorSubTableEXT (_GET_TLS_PROCTABLE()->ColorSubTableEXT) +#define glCopyColorSubTableEXT (_GET_TLS_PROCTABLE()->CopyColorSubTableEXT) +#define glHintPGI (_GET_TLS_PROCTABLE()->HintPGI) +#define glColorTableEXT (_GET_TLS_PROCTABLE()->ColorTableEXT) +#define glGetColorTableEXT (_GET_TLS_PROCTABLE()->GetColorTableEXT) +#define glGetColorTableParameterivEXT (_GET_TLS_PROCTABLE()->GetColorTableParameterivEXT) +#define glGetColorTableParameterfvEXT (_GET_TLS_PROCTABLE()->GetColorTableParameterfvEXT) +#define glGetListParameterfvSGIX (_GET_TLS_PROCTABLE()->GetListParameterfvSGIX) +#define glGetListParameterivSGIX (_GET_TLS_PROCTABLE()->GetListParameterivSGIX) +#define glListParameterfSGIX (_GET_TLS_PROCTABLE()->ListParameterfSGIX) +#define glListParameterfvSGIX (_GET_TLS_PROCTABLE()->ListParameterfvSGIX) +#define glListParameteriSGIX (_GET_TLS_PROCTABLE()->ListParameteriSGIX) +#define glListParameterivSGIX (_GET_TLS_PROCTABLE()->ListParameterivSGIX) +#define glIndexMaterialEXT (_GET_TLS_PROCTABLE()->IndexMaterialEXT) +#define glIndexFuncEXT (_GET_TLS_PROCTABLE()->IndexFuncEXT) +#define glLockArraysEXT (_GET_TLS_PROCTABLE()->LockArraysEXT) +#define glUnlockArraysEXT (_GET_TLS_PROCTABLE()->UnlockArraysEXT) +#define glCullParameterdvEXT (_GET_TLS_PROCTABLE()->CullParameterdvEXT) +#define glCullParameterfvEXT (_GET_TLS_PROCTABLE()->CullParameterfvEXT) +#define glFragmentColorMaterialSGIX (_GET_TLS_PROCTABLE()->FragmentColorMaterialSGIX) +#define glFragmentLightfSGIX (_GET_TLS_PROCTABLE()->FragmentLightfSGIX) +#define glFragmentLightfvSGIX (_GET_TLS_PROCTABLE()->FragmentLightfvSGIX) +#define glFragmentLightiSGIX (_GET_TLS_PROCTABLE()->FragmentLightiSGIX) +#define glFragmentLightivSGIX (_GET_TLS_PROCTABLE()->FragmentLightivSGIX) +#define glFragmentLightModelfSGIX (_GET_TLS_PROCTABLE()->FragmentLightModelfSGIX) +#define glFragmentLightModelfvSGIX (_GET_TLS_PROCTABLE()->FragmentLightModelfvSGIX) +#define glFragmentLightModeliSGIX (_GET_TLS_PROCTABLE()->FragmentLightModeliSGIX) +#define glFragmentLightModelivSGIX (_GET_TLS_PROCTABLE()->FragmentLightModelivSGIX) +#define glFragmentMaterialfSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialfSGIX) +#define glFragmentMaterialfvSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialfvSGIX) +#define glFragmentMaterialiSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialiSGIX) +#define glFragmentMaterialivSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialivSGIX) +#define glGetFragmentLightfvSGIX (_GET_TLS_PROCTABLE()->GetFragmentLightfvSGIX) +#define glGetFragmentLightivSGIX (_GET_TLS_PROCTABLE()->GetFragmentLightivSGIX) +#define glGetFragmentMaterialfvSGIX (_GET_TLS_PROCTABLE()->GetFragmentMaterialfvSGIX) +#define glGetFragmentMaterialivSGIX (_GET_TLS_PROCTABLE()->GetFragmentMaterialivSGIX) +#define glLightEnviSGIX (_GET_TLS_PROCTABLE()->LightEnviSGIX) +#define glDrawRangeElementsEXT (_GET_TLS_PROCTABLE()->DrawRangeElementsEXT) +#define glApplyTextureEXT (_GET_TLS_PROCTABLE()->ApplyTextureEXT) +#define glTextureLightEXT (_GET_TLS_PROCTABLE()->TextureLightEXT) +#define glTextureMaterialEXT (_GET_TLS_PROCTABLE()->TextureMaterialEXT) +#define glAsyncMarkerSGIX (_GET_TLS_PROCTABLE()->AsyncMarkerSGIX) +#define glFinishAsyncSGIX (_GET_TLS_PROCTABLE()->FinishAsyncSGIX) +#define glPollAsyncSGIX (_GET_TLS_PROCTABLE()->PollAsyncSGIX) +#define glGenAsyncMarkersSGIX (_GET_TLS_PROCTABLE()->GenAsyncMarkersSGIX) +#define glDeleteAsyncMarkersSGIX (_GET_TLS_PROCTABLE()->DeleteAsyncMarkersSGIX) +#define glIsAsyncMarkerSGIX (_GET_TLS_PROCTABLE()->IsAsyncMarkerSGIX) +#define glVertexPointervINTEL (_GET_TLS_PROCTABLE()->VertexPointervINTEL) +#define glNormalPointervINTEL (_GET_TLS_PROCTABLE()->NormalPointervINTEL) +#define glColorPointervINTEL (_GET_TLS_PROCTABLE()->ColorPointervINTEL) +#define glTexCoordPointervINTEL (_GET_TLS_PROCTABLE()->TexCoordPointervINTEL) +#define glPixelTransformParameteriEXT (_GET_TLS_PROCTABLE()->PixelTransformParameteriEXT) +#define glPixelTransformParameterfEXT (_GET_TLS_PROCTABLE()->PixelTransformParameterfEXT) +#define glPixelTransformParameterivEXT (_GET_TLS_PROCTABLE()->PixelTransformParameterivEXT) +#define glPixelTransformParameterfvEXT (_GET_TLS_PROCTABLE()->PixelTransformParameterfvEXT) +#define glSecondaryColor3bEXT (_GET_TLS_PROCTABLE()->SecondaryColor3bEXT) +#define glSecondaryColor3bvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3bvEXT) +#define glSecondaryColor3dEXT (_GET_TLS_PROCTABLE()->SecondaryColor3dEXT) +#define glSecondaryColor3dvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3dvEXT) +#define glSecondaryColor3fEXT (_GET_TLS_PROCTABLE()->SecondaryColor3fEXT) +#define glSecondaryColor3fvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3fvEXT) +#define glSecondaryColor3iEXT (_GET_TLS_PROCTABLE()->SecondaryColor3iEXT) +#define glSecondaryColor3ivEXT (_GET_TLS_PROCTABLE()->SecondaryColor3ivEXT) +#define glSecondaryColor3sEXT (_GET_TLS_PROCTABLE()->SecondaryColor3sEXT) +#define glSecondaryColor3svEXT (_GET_TLS_PROCTABLE()->SecondaryColor3svEXT) +#define glSecondaryColor3ubEXT (_GET_TLS_PROCTABLE()->SecondaryColor3ubEXT) +#define glSecondaryColor3ubvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3ubvEXT) +#define glSecondaryColor3uiEXT (_GET_TLS_PROCTABLE()->SecondaryColor3uiEXT) +#define glSecondaryColor3uivEXT (_GET_TLS_PROCTABLE()->SecondaryColor3uivEXT) +#define glSecondaryColor3usEXT (_GET_TLS_PROCTABLE()->SecondaryColor3usEXT) +#define glSecondaryColor3usvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3usvEXT) +#define glSecondaryColorPointerEXT (_GET_TLS_PROCTABLE()->SecondaryColorPointerEXT) +#define glTextureNormalEXT (_GET_TLS_PROCTABLE()->TextureNormalEXT) +#define glMultiDrawArraysEXT (_GET_TLS_PROCTABLE()->MultiDrawArraysEXT) +#define glMultiDrawElementsEXT (_GET_TLS_PROCTABLE()->MultiDrawElementsEXT) +#define glFogCoordfEXT (_GET_TLS_PROCTABLE()->FogCoordfEXT) +#define glFogCoordfvEXT (_GET_TLS_PROCTABLE()->FogCoordfvEXT) +#define glFogCoorddEXT (_GET_TLS_PROCTABLE()->FogCoorddEXT) +#define glFogCoorddvEXT (_GET_TLS_PROCTABLE()->FogCoorddvEXT) +#define glFogCoordPointerEXT (_GET_TLS_PROCTABLE()->FogCoordPointerEXT) +#define glTangent3bEXT (_GET_TLS_PROCTABLE()->Tangent3bEXT) +#define glTangent3bvEXT (_GET_TLS_PROCTABLE()->Tangent3bvEXT) +#define glTangent3dEXT (_GET_TLS_PROCTABLE()->Tangent3dEXT) +#define glTangent3dvEXT (_GET_TLS_PROCTABLE()->Tangent3dvEXT) +#define glTangent3fEXT (_GET_TLS_PROCTABLE()->Tangent3fEXT) +#define glTangent3fvEXT (_GET_TLS_PROCTABLE()->Tangent3fvEXT) +#define glTangent3iEXT (_GET_TLS_PROCTABLE()->Tangent3iEXT) +#define glTangent3ivEXT (_GET_TLS_PROCTABLE()->Tangent3ivEXT) +#define glTangent3sEXT (_GET_TLS_PROCTABLE()->Tangent3sEXT) +#define glTangent3svEXT (_GET_TLS_PROCTABLE()->Tangent3svEXT) +#define glBinormal3bEXT (_GET_TLS_PROCTABLE()->Binormal3bEXT) +#define glBinormal3bvEXT (_GET_TLS_PROCTABLE()->Binormal3bvEXT) +#define glBinormal3dEXT (_GET_TLS_PROCTABLE()->Binormal3dEXT) +#define glBinormal3dvEXT (_GET_TLS_PROCTABLE()->Binormal3dvEXT) +#define glBinormal3fEXT (_GET_TLS_PROCTABLE()->Binormal3fEXT) +#define glBinormal3fvEXT (_GET_TLS_PROCTABLE()->Binormal3fvEXT) +#define glBinormal3iEXT (_GET_TLS_PROCTABLE()->Binormal3iEXT) +#define glBinormal3ivEXT (_GET_TLS_PROCTABLE()->Binormal3ivEXT) +#define glBinormal3sEXT (_GET_TLS_PROCTABLE()->Binormal3sEXT) +#define glBinormal3svEXT (_GET_TLS_PROCTABLE()->Binormal3svEXT) +#define glTangentPointerEXT (_GET_TLS_PROCTABLE()->TangentPointerEXT) +#define glBinormalPointerEXT (_GET_TLS_PROCTABLE()->BinormalPointerEXT) +#define glFinishTextureSUNX (_GET_TLS_PROCTABLE()->FinishTextureSUNX) +#define glGlobalAlphaFactorbSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorbSUN) +#define glGlobalAlphaFactorsSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorsSUN) +#define glGlobalAlphaFactoriSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactoriSUN) +#define glGlobalAlphaFactorfSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorfSUN) +#define glGlobalAlphaFactordSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactordSUN) +#define glGlobalAlphaFactorubSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorubSUN) +#define glGlobalAlphaFactorusSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorusSUN) +#define glGlobalAlphaFactoruiSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactoruiSUN) +#define glReplacementCodeuiSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiSUN) +#define glReplacementCodeusSUN (_GET_TLS_PROCTABLE()->ReplacementCodeusSUN) +#define glReplacementCodeubSUN (_GET_TLS_PROCTABLE()->ReplacementCodeubSUN) +#define glReplacementCodeuivSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuivSUN) +#define glReplacementCodeusvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeusvSUN) +#define glReplacementCodeubvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeubvSUN) +#define glReplacementCodePointerSUN (_GET_TLS_PROCTABLE()->ReplacementCodePointerSUN) +#define glColor4ubVertex2fSUN (_GET_TLS_PROCTABLE()->Color4ubVertex2fSUN) +#define glColor4ubVertex2fvSUN (_GET_TLS_PROCTABLE()->Color4ubVertex2fvSUN) +#define glColor4ubVertex3fSUN (_GET_TLS_PROCTABLE()->Color4ubVertex3fSUN) +#define glColor4ubVertex3fvSUN (_GET_TLS_PROCTABLE()->Color4ubVertex3fvSUN) +#define glColor3fVertex3fSUN (_GET_TLS_PROCTABLE()->Color3fVertex3fSUN) +#define glColor3fVertex3fvSUN (_GET_TLS_PROCTABLE()->Color3fVertex3fvSUN) +#define glNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->Normal3fVertex3fSUN) +#define glNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->Normal3fVertex3fvSUN) +#define glColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->Color4fNormal3fVertex3fSUN) +#define glColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->Color4fNormal3fVertex3fvSUN) +#define glTexCoord2fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fVertex3fSUN) +#define glTexCoord2fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fVertex3fvSUN) +#define glTexCoord4fVertex4fSUN (_GET_TLS_PROCTABLE()->TexCoord4fVertex4fSUN) +#define glTexCoord4fVertex4fvSUN (_GET_TLS_PROCTABLE()->TexCoord4fVertex4fvSUN) +#define glTexCoord2fColor4ubVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4ubVertex3fSUN) +#define glTexCoord2fColor4ubVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4ubVertex3fvSUN) +#define glTexCoord2fColor3fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor3fVertex3fSUN) +#define glTexCoord2fColor3fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor3fVertex3fvSUN) +#define glTexCoord2fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fNormal3fVertex3fSUN) +#define glTexCoord2fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fNormal3fVertex3fvSUN) +#define glTexCoord2fColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4fNormal3fVertex3fSUN) +#define glTexCoord2fColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4fNormal3fVertex3fvSUN) +#define glTexCoord4fColor4fNormal3fVertex4fSUN (_GET_TLS_PROCTABLE()->TexCoord4fColor4fNormal3fVertex4fSUN) +#define glTexCoord4fColor4fNormal3fVertex4fvSUN (_GET_TLS_PROCTABLE()->TexCoord4fColor4fNormal3fVertex4fvSUN) +#define glReplacementCodeuiVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiVertex3fSUN) +#define glReplacementCodeuiVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiVertex3fvSUN) +#define glReplacementCodeuiColor4ubVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4ubVertex3fSUN) +#define glReplacementCodeuiColor4ubVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4ubVertex3fvSUN) +#define glReplacementCodeuiColor3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor3fVertex3fSUN) +#define glReplacementCodeuiColor3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor3fVertex3fvSUN) +#define glReplacementCodeuiNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiNormal3fVertex3fSUN) +#define glReplacementCodeuiNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glBlendFuncSeparateEXT (_GET_TLS_PROCTABLE()->BlendFuncSeparateEXT) +#define glBlendFuncSeparateINGR (_GET_TLS_PROCTABLE()->BlendFuncSeparateINGR) +#define glVertexWeightfEXT (_GET_TLS_PROCTABLE()->VertexWeightfEXT) +#define glVertexWeightfvEXT (_GET_TLS_PROCTABLE()->VertexWeightfvEXT) +#define glVertexWeightPointerEXT (_GET_TLS_PROCTABLE()->VertexWeightPointerEXT) +#define glFlushVertexArrayRangeNV (_GET_TLS_PROCTABLE()->FlushVertexArrayRangeNV) +#define glVertexArrayRangeNV (_GET_TLS_PROCTABLE()->VertexArrayRangeNV) +#define glCombinerParameterfvNV (_GET_TLS_PROCTABLE()->CombinerParameterfvNV) +#define glCombinerParameterfNV (_GET_TLS_PROCTABLE()->CombinerParameterfNV) +#define glCombinerParameterivNV (_GET_TLS_PROCTABLE()->CombinerParameterivNV) +#define glCombinerParameteriNV (_GET_TLS_PROCTABLE()->CombinerParameteriNV) +#define glCombinerInputNV (_GET_TLS_PROCTABLE()->CombinerInputNV) +#define glCombinerOutputNV (_GET_TLS_PROCTABLE()->CombinerOutputNV) +#define glFinalCombinerInputNV (_GET_TLS_PROCTABLE()->FinalCombinerInputNV) +#define glGetCombinerInputParameterfvNV (_GET_TLS_PROCTABLE()->GetCombinerInputParameterfvNV) +#define glGetCombinerInputParameterivNV (_GET_TLS_PROCTABLE()->GetCombinerInputParameterivNV) +#define glGetCombinerOutputParameterfvNV (_GET_TLS_PROCTABLE()->GetCombinerOutputParameterfvNV) +#define glGetCombinerOutputParameterivNV (_GET_TLS_PROCTABLE()->GetCombinerOutputParameterivNV) +#define glGetFinalCombinerInputParameterfvNV (_GET_TLS_PROCTABLE()->GetFinalCombinerInputParameterfvNV) +#define glGetFinalCombinerInputParameterivNV (_GET_TLS_PROCTABLE()->GetFinalCombinerInputParameterivNV) +#define glResizeBuffersMESA (_GET_TLS_PROCTABLE()->ResizeBuffersMESA) +#define glWindowPos2dMESA (_GET_TLS_PROCTABLE()->WindowPos2dMESA) +#define glWindowPos2dvMESA (_GET_TLS_PROCTABLE()->WindowPos2dvMESA) +#define glWindowPos2fMESA (_GET_TLS_PROCTABLE()->WindowPos2fMESA) +#define glWindowPos2fvMESA (_GET_TLS_PROCTABLE()->WindowPos2fvMESA) +#define glWindowPos2iMESA (_GET_TLS_PROCTABLE()->WindowPos2iMESA) +#define glWindowPos2ivMESA (_GET_TLS_PROCTABLE()->WindowPos2ivMESA) +#define glWindowPos2sMESA (_GET_TLS_PROCTABLE()->WindowPos2sMESA) +#define glWindowPos2svMESA (_GET_TLS_PROCTABLE()->WindowPos2svMESA) +#define glWindowPos3dMESA (_GET_TLS_PROCTABLE()->WindowPos3dMESA) +#define glWindowPos3dvMESA (_GET_TLS_PROCTABLE()->WindowPos3dvMESA) +#define glWindowPos3fMESA (_GET_TLS_PROCTABLE()->WindowPos3fMESA) +#define glWindowPos3fvMESA (_GET_TLS_PROCTABLE()->WindowPos3fvMESA) +#define glWindowPos3iMESA (_GET_TLS_PROCTABLE()->WindowPos3iMESA) +#define glWindowPos3ivMESA (_GET_TLS_PROCTABLE()->WindowPos3ivMESA) +#define glWindowPos3sMESA (_GET_TLS_PROCTABLE()->WindowPos3sMESA) +#define glWindowPos3svMESA (_GET_TLS_PROCTABLE()->WindowPos3svMESA) +#define glWindowPos4dMESA (_GET_TLS_PROCTABLE()->WindowPos4dMESA) +#define glWindowPos4dvMESA (_GET_TLS_PROCTABLE()->WindowPos4dvMESA) +#define glWindowPos4fMESA (_GET_TLS_PROCTABLE()->WindowPos4fMESA) +#define glWindowPos4fvMESA (_GET_TLS_PROCTABLE()->WindowPos4fvMESA) +#define glWindowPos4iMESA (_GET_TLS_PROCTABLE()->WindowPos4iMESA) +#define glWindowPos4ivMESA (_GET_TLS_PROCTABLE()->WindowPos4ivMESA) +#define glWindowPos4sMESA (_GET_TLS_PROCTABLE()->WindowPos4sMESA) +#define glWindowPos4svMESA (_GET_TLS_PROCTABLE()->WindowPos4svMESA) +#define glMultiModeDrawArraysIBM (_GET_TLS_PROCTABLE()->MultiModeDrawArraysIBM) +#define glMultiModeDrawElementsIBM (_GET_TLS_PROCTABLE()->MultiModeDrawElementsIBM) +#define glColorPointerListIBM (_GET_TLS_PROCTABLE()->ColorPointerListIBM) +#define glSecondaryColorPointerListIBM (_GET_TLS_PROCTABLE()->SecondaryColorPointerListIBM) +#define glEdgeFlagPointerListIBM (_GET_TLS_PROCTABLE()->EdgeFlagPointerListIBM) +#define glFogCoordPointerListIBM (_GET_TLS_PROCTABLE()->FogCoordPointerListIBM) +#define glIndexPointerListIBM (_GET_TLS_PROCTABLE()->IndexPointerListIBM) +#define glNormalPointerListIBM (_GET_TLS_PROCTABLE()->NormalPointerListIBM) +#define glTexCoordPointerListIBM (_GET_TLS_PROCTABLE()->TexCoordPointerListIBM) +#define glVertexPointerListIBM (_GET_TLS_PROCTABLE()->VertexPointerListIBM) +#define glTbufferMask3DFX (_GET_TLS_PROCTABLE()->TbufferMask3DFX) +#define glSampleMaskEXT (_GET_TLS_PROCTABLE()->SampleMaskEXT) +#define glSamplePatternEXT (_GET_TLS_PROCTABLE()->SamplePatternEXT) +#define glTextureColorMaskSGIS (_GET_TLS_PROCTABLE()->TextureColorMaskSGIS) +#define glIglooInterfaceSGIX (_GET_TLS_PROCTABLE()->IglooInterfaceSGIX) +#define glDeleteFencesNV (_GET_TLS_PROCTABLE()->DeleteFencesNV) +#define glGenFencesNV (_GET_TLS_PROCTABLE()->GenFencesNV) +#define glIsFenceNV (_GET_TLS_PROCTABLE()->IsFenceNV) +#define glTestFenceNV (_GET_TLS_PROCTABLE()->TestFenceNV) +#define glGetFenceivNV (_GET_TLS_PROCTABLE()->GetFenceivNV) +#define glFinishFenceNV (_GET_TLS_PROCTABLE()->FinishFenceNV) +#define glSetFenceNV (_GET_TLS_PROCTABLE()->SetFenceNV) +#define glMapControlPointsNV (_GET_TLS_PROCTABLE()->MapControlPointsNV) +#define glMapParameterivNV (_GET_TLS_PROCTABLE()->MapParameterivNV) +#define glMapParameterfvNV (_GET_TLS_PROCTABLE()->MapParameterfvNV) +#define glGetMapControlPointsNV (_GET_TLS_PROCTABLE()->GetMapControlPointsNV) +#define glGetMapParameterivNV (_GET_TLS_PROCTABLE()->GetMapParameterivNV) +#define glGetMapParameterfvNV (_GET_TLS_PROCTABLE()->GetMapParameterfvNV) +#define glGetMapAttribParameterivNV (_GET_TLS_PROCTABLE()->GetMapAttribParameterivNV) +#define glGetMapAttribParameterfvNV (_GET_TLS_PROCTABLE()->GetMapAttribParameterfvNV) +#define glEvalMapsNV (_GET_TLS_PROCTABLE()->EvalMapsNV) +#define glCombinerStageParameterfvNV (_GET_TLS_PROCTABLE()->CombinerStageParameterfvNV) +#define glGetCombinerStageParameterfvNV (_GET_TLS_PROCTABLE()->GetCombinerStageParameterfvNV) +#define glAreProgramsResidentNV (_GET_TLS_PROCTABLE()->AreProgramsResidentNV) +#define glBindProgramNV (_GET_TLS_PROCTABLE()->BindProgramNV) +#define glDeleteProgramsNV (_GET_TLS_PROCTABLE()->DeleteProgramsNV) +#define glExecuteProgramNV (_GET_TLS_PROCTABLE()->ExecuteProgramNV) +#define glGenProgramsNV (_GET_TLS_PROCTABLE()->GenProgramsNV) +#define glGetProgramParameterdvNV (_GET_TLS_PROCTABLE()->GetProgramParameterdvNV) +#define glGetProgramParameterfvNV (_GET_TLS_PROCTABLE()->GetProgramParameterfvNV) +#define glGetProgramivNV (_GET_TLS_PROCTABLE()->GetProgramivNV) +#define glGetProgramStringNV (_GET_TLS_PROCTABLE()->GetProgramStringNV) +#define glGetTrackMatrixivNV (_GET_TLS_PROCTABLE()->GetTrackMatrixivNV) +#define glGetVertexAttribdvNV (_GET_TLS_PROCTABLE()->GetVertexAttribdvNV) +#define glGetVertexAttribfvNV (_GET_TLS_PROCTABLE()->GetVertexAttribfvNV) +#define glGetVertexAttribivNV (_GET_TLS_PROCTABLE()->GetVertexAttribivNV) +#define glGetVertexAttribPointervNV (_GET_TLS_PROCTABLE()->GetVertexAttribPointervNV) +#define glIsProgramNV (_GET_TLS_PROCTABLE()->IsProgramNV) +#define glLoadProgramNV (_GET_TLS_PROCTABLE()->LoadProgramNV) +#define glProgramParameter4dNV (_GET_TLS_PROCTABLE()->ProgramParameter4dNV) +#define glProgramParameter4dvNV (_GET_TLS_PROCTABLE()->ProgramParameter4dvNV) +#define glProgramParameter4fNV (_GET_TLS_PROCTABLE()->ProgramParameter4fNV) +#define glProgramParameter4fvNV (_GET_TLS_PROCTABLE()->ProgramParameter4fvNV) +#define glProgramParameters4dvNV (_GET_TLS_PROCTABLE()->ProgramParameters4dvNV) +#define glProgramParameters4fvNV (_GET_TLS_PROCTABLE()->ProgramParameters4fvNV) +#define glRequestResidentProgramsNV (_GET_TLS_PROCTABLE()->RequestResidentProgramsNV) +#define glTrackMatrixNV (_GET_TLS_PROCTABLE()->TrackMatrixNV) +#define glVertexAttribPointerNV (_GET_TLS_PROCTABLE()->VertexAttribPointerNV) +#define glVertexAttrib1dNV (_GET_TLS_PROCTABLE()->VertexAttrib1dNV) +#define glVertexAttrib1dvNV (_GET_TLS_PROCTABLE()->VertexAttrib1dvNV) +#define glVertexAttrib1fNV (_GET_TLS_PROCTABLE()->VertexAttrib1fNV) +#define glVertexAttrib1fvNV (_GET_TLS_PROCTABLE()->VertexAttrib1fvNV) +#define glVertexAttrib1sNV (_GET_TLS_PROCTABLE()->VertexAttrib1sNV) +#define glVertexAttrib1svNV (_GET_TLS_PROCTABLE()->VertexAttrib1svNV) +#define glVertexAttrib2dNV (_GET_TLS_PROCTABLE()->VertexAttrib2dNV) +#define glVertexAttrib2dvNV (_GET_TLS_PROCTABLE()->VertexAttrib2dvNV) +#define glVertexAttrib2fNV (_GET_TLS_PROCTABLE()->VertexAttrib2fNV) +#define glVertexAttrib2fvNV (_GET_TLS_PROCTABLE()->VertexAttrib2fvNV) +#define glVertexAttrib2sNV (_GET_TLS_PROCTABLE()->VertexAttrib2sNV) +#define glVertexAttrib2svNV (_GET_TLS_PROCTABLE()->VertexAttrib2svNV) +#define glVertexAttrib3dNV (_GET_TLS_PROCTABLE()->VertexAttrib3dNV) +#define glVertexAttrib3dvNV (_GET_TLS_PROCTABLE()->VertexAttrib3dvNV) +#define glVertexAttrib3fNV (_GET_TLS_PROCTABLE()->VertexAttrib3fNV) +#define glVertexAttrib3fvNV (_GET_TLS_PROCTABLE()->VertexAttrib3fvNV) +#define glVertexAttrib3sNV (_GET_TLS_PROCTABLE()->VertexAttrib3sNV) +#define glVertexAttrib3svNV (_GET_TLS_PROCTABLE()->VertexAttrib3svNV) +#define glVertexAttrib4dNV (_GET_TLS_PROCTABLE()->VertexAttrib4dNV) +#define glVertexAttrib4dvNV (_GET_TLS_PROCTABLE()->VertexAttrib4dvNV) +#define glVertexAttrib4fNV (_GET_TLS_PROCTABLE()->VertexAttrib4fNV) +#define glVertexAttrib4fvNV (_GET_TLS_PROCTABLE()->VertexAttrib4fvNV) +#define glVertexAttrib4sNV (_GET_TLS_PROCTABLE()->VertexAttrib4sNV) +#define glVertexAttrib4svNV (_GET_TLS_PROCTABLE()->VertexAttrib4svNV) +#define glVertexAttrib4ubNV (_GET_TLS_PROCTABLE()->VertexAttrib4ubNV) +#define glVertexAttrib4ubvNV (_GET_TLS_PROCTABLE()->VertexAttrib4ubvNV) +#define glVertexAttribs1dvNV (_GET_TLS_PROCTABLE()->VertexAttribs1dvNV) +#define glVertexAttribs1fvNV (_GET_TLS_PROCTABLE()->VertexAttribs1fvNV) +#define glVertexAttribs1svNV (_GET_TLS_PROCTABLE()->VertexAttribs1svNV) +#define glVertexAttribs2dvNV (_GET_TLS_PROCTABLE()->VertexAttribs2dvNV) +#define glVertexAttribs2fvNV (_GET_TLS_PROCTABLE()->VertexAttribs2fvNV) +#define glVertexAttribs2svNV (_GET_TLS_PROCTABLE()->VertexAttribs2svNV) +#define glVertexAttribs3dvNV (_GET_TLS_PROCTABLE()->VertexAttribs3dvNV) +#define glVertexAttribs3fvNV (_GET_TLS_PROCTABLE()->VertexAttribs3fvNV) +#define glVertexAttribs3svNV (_GET_TLS_PROCTABLE()->VertexAttribs3svNV) +#define glVertexAttribs4dvNV (_GET_TLS_PROCTABLE()->VertexAttribs4dvNV) +#define glVertexAttribs4fvNV (_GET_TLS_PROCTABLE()->VertexAttribs4fvNV) +#define glVertexAttribs4svNV (_GET_TLS_PROCTABLE()->VertexAttribs4svNV) +#define glVertexAttribs4ubvNV (_GET_TLS_PROCTABLE()->VertexAttribs4ubvNV) +#define glTexBumpParameterivATI (_GET_TLS_PROCTABLE()->TexBumpParameterivATI) +#define glTexBumpParameterfvATI (_GET_TLS_PROCTABLE()->TexBumpParameterfvATI) +#define glGetTexBumpParameterivATI (_GET_TLS_PROCTABLE()->GetTexBumpParameterivATI) +#define glGetTexBumpParameterfvATI (_GET_TLS_PROCTABLE()->GetTexBumpParameterfvATI) +#define glGenFragmentShadersATI (_GET_TLS_PROCTABLE()->GenFragmentShadersATI) +#define glBindFragmentShaderATI (_GET_TLS_PROCTABLE()->BindFragmentShaderATI) +#define glDeleteFragmentShaderATI (_GET_TLS_PROCTABLE()->DeleteFragmentShaderATI) +#define glBeginFragmentShaderATI (_GET_TLS_PROCTABLE()->BeginFragmentShaderATI) +#define glEndFragmentShaderATI (_GET_TLS_PROCTABLE()->EndFragmentShaderATI) +#define glPassTexCoordATI (_GET_TLS_PROCTABLE()->PassTexCoordATI) +#define glSampleMapATI (_GET_TLS_PROCTABLE()->SampleMapATI) +#define glColorFragmentOp1ATI (_GET_TLS_PROCTABLE()->ColorFragmentOp1ATI) +#define glColorFragmentOp2ATI (_GET_TLS_PROCTABLE()->ColorFragmentOp2ATI) +#define glColorFragmentOp3ATI (_GET_TLS_PROCTABLE()->ColorFragmentOp3ATI) +#define glAlphaFragmentOp1ATI (_GET_TLS_PROCTABLE()->AlphaFragmentOp1ATI) +#define glAlphaFragmentOp2ATI (_GET_TLS_PROCTABLE()->AlphaFragmentOp2ATI) +#define glAlphaFragmentOp3ATI (_GET_TLS_PROCTABLE()->AlphaFragmentOp3ATI) +#define glSetFragmentShaderConstantATI (_GET_TLS_PROCTABLE()->SetFragmentShaderConstantATI) +#define glPNTrianglesiATI (_GET_TLS_PROCTABLE()->PNTrianglesiATI) +#define glPNTrianglesfATI (_GET_TLS_PROCTABLE()->PNTrianglesfATI) +#define glNewObjectBufferATI (_GET_TLS_PROCTABLE()->NewObjectBufferATI) +#define glIsObjectBufferATI (_GET_TLS_PROCTABLE()->IsObjectBufferATI) +#define glUpdateObjectBufferATI (_GET_TLS_PROCTABLE()->UpdateObjectBufferATI) +#define glGetObjectBufferfvATI (_GET_TLS_PROCTABLE()->GetObjectBufferfvATI) +#define glGetObjectBufferivATI (_GET_TLS_PROCTABLE()->GetObjectBufferivATI) +#define glFreeObjectBufferATI (_GET_TLS_PROCTABLE()->FreeObjectBufferATI) +#define glArrayObjectATI (_GET_TLS_PROCTABLE()->ArrayObjectATI) +#define glGetArrayObjectfvATI (_GET_TLS_PROCTABLE()->GetArrayObjectfvATI) +#define glGetArrayObjectivATI (_GET_TLS_PROCTABLE()->GetArrayObjectivATI) +#define glVariantArrayObjectATI (_GET_TLS_PROCTABLE()->VariantArrayObjectATI) +#define glGetVariantArrayObjectfvATI (_GET_TLS_PROCTABLE()->GetVariantArrayObjectfvATI) +#define glGetVariantArrayObjectivATI (_GET_TLS_PROCTABLE()->GetVariantArrayObjectivATI) +#define glBeginVertexShaderEXT (_GET_TLS_PROCTABLE()->BeginVertexShaderEXT) +#define glEndVertexShaderEXT (_GET_TLS_PROCTABLE()->EndVertexShaderEXT) +#define glBindVertexShaderEXT (_GET_TLS_PROCTABLE()->BindVertexShaderEXT) +#define glGenVertexShadersEXT (_GET_TLS_PROCTABLE()->GenVertexShadersEXT) +#define glDeleteVertexShaderEXT (_GET_TLS_PROCTABLE()->DeleteVertexShaderEXT) +#define glShaderOp1EXT (_GET_TLS_PROCTABLE()->ShaderOp1EXT) +#define glShaderOp2EXT (_GET_TLS_PROCTABLE()->ShaderOp2EXT) +#define glShaderOp3EXT (_GET_TLS_PROCTABLE()->ShaderOp3EXT) +#define glSwizzleEXT (_GET_TLS_PROCTABLE()->SwizzleEXT) +#define glWriteMaskEXT (_GET_TLS_PROCTABLE()->WriteMaskEXT) +#define glInsertComponentEXT (_GET_TLS_PROCTABLE()->InsertComponentEXT) +#define glExtractComponentEXT (_GET_TLS_PROCTABLE()->ExtractComponentEXT) +#define glGenSymbolsEXT (_GET_TLS_PROCTABLE()->GenSymbolsEXT) +#define glSetInvariantEXT (_GET_TLS_PROCTABLE()->SetInvariantEXT) +#define glSetLocalConstantEXT (_GET_TLS_PROCTABLE()->SetLocalConstantEXT) +#define glVariantbvEXT (_GET_TLS_PROCTABLE()->VariantbvEXT) +#define glVariantsvEXT (_GET_TLS_PROCTABLE()->VariantsvEXT) +#define glVariantivEXT (_GET_TLS_PROCTABLE()->VariantivEXT) +#define glVariantfvEXT (_GET_TLS_PROCTABLE()->VariantfvEXT) +#define glVariantdvEXT (_GET_TLS_PROCTABLE()->VariantdvEXT) +#define glVariantubvEXT (_GET_TLS_PROCTABLE()->VariantubvEXT) +#define glVariantusvEXT (_GET_TLS_PROCTABLE()->VariantusvEXT) +#define glVariantuivEXT (_GET_TLS_PROCTABLE()->VariantuivEXT) +#define glVariantPointerEXT (_GET_TLS_PROCTABLE()->VariantPointerEXT) +#define glEnableVariantClientStateEXT (_GET_TLS_PROCTABLE()->EnableVariantClientStateEXT) +#define glDisableVariantClientStateEXT (_GET_TLS_PROCTABLE()->DisableVariantClientStateEXT) +#define glBindLightParameterEXT (_GET_TLS_PROCTABLE()->BindLightParameterEXT) +#define glBindMaterialParameterEXT (_GET_TLS_PROCTABLE()->BindMaterialParameterEXT) +#define glBindTexGenParameterEXT (_GET_TLS_PROCTABLE()->BindTexGenParameterEXT) +#define glBindTextureUnitParameterEXT (_GET_TLS_PROCTABLE()->BindTextureUnitParameterEXT) +#define glBindParameterEXT (_GET_TLS_PROCTABLE()->BindParameterEXT) +#define glIsVariantEnabledEXT (_GET_TLS_PROCTABLE()->IsVariantEnabledEXT) +#define glGetVariantBooleanvEXT (_GET_TLS_PROCTABLE()->GetVariantBooleanvEXT) +#define glGetVariantIntegervEXT (_GET_TLS_PROCTABLE()->GetVariantIntegervEXT) +#define glGetVariantFloatvEXT (_GET_TLS_PROCTABLE()->GetVariantFloatvEXT) +#define glGetVariantPointervEXT (_GET_TLS_PROCTABLE()->GetVariantPointervEXT) +#define glGetInvariantBooleanvEXT (_GET_TLS_PROCTABLE()->GetInvariantBooleanvEXT) +#define glGetInvariantIntegervEXT (_GET_TLS_PROCTABLE()->GetInvariantIntegervEXT) +#define glGetInvariantFloatvEXT (_GET_TLS_PROCTABLE()->GetInvariantFloatvEXT) +#define glGetLocalConstantBooleanvEXT (_GET_TLS_PROCTABLE()->GetLocalConstantBooleanvEXT) +#define glGetLocalConstantIntegervEXT (_GET_TLS_PROCTABLE()->GetLocalConstantIntegervEXT) +#define glGetLocalConstantFloatvEXT (_GET_TLS_PROCTABLE()->GetLocalConstantFloatvEXT) +#define glVertexStream1sATI (_GET_TLS_PROCTABLE()->VertexStream1sATI) +#define glVertexStream1svATI (_GET_TLS_PROCTABLE()->VertexStream1svATI) +#define glVertexStream1iATI (_GET_TLS_PROCTABLE()->VertexStream1iATI) +#define glVertexStream1ivATI (_GET_TLS_PROCTABLE()->VertexStream1ivATI) +#define glVertexStream1fATI (_GET_TLS_PROCTABLE()->VertexStream1fATI) +#define glVertexStream1fvATI (_GET_TLS_PROCTABLE()->VertexStream1fvATI) +#define glVertexStream1dATI (_GET_TLS_PROCTABLE()->VertexStream1dATI) +#define glVertexStream1dvATI (_GET_TLS_PROCTABLE()->VertexStream1dvATI) +#define glVertexStream2sATI (_GET_TLS_PROCTABLE()->VertexStream2sATI) +#define glVertexStream2svATI (_GET_TLS_PROCTABLE()->VertexStream2svATI) +#define glVertexStream2iATI (_GET_TLS_PROCTABLE()->VertexStream2iATI) +#define glVertexStream2ivATI (_GET_TLS_PROCTABLE()->VertexStream2ivATI) +#define glVertexStream2fATI (_GET_TLS_PROCTABLE()->VertexStream2fATI) +#define glVertexStream2fvATI (_GET_TLS_PROCTABLE()->VertexStream2fvATI) +#define glVertexStream2dATI (_GET_TLS_PROCTABLE()->VertexStream2dATI) +#define glVertexStream2dvATI (_GET_TLS_PROCTABLE()->VertexStream2dvATI) +#define glVertexStream3sATI (_GET_TLS_PROCTABLE()->VertexStream3sATI) +#define glVertexStream3svATI (_GET_TLS_PROCTABLE()->VertexStream3svATI) +#define glVertexStream3iATI (_GET_TLS_PROCTABLE()->VertexStream3iATI) +#define glVertexStream3ivATI (_GET_TLS_PROCTABLE()->VertexStream3ivATI) +#define glVertexStream3fATI (_GET_TLS_PROCTABLE()->VertexStream3fATI) +#define glVertexStream3fvATI (_GET_TLS_PROCTABLE()->VertexStream3fvATI) +#define glVertexStream3dATI (_GET_TLS_PROCTABLE()->VertexStream3dATI) +#define glVertexStream3dvATI (_GET_TLS_PROCTABLE()->VertexStream3dvATI) +#define glVertexStream4sATI (_GET_TLS_PROCTABLE()->VertexStream4sATI) +#define glVertexStream4svATI (_GET_TLS_PROCTABLE()->VertexStream4svATI) +#define glVertexStream4iATI (_GET_TLS_PROCTABLE()->VertexStream4iATI) +#define glVertexStream4ivATI (_GET_TLS_PROCTABLE()->VertexStream4ivATI) +#define glVertexStream4fATI (_GET_TLS_PROCTABLE()->VertexStream4fATI) +#define glVertexStream4fvATI (_GET_TLS_PROCTABLE()->VertexStream4fvATI) +#define glVertexStream4dATI (_GET_TLS_PROCTABLE()->VertexStream4dATI) +#define glVertexStream4dvATI (_GET_TLS_PROCTABLE()->VertexStream4dvATI) +#define glNormalStream3bATI (_GET_TLS_PROCTABLE()->NormalStream3bATI) +#define glNormalStream3bvATI (_GET_TLS_PROCTABLE()->NormalStream3bvATI) +#define glNormalStream3sATI (_GET_TLS_PROCTABLE()->NormalStream3sATI) +#define glNormalStream3svATI (_GET_TLS_PROCTABLE()->NormalStream3svATI) +#define glNormalStream3iATI (_GET_TLS_PROCTABLE()->NormalStream3iATI) +#define glNormalStream3ivATI (_GET_TLS_PROCTABLE()->NormalStream3ivATI) +#define glNormalStream3fATI (_GET_TLS_PROCTABLE()->NormalStream3fATI) +#define glNormalStream3fvATI (_GET_TLS_PROCTABLE()->NormalStream3fvATI) +#define glNormalStream3dATI (_GET_TLS_PROCTABLE()->NormalStream3dATI) +#define glNormalStream3dvATI (_GET_TLS_PROCTABLE()->NormalStream3dvATI) +#define glClientActiveVertexStreamATI (_GET_TLS_PROCTABLE()->ClientActiveVertexStreamATI) +#define glVertexBlendEnviATI (_GET_TLS_PROCTABLE()->VertexBlendEnviATI) +#define glVertexBlendEnvfATI (_GET_TLS_PROCTABLE()->VertexBlendEnvfATI) +#define glElementPointerATI (_GET_TLS_PROCTABLE()->ElementPointerATI) +#define glDrawElementArrayATI (_GET_TLS_PROCTABLE()->DrawElementArrayATI) +#define glDrawRangeElementArrayATI (_GET_TLS_PROCTABLE()->DrawRangeElementArrayATI) +#define glDrawMeshArraysSUN (_GET_TLS_PROCTABLE()->DrawMeshArraysSUN) +#define glGenOcclusionQueriesNV (_GET_TLS_PROCTABLE()->GenOcclusionQueriesNV) +#define glDeleteOcclusionQueriesNV (_GET_TLS_PROCTABLE()->DeleteOcclusionQueriesNV) +#define glIsOcclusionQueryNV (_GET_TLS_PROCTABLE()->IsOcclusionQueryNV) +#define glBeginOcclusionQueryNV (_GET_TLS_PROCTABLE()->BeginOcclusionQueryNV) +#define glEndOcclusionQueryNV (_GET_TLS_PROCTABLE()->EndOcclusionQueryNV) +#define glGetOcclusionQueryivNV (_GET_TLS_PROCTABLE()->GetOcclusionQueryivNV) +#define glGetOcclusionQueryuivNV (_GET_TLS_PROCTABLE()->GetOcclusionQueryuivNV) +#define glPointParameteriNV (_GET_TLS_PROCTABLE()->PointParameteriNV) +#define glPointParameterivNV (_GET_TLS_PROCTABLE()->PointParameterivNV) +#define glActiveStencilFaceEXT (_GET_TLS_PROCTABLE()->ActiveStencilFaceEXT) +#define glElementPointerAPPLE (_GET_TLS_PROCTABLE()->ElementPointerAPPLE) +#define glDrawElementArrayAPPLE (_GET_TLS_PROCTABLE()->DrawElementArrayAPPLE) +#define glDrawRangeElementArrayAPPLE (_GET_TLS_PROCTABLE()->DrawRangeElementArrayAPPLE) +#define glMultiDrawElementArrayAPPLE (_GET_TLS_PROCTABLE()->MultiDrawElementArrayAPPLE) +#define glMultiDrawRangeElementArrayAPPLE (_GET_TLS_PROCTABLE()->MultiDrawRangeElementArrayAPPLE) +#define glGenFencesAPPLE (_GET_TLS_PROCTABLE()->GenFencesAPPLE) +#define glDeleteFencesAPPLE (_GET_TLS_PROCTABLE()->DeleteFencesAPPLE) +#define glSetFenceAPPLE (_GET_TLS_PROCTABLE()->SetFenceAPPLE) +#define glIsFenceAPPLE (_GET_TLS_PROCTABLE()->IsFenceAPPLE) +#define glTestFenceAPPLE (_GET_TLS_PROCTABLE()->TestFenceAPPLE) +#define glFinishFenceAPPLE (_GET_TLS_PROCTABLE()->FinishFenceAPPLE) +#define glTestObjectAPPLE (_GET_TLS_PROCTABLE()->TestObjectAPPLE) +#define glFinishObjectAPPLE (_GET_TLS_PROCTABLE()->FinishObjectAPPLE) +#define glBindVertexArrayAPPLE (_GET_TLS_PROCTABLE()->BindVertexArrayAPPLE) +#define glDeleteVertexArraysAPPLE (_GET_TLS_PROCTABLE()->DeleteVertexArraysAPPLE) +#define glGenVertexArraysAPPLE (_GET_TLS_PROCTABLE()->GenVertexArraysAPPLE) +#define glIsVertexArrayAPPLE (_GET_TLS_PROCTABLE()->IsVertexArrayAPPLE) +#define glVertexArrayRangeAPPLE (_GET_TLS_PROCTABLE()->VertexArrayRangeAPPLE) +#define glFlushVertexArrayRangeAPPLE (_GET_TLS_PROCTABLE()->FlushVertexArrayRangeAPPLE) +#define glVertexArrayParameteriAPPLE (_GET_TLS_PROCTABLE()->VertexArrayParameteriAPPLE) +#define glDrawBuffersATI (_GET_TLS_PROCTABLE()->DrawBuffersATI) +#define glProgramNamedParameter4fNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4fNV) +#define glProgramNamedParameter4dNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4dNV) +#define glProgramNamedParameter4fvNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4fvNV) +#define glProgramNamedParameter4dvNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4dvNV) +#define glGetProgramNamedParameterfvNV (_GET_TLS_PROCTABLE()->GetProgramNamedParameterfvNV) +#define glGetProgramNamedParameterdvNV (_GET_TLS_PROCTABLE()->GetProgramNamedParameterdvNV) +#define glVertex2hNV (_GET_TLS_PROCTABLE()->Vertex2hNV) +#define glVertex2hvNV (_GET_TLS_PROCTABLE()->Vertex2hvNV) +#define glVertex3hNV (_GET_TLS_PROCTABLE()->Vertex3hNV) +#define glVertex3hvNV (_GET_TLS_PROCTABLE()->Vertex3hvNV) +#define glVertex4hNV (_GET_TLS_PROCTABLE()->Vertex4hNV) +#define glVertex4hvNV (_GET_TLS_PROCTABLE()->Vertex4hvNV) +#define glNormal3hNV (_GET_TLS_PROCTABLE()->Normal3hNV) +#define glNormal3hvNV (_GET_TLS_PROCTABLE()->Normal3hvNV) +#define glColor3hNV (_GET_TLS_PROCTABLE()->Color3hNV) +#define glColor3hvNV (_GET_TLS_PROCTABLE()->Color3hvNV) +#define glColor4hNV (_GET_TLS_PROCTABLE()->Color4hNV) +#define glColor4hvNV (_GET_TLS_PROCTABLE()->Color4hvNV) +#define glTexCoord1hNV (_GET_TLS_PROCTABLE()->TexCoord1hNV) +#define glTexCoord1hvNV (_GET_TLS_PROCTABLE()->TexCoord1hvNV) +#define glTexCoord2hNV (_GET_TLS_PROCTABLE()->TexCoord2hNV) +#define glTexCoord2hvNV (_GET_TLS_PROCTABLE()->TexCoord2hvNV) +#define glTexCoord3hNV (_GET_TLS_PROCTABLE()->TexCoord3hNV) +#define glTexCoord3hvNV (_GET_TLS_PROCTABLE()->TexCoord3hvNV) +#define glTexCoord4hNV (_GET_TLS_PROCTABLE()->TexCoord4hNV) +#define glTexCoord4hvNV (_GET_TLS_PROCTABLE()->TexCoord4hvNV) +#define glMultiTexCoord1hNV (_GET_TLS_PROCTABLE()->MultiTexCoord1hNV) +#define glMultiTexCoord1hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord1hvNV) +#define glMultiTexCoord2hNV (_GET_TLS_PROCTABLE()->MultiTexCoord2hNV) +#define glMultiTexCoord2hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord2hvNV) +#define glMultiTexCoord3hNV (_GET_TLS_PROCTABLE()->MultiTexCoord3hNV) +#define glMultiTexCoord3hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord3hvNV) +#define glMultiTexCoord4hNV (_GET_TLS_PROCTABLE()->MultiTexCoord4hNV) +#define glMultiTexCoord4hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord4hvNV) +#define glFogCoordhNV (_GET_TLS_PROCTABLE()->FogCoordhNV) +#define glFogCoordhvNV (_GET_TLS_PROCTABLE()->FogCoordhvNV) +#define glSecondaryColor3hNV (_GET_TLS_PROCTABLE()->SecondaryColor3hNV) +#define glSecondaryColor3hvNV (_GET_TLS_PROCTABLE()->SecondaryColor3hvNV) +#define glVertexWeighthNV (_GET_TLS_PROCTABLE()->VertexWeighthNV) +#define glVertexWeighthvNV (_GET_TLS_PROCTABLE()->VertexWeighthvNV) +#define glVertexAttrib1hNV (_GET_TLS_PROCTABLE()->VertexAttrib1hNV) +#define glVertexAttrib1hvNV (_GET_TLS_PROCTABLE()->VertexAttrib1hvNV) +#define glVertexAttrib2hNV (_GET_TLS_PROCTABLE()->VertexAttrib2hNV) +#define glVertexAttrib2hvNV (_GET_TLS_PROCTABLE()->VertexAttrib2hvNV) +#define glVertexAttrib3hNV (_GET_TLS_PROCTABLE()->VertexAttrib3hNV) +#define glVertexAttrib3hvNV (_GET_TLS_PROCTABLE()->VertexAttrib3hvNV) +#define glVertexAttrib4hNV (_GET_TLS_PROCTABLE()->VertexAttrib4hNV) +#define glVertexAttrib4hvNV (_GET_TLS_PROCTABLE()->VertexAttrib4hvNV) +#define glVertexAttribs1hvNV (_GET_TLS_PROCTABLE()->VertexAttribs1hvNV) +#define glVertexAttribs2hvNV (_GET_TLS_PROCTABLE()->VertexAttribs2hvNV) +#define glVertexAttribs3hvNV (_GET_TLS_PROCTABLE()->VertexAttribs3hvNV) +#define glVertexAttribs4hvNV (_GET_TLS_PROCTABLE()->VertexAttribs4hvNV) +#define glPixelDataRangeNV (_GET_TLS_PROCTABLE()->PixelDataRangeNV) +#define glFlushPixelDataRangeNV (_GET_TLS_PROCTABLE()->FlushPixelDataRangeNV) +#define glPrimitiveRestartNV (_GET_TLS_PROCTABLE()->PrimitiveRestartNV) +#define glPrimitiveRestartIndexNV (_GET_TLS_PROCTABLE()->PrimitiveRestartIndexNV) +#define glMapObjectBufferATI (_GET_TLS_PROCTABLE()->MapObjectBufferATI) +#define glUnmapObjectBufferATI (_GET_TLS_PROCTABLE()->UnmapObjectBufferATI) +#define glStencilOpSeparateATI (_GET_TLS_PROCTABLE()->StencilOpSeparateATI) +#define glStencilFuncSeparateATI (_GET_TLS_PROCTABLE()->StencilFuncSeparateATI) +#define glVertexAttribArrayObjectATI (_GET_TLS_PROCTABLE()->VertexAttribArrayObjectATI) +#define glGetVertexAttribArrayObjectfvATI (_GET_TLS_PROCTABLE()->GetVertexAttribArrayObjectfvATI) +#define glGetVertexAttribArrayObjectivATI (_GET_TLS_PROCTABLE()->GetVertexAttribArrayObjectivATI) +#define glDepthBoundsEXT (_GET_TLS_PROCTABLE()->DepthBoundsEXT) +#define glBlendEquationSeparateEXT (_GET_TLS_PROCTABLE()->BlendEquationSeparateEXT) +#define glAddSwapHintRectWIN (_GET_TLS_PROCTABLE()->AddSwapHintRectWIN) +#ifdef _WIN32 +#define wglCreateBufferRegionARB (_GET_TLS_PROCTABLE()->CreateBufferRegionARB) +#define wglDeleteBufferRegionARB (_GET_TLS_PROCTABLE()->DeleteBufferRegionARB) +#define wglSaveBufferRegionARB (_GET_TLS_PROCTABLE()->SaveBufferRegionARB) +#define wglRestoreBufferRegionARB (_GET_TLS_PROCTABLE()->RestoreBufferRegionARB) +#define wglGetExtensionsStringARB (_GET_TLS_PROCTABLE()->GetExtensionsStringARB) +#define wglGetPixelFormatAttribivARB (_GET_TLS_PROCTABLE()->GetPixelFormatAttribivARB) +#define wglGetPixelFormatAttribfvARB (_GET_TLS_PROCTABLE()->GetPixelFormatAttribfvARB) +#define wglChoosePixelFormatARB (_GET_TLS_PROCTABLE()->ChoosePixelFormatARB) +#define wglMakeContextCurrentARB (_GET_TLS_PROCTABLE()->MakeContextCurrentARB) +#define wglGetCurrentReadDCARB (_GET_TLS_PROCTABLE()->GetCurrentReadDCARB) +#define wglCreatePbufferARB (_GET_TLS_PROCTABLE()->CreatePbufferARB) +#define wglGetPbufferDCARB (_GET_TLS_PROCTABLE()->GetPbufferDCARB) +#define wglReleasePbufferDCARB (_GET_TLS_PROCTABLE()->ReleasePbufferDCARB) +#define wglDestroyPbufferARB (_GET_TLS_PROCTABLE()->DestroyPbufferARB) +#define wglQueryPbufferARB (_GET_TLS_PROCTABLE()->QueryPbufferARB) +#define wglBindTexImageARB (_GET_TLS_PROCTABLE()->BindTexImageARB) +#define wglReleaseTexImageARB (_GET_TLS_PROCTABLE()->ReleaseTexImageARB) +#define wglSetPbufferAttribARB (_GET_TLS_PROCTABLE()->SetPbufferAttribARB) +#define wglCreateDisplayColorTableEXT (_GET_TLS_PROCTABLE()->CreateDisplayColorTableEXT) +#define wglLoadDisplayColorTableEXT (_GET_TLS_PROCTABLE()->LoadDisplayColorTableEXT) +#define wglBindDisplayColorTableEXT (_GET_TLS_PROCTABLE()->BindDisplayColorTableEXT) +#define wglDestroyDisplayColorTableEXT (_GET_TLS_PROCTABLE()->DestroyDisplayColorTableEXT) +#define wglGetExtensionsStringEXT (_GET_TLS_PROCTABLE()->GetExtensionsStringEXT) +#define wglMakeContextCurrentEXT (_GET_TLS_PROCTABLE()->MakeContextCurrentEXT) +#define wglGetCurrentReadDCEXT (_GET_TLS_PROCTABLE()->GetCurrentReadDCEXT) +#define wglCreatePbufferEXT (_GET_TLS_PROCTABLE()->CreatePbufferEXT) +#define wglGetPbufferDCEXT (_GET_TLS_PROCTABLE()->GetPbufferDCEXT) +#define wglReleasePbufferDCEXT (_GET_TLS_PROCTABLE()->ReleasePbufferDCEXT) +#define wglDestroyPbufferEXT (_GET_TLS_PROCTABLE()->DestroyPbufferEXT) +#define wglQueryPbufferEXT (_GET_TLS_PROCTABLE()->QueryPbufferEXT) +#define wglGetPixelFormatAttribivEXT (_GET_TLS_PROCTABLE()->GetPixelFormatAttribivEXT) +#define wglGetPixelFormatAttribfvEXT (_GET_TLS_PROCTABLE()->GetPixelFormatAttribfvEXT) +#define wglChoosePixelFormatEXT (_GET_TLS_PROCTABLE()->ChoosePixelFormatEXT) +#define wglSwapIntervalEXT (_GET_TLS_PROCTABLE()->SwapIntervalEXT) +#define wglGetSwapIntervalEXT (_GET_TLS_PROCTABLE()->GetSwapIntervalEXT) +#define wglAllocateMemoryNV (_GET_TLS_PROCTABLE()->AllocateMemoryNV) +#define wglFreeMemoryNV (_GET_TLS_PROCTABLE()->FreeMemoryNV) +#define wglGetSyncValuesOML (_GET_TLS_PROCTABLE()->GetSyncValuesOML) +#define wglGetMscRateOML (_GET_TLS_PROCTABLE()->GetMscRateOML) +#define wglSwapBuffersMscOML (_GET_TLS_PROCTABLE()->SwapBuffersMscOML) +#define wglSwapLayerBuffersMscOML (_GET_TLS_PROCTABLE()->SwapLayerBuffersMscOML) +#define wglWaitForMscOML (_GET_TLS_PROCTABLE()->WaitForMscOML) +#define wglWaitForSbcOML (_GET_TLS_PROCTABLE()->WaitForSbcOML) +#define wglGetDigitalVideoParametersI3D (_GET_TLS_PROCTABLE()->GetDigitalVideoParametersI3D) +#define wglSetDigitalVideoParametersI3D (_GET_TLS_PROCTABLE()->SetDigitalVideoParametersI3D) +#define wglGetGammaTableParametersI3D (_GET_TLS_PROCTABLE()->GetGammaTableParametersI3D) +#define wglSetGammaTableParametersI3D (_GET_TLS_PROCTABLE()->SetGammaTableParametersI3D) +#define wglGetGammaTableI3D (_GET_TLS_PROCTABLE()->GetGammaTableI3D) +#define wglSetGammaTableI3D (_GET_TLS_PROCTABLE()->SetGammaTableI3D) +#define wglEnableGenlockI3D (_GET_TLS_PROCTABLE()->EnableGenlockI3D) +#define wglDisableGenlockI3D (_GET_TLS_PROCTABLE()->DisableGenlockI3D) +#define wglIsEnabledGenlockI3D (_GET_TLS_PROCTABLE()->IsEnabledGenlockI3D) +#define wglGenlockSourceI3D (_GET_TLS_PROCTABLE()->GenlockSourceI3D) +#define wglGetGenlockSourceI3D (_GET_TLS_PROCTABLE()->GetGenlockSourceI3D) +#define wglGenlockSourceEdgeI3D (_GET_TLS_PROCTABLE()->GenlockSourceEdgeI3D) +#define wglGetGenlockSourceEdgeI3D (_GET_TLS_PROCTABLE()->GetGenlockSourceEdgeI3D) +#define wglGenlockSampleRateI3D (_GET_TLS_PROCTABLE()->GenlockSampleRateI3D) +#define wglGetGenlockSampleRateI3D (_GET_TLS_PROCTABLE()->GetGenlockSampleRateI3D) +#define wglGenlockSourceDelayI3D (_GET_TLS_PROCTABLE()->GenlockSourceDelayI3D) +#define wglGetGenlockSourceDelayI3D (_GET_TLS_PROCTABLE()->GetGenlockSourceDelayI3D) +#define wglQueryGenlockMaxSourceDelayI3D (_GET_TLS_PROCTABLE()->QueryGenlockMaxSourceDelayI3D) +#define wglCreateImageBufferI3D (_GET_TLS_PROCTABLE()->CreateImageBufferI3D) +#define wglDestroyImageBufferI3D (_GET_TLS_PROCTABLE()->DestroyImageBufferI3D) +#define wglAssociateImageBufferEventsI3D (_GET_TLS_PROCTABLE()->AssociateImageBufferEventsI3D) +#define wglReleaseImageBufferEventsI3D (_GET_TLS_PROCTABLE()->ReleaseImageBufferEventsI3D) +#define wglEnableFrameLockI3D (_GET_TLS_PROCTABLE()->EnableFrameLockI3D) +#define wglDisableFrameLockI3D (_GET_TLS_PROCTABLE()->DisableFrameLockI3D) +#define wglIsEnabledFrameLockI3D (_GET_TLS_PROCTABLE()->IsEnabledFrameLockI3D) +#define wglQueryFrameLockMasterI3D (_GET_TLS_PROCTABLE()->QueryFrameLockMasterI3D) +#define wglGetFrameUsageI3D (_GET_TLS_PROCTABLE()->GetFrameUsageI3D) +#define wglBeginFrameTrackingI3D (_GET_TLS_PROCTABLE()->BeginFrameTrackingI3D) +#define wglEndFrameTrackingI3D (_GET_TLS_PROCTABLE()->EndFrameTrackingI3D) +#define wglQueryFrameTrackingI3D (_GET_TLS_PROCTABLE()->QueryFrameTrackingI3D) +#endif /* _WIN32 */ + +#ifndef _APP_PROCTABLE + +/* + * Applications can replace the following function with its own function + * for accessing thread local proc/context dependent proc table. + * The following default function works for most applications which + * are using the same device for all their contexts - even if + * the contexts are on different threads. + */ + +static _inline _GLextensionProcs *_GET_TLS_PROCTABLE(void) + +{ + extern _GLextensionProcs _extensionProcs; + + return (&_extensionProcs); +} + +#else + +/* + * Application should replace this compiled function with + * an inlined function for maximum performance. + */ + +extern _GLextensionProcs *_GET_TLS_PROCTABLE(void); + +#endif + +/* + * Provide an initialization function for the application + * to initialize its own proc tables in case the application + * needs to use multiple proc tables. + */ + +static _inline void _InitExtensionProcs(_GLextensionProcs *appProcs) +{ + extern _GLextensionProcs _extensionProcs; + + *appProcs = _extensionProcs; +} + +#ifdef __cplusplus +} +#endif + + +#endif /* _GLPROCS_H_ */ diff --git a/plugins/zzogl-pg/opengl/install-sh b/plugins/zzogl-pg/opengl/install-sh new file mode 100644 index 0000000000..4d4a9519ea --- /dev/null +++ b/plugins/zzogl-pg/opengl/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/plugins/zzogl-pg/opengl/memcpy_amd.cpp b/plugins/zzogl-pg/opengl/memcpy_amd.cpp new file mode 100644 index 0000000000..dfd1119330 --- /dev/null +++ b/plugins/zzogl-pg/opengl/memcpy_amd.cpp @@ -0,0 +1,478 @@ +/****************************************************************************** + + Copyright (c) 2001 Advanced Micro Devices, Inc. + + LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY + EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, + NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY + PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY + DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, + BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR + INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION + OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY + NOT APPLY TO YOU. + + AMD does not assume any responsibility for any errors which may appear in the + Materials nor any responsibility to support or update the Materials. AMD retains + the right to make changes to its test specifications at any time, without notice. + + NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + further information, software, technical information, know-how, or show-how + available to you. + + So that all may benefit from your experience, please report any problems + or suggestions about this software to 3dsdk.support@amd.com + + AMD Developer Technologies, M/S 585 + Advanced Micro Devices, Inc. + 5900 E. Ben White Blvd. + Austin, TX 78741 + 3dsdk.support@amd.com +******************************************************************************/ + +#include + +/***************************************************************************** +MEMCPY_AMD.CPP +******************************************************************************/ + +// Very optimized memcpy() routine for AMD Athlon and Duron family. +// This code uses any of FOUR different basic copy methods, depending +// on the transfer size. +// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or +// "Streaming Store"), and also uses the software prefetch instructions, +// be sure you're running on Athlon/Duron or other recent CPU before calling! + +#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". + +#define IN_CACHE_COPY 2 * 1024 // upper limit for movq/movq copy w/SW prefetch +// Next is a copy that uses the MMX registers to copy 8 bytes at a time, +// also using the "unrolled loop" optimization. This code uses +// the software prefetch instruction to get the data into the cache. + +#define UNCACHED_COPY 4 * 1024 // upper limit for movq/movntq w/SW prefetch +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE" + +#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch +#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. + +//#include + +// Inline assembly syntax for use with Visual C++ +#ifdef _WIN32 +#include +#endif + +extern "C" { +#include "PS2Etypes.h" + +#if defined(_MSC_VER) && !defined(__x86_64__) + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ + __asm { + mov ecx, [n] ; number of bytes to copy + mov edi, [dest] ; destination + mov esi, [src] ; source + mov ebx, ecx ; keep a copy of count + + cld + cmp ecx, TINY_BLOCK_COPY + jb $memcpy_ic_3 ; tiny? skip mmx copy + + cmp ecx, 32*1024 ; don't align between 32k-64k because + jbe $memcpy_do_align ; it appears to be slower + cmp ecx, 64*1024 + jbe $memcpy_align_done +$memcpy_do_align: + mov ecx, 8 ; a trick that's faster than rep movsb... + sub ecx, edi ; align destination to qword + and ecx, 111b ; get the low bits + sub ebx, ecx ; update copy count + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_align_done + jmp ecx ; jump to array of movsb's + +align 4 + movsb + movsb + movsb + movsb + movsb + movsb + movsb + movsb + +$memcpy_align_done: ; destination is dword aligned + mov ecx, ebx ; number of bytes left to copy + shr ecx, 6 ; get 64-byte block count + jz $memcpy_ic_2 ; finish the last few bytes + + cmp ecx, IN_CACHE_COPY/64 ; too big 4 cache? use uncached copy + jae $memcpy_uc_test + +// This is small block copy that uses the MMX registers to copy 8 bytes +// at a time. It uses the "unrolled loop" optimization, and also uses +// the software prefetch instruction to get the data into the cache. +align 16 +$memcpy_ic_1: ; 64-byte block copies, in-cache copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0, [esi+0] ; read 64 bits + movq mm1, [esi+8] + movq [edi+0], mm0 ; write 64 bits + movq [edi+8], mm1 ; note: the normal movq writes the + movq mm2, [esi+16] ; data to cache; a cache line will be + movq mm3, [esi+24] ; allocated as needed, to store the data + movq [edi+16], mm2 + movq [edi+24], mm3 + movq mm0, [esi+32] + movq mm1, [esi+40] + movq [edi+32], mm0 + movq [edi+40], mm1 + movq mm2, [esi+48] + movq mm3, [esi+56] + movq [edi+48], mm2 + movq [edi+56], mm3 + + add esi, 64 ; update source pointer + add edi, 64 ; update destination pointer + dec ecx ; count down + jnz $memcpy_ic_1 ; last 64-byte block? + +$memcpy_ic_2: + mov ecx, ebx ; has valid low 6 bits of the byte count +$memcpy_ic_3: + shr ecx, 2 ; dword count + and ecx, 1111b ; only look at the "remainder" bits + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_last_few + jmp ecx ; jump to array of movsd's + +$memcpy_uc_test: + cmp ecx, UNCACHED_COPY/64 ; big enough? use block prefetch copy + jae $memcpy_bp_1 + +$memcpy_64_test: + or ecx, ecx ; tail end of block prefetch will jump here + jz $memcpy_ic_2 ; no more 64-byte blocks left + +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +align 16 +$memcpy_uc_1: ; 64-byte blocks, uncached copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0,[esi+0] ; read 64 bits + add edi,64 ; update destination pointer + movq mm1,[esi+8] + add esi,64 ; update source pointer + movq mm2,[esi-48] + movntq [edi-64], mm0 ; write 64 bits, bypassing the cache + movq mm0,[esi-40] ; note: movntq also prevents the CPU + movntq [edi-56], mm1 ; from READING the destination address + movq mm1,[esi-32] ; into the cache, only to be over-written + movntq [edi-48], mm2 ; so that also helps performance + movq mm2,[esi-24] + movntq [edi-40], mm0 + movq mm0,[esi-16] + movntq [edi-32], mm1 + movq mm1,[esi-8] + movntq [edi-24], mm2 + movntq [edi-16], mm0 + dec ecx + movntq [edi-8], mm1 + jnz $memcpy_uc_1 ; last 64-byte block? + + jmp $memcpy_ic_2 ; almost done + +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. +$memcpy_bp_1: ; large blocks, block prefetch copy + + cmp ecx, CACHEBLOCK ; big enough to run another prefetch loop? + jl $memcpy_64_test ; no, back to regular uncached copy + + mov eax, CACHEBLOCK / 2 ; block prefetch loop, unrolled 2X + add esi, CACHEBLOCK * 64 ; move to the top of the block +align 16 +$memcpy_bp_2: + mov edx, [esi-64] ; grab one address per cache line + mov edx, [esi-128] ; grab one address per cache line + sub esi, 128 ; go reverse order to suppress HW prefetcher + dec eax ; count down the cache lines + jnz $memcpy_bp_2 ; keep grabbing more lines into cache + + mov eax, CACHEBLOCK ; now that it's in cache, do the copy +align 16 +$memcpy_bp_3: + movq mm0, [esi ] ; read 64 bits + movq mm1, [esi+ 8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + add esi, 64 ; update source pointer + movntq [edi ], mm0 ; write 64 bits, bypassing cache + movntq [edi+ 8], mm1 ; note: movntq also prevents the CPU + movntq [edi+16], mm2 ; from READING the destination address + movntq [edi+24], mm3 ; into the cache, only to be over-written, + movntq [edi+32], mm4 ; so that also helps performance + movntq [edi+40], mm5 + movntq [edi+48], mm6 + movntq [edi+56], mm7 + add edi, 64 ; update dest pointer + + dec eax ; count down + + jnz $memcpy_bp_3 ; keep copying + sub ecx, CACHEBLOCK ; update the 64-byte block count + jmp $memcpy_bp_1 ; keep processing chunks + +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". Then it handles the last few bytes. +align 4 + movsd + movsd ; perform last 1-15 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + movsd + movsd ; perform last 1-7 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + +$memcpy_last_few: ; dword aligned from before movsd's + mov ecx, ebx ; has valid low 2 bits of the byte count + and ecx, 11b ; the last few cows must come home + jz $memcpy_final ; no more, let's leave + rep movsb ; the last 1, 2, or 3 bytes + +$memcpy_final: + emms ; clean up the MMX state + sfence ; flush the write buffer + mov eax, [dest] ; ret value = destination pointer + + } +} + +// mmx memcpy implementation, size has to be a multiple of 8 +// returns 0 is equal, nonzero value if not equal +// ~10 times faster than standard memcmp +// (zerofrog) +u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +{ + assert( (cmpsize&7) == 0 ); + + __asm { +push esi + mov ecx, cmpsize + mov edx, src1 + mov esi, src2 + + cmp ecx, 32 + jl Done4 + + // custom test first 8 to make sure things are ok + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + movq mm2, [esi+16] + pmovmskb eax, mm0 + movq mm3, [esi+24] + + // check if eq + cmp eax, 0xff + je NextComp + mov eax, 1 + jmp End + +NextComp: + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je ContinueTest + mov eax, 1 + jmp End + + cmp ecx, 64 + jl Done8 + +Cmp8: + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pcmpeqd mm4, [edx+32] + pand mm0, mm2 + pcmpeqd mm5, [edx+40] + pand mm0, mm3 + pcmpeqd mm6, [edx+48] + pand mm0, mm4 + pcmpeqd mm7, [edx+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je Continue + mov eax, 1 + jmp End + +Continue: + sub ecx, 64 + add esi, 64 + add edx, 64 +ContinueTest: + cmp ecx, 64 + jge Cmp8 + +Done8: + test ecx, 0x20 + jz Done4 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je Done4 + mov eax, 1 + jmp End + +Done4: + cmp ecx, 24 + jne Done2 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done2: + cmp ecx, 16 + jne Done1 + + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done1: + cmp ecx, 8 + jne Done + + mov eax, [esi] + mov esi, [esi+4] + cmp eax, [edx] + je Next + mov eax, 1 + jmp End + +Next: + cmp esi, [edx+4] + setne al + jmp End + +Done: + xor eax, eax + +End: + pop esi + emms + } +} + +#else // _MSC_VER +// assume gcc or mingw or win x64 + +#include +#include + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ +memcpy(dest, src, n); +return dest; +} + + +#endif + +} diff --git a/plugins/zzogl-pg/opengl/missing b/plugins/zzogl-pg/opengl/missing new file mode 120000 index 0000000000..20bc5b0ed9 --- /dev/null +++ b/plugins/zzogl-pg/opengl/missing @@ -0,0 +1 @@ +/usr/share/automake-1.11/missing \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/ps2hw.dat b/plugins/zzogl-pg/opengl/ps2hw.dat new file mode 100644 index 0000000000000000000000000000000000000000..970b7b17e9906e67a7678211bd4e1e1177a01fbb GIT binary patch literal 108445 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 g_fBilinear.z ) // region repeat mode for x (umsk&x)|ufix + final.x = texRECT(g_sBitwiseANDX, abs(coord.x)*TexWrapMode.zz).x * g_fClampExts.x + g_fClampExts.z; + if( TexWrapMode.y > g_fBilinear.z ) // region repeat mode for x (vmsk&x)|vfix + final.y = texRECT(g_sBitwiseANDY, abs(coord.y)*TexWrapMode.ww).x * g_fClampExts.y + g_fClampExts.w; + + return final; +} + +#else + +float2 ps2addr(float2 coord) +{ + return frac(clamp(coord.xy, g_fClampExts.xy, g_fClampExts.zw)); +} + +#endif + +half4 tex2DPS_32(float2 tex0) +{ + return texRECT(g_sMemory, ps2memcoord(tex0).xy); +} + +// use when texture is not tiled -- shader 1 +half4 tex2DPS_tex32(float2 tex0) +{ + return texRECT(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw)*g_fZBias.zzzw+g_fPageOffset.w; +} + +// use when texture is not tiled -- shader 2 +half4 tex2DPS_clut32(float2 tex0) +{ + float index = texRECT(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw).a+g_fPageOffset.w; + return tex2D(g_sCLUT, index*g_fExactColor.xz+g_fExactColor.yz); +} + +// Shader 3 +// use when texture is not tiled and converting from 32bit to 16bit +// don't convert on the block level, only on the column level +// so every other 8 pixels, use the upper bits instead of lower +half4 tex2DPS_tex32to16(float2 tex0) +{ + bool upper = false; + tex0.y += g_fPageOffset.z; + float2 ffrac = fmod(tex0, g_fTexOffset.xy); + tex0.xy = g_fc0.ww * (tex0.xy + ffrac); + if( ffrac.x > g_fTexOffset.z ) { + tex0.x -= g_fTexOffset.z; + upper = true; + } + if( ffrac.y >= g_fTexOffset.w ) { + tex0.y -= g_fTexOffset.w; + tex0.x += g_fc0.w; + } + + half4 color = texRECT(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw)*g_fZBias.zzzw+g_fPageOffset.w; + float2 uv = upper ? color.xw : color.zy; + return tex2D(g_sConv16to32, uv+g_fPageOffset.xy); +} + +// Shader 4 +// used when a 16 bit texture is used an 8h +half4 tex2DPS_tex16to8h(float2 tex0) +{ + float4 final; + float2 ffrac = fmod(tex0+g_fPageOffset.zw, g_fTexOffset.xy); + tex0.xy = g_fPageOffset.xy * tex0.xy - ffrac * g_fc0.yw; + + if( ffrac.x > g_fTexOffset.x*g_fc0.w ) + tex0.x += g_fTexOffset.x*g_fc0.w; + if( tex0.x >= g_fc0.y ) tex0 += g_fTexOffset.zw; + + float4 upper = texRECT(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw); + + // only need alpha + float index = tex3D(g_sConv32to16, upper.zyx-g_fc0.z).y + upper.w*g_fc0.w*g_fc0.w; + return tex2D(g_sCLUT, index+g_fExactColor.yz); +} + +// Shader 5 +// used when a 16 bit texture is used a 32bit one +half4 tex2DPS_tex16to32(float2 tex0) +{ + float4 final; + float2 ffrac = fmod(tex0+g_fPageOffset.zw, g_fTexOffset.xy); + //tex0.xy = g_fPageOffset.xy * tex0.xy - ffrac * g_fc0.yw; + tex0.y += g_fPageOffset.y * ffrac.y; + + if( ffrac.x > g_fTexOffset.z ) { + tex0.x -= g_fTexOffset.z; + tex0.y += g_fTexOffset.w; + } + + float fconst = g_fc0.w*g_fc0.w; + float4 lower = tex2D(g_sSrcFinal, g_fTexDims.xy*tex0); + float4 upper = tex2D(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw); + + final.zy = tex3D(g_sConv32to16, lower.zyx).xy + lower.ww*fconst; + final.xw = tex3D(g_sConv32to16, upper.zyx).xy + upper.ww*fconst; + return final; +} + + +//half4 f; +//f.w = old.y > (127.2f/255.0f) ? 1 : 0; +//old.y -= 0.5f * f.w; +//f.xyz = frac(old.yyx*half3(2.002*255.0f/256.0f, 64.025f*255.0f/256.0f, 8.002*255.0f/256.0f)); +//f.y += old.x * (0.25f*255.0f/256.0f); + +//////////////////////////////// +// calculates the texture color +//////////////////////////////// + +#define decl_ps2shade(num) \ +decl_ps2shade_##num(_32) \ +decl_ps2shade_##num(_tex32) \ +decl_ps2shade_##num(_clut32) \ +decl_ps2shade_##num(_tex32to16) \ +decl_ps2shade_##num(_tex16to8h) \ +decl_ps2shade_##num(_tex16to32h) \ + +// nearest +#define decl_ps2shade_0(bit) \ +half4 ps2shade0##bit( TEX_DECL tex) \ +{ \ + return tex2DPS##bit( ps2addr(TEX_XY)); \ +} \ + +// do fast memcoord4 calcs when textures behave well +#ifdef REPEAT +#define PS2MEMCOORD4 ps2memcoord4 +#else +#define PS2MEMCOORD4 ps2memcoord4 +#endif + +#define decl_BilinearFilter(bit, addrfn) \ +half4 BilinearFilter##bit(float2 tex0) \ +{ \ + float4 off0, off1; \ + float4 ftex; \ + float2 ffrac; \ + ftex.xy = tex0 + g_fBilinear.xy * g_fRealTexDims.zw; \ + ffrac = frac(ftex.xy*g_fRealTexDims.xy); \ + ftex.xy -= ffrac.xy * g_fRealTexDims.zw; \ + \ + ftex.zw = ps2addr(ftex.xy + g_fRealTexDims.zw); \ + ftex.xy = ps2addr(ftex.xy); \ + \ + PS2MEMCOORD4(ftex, off0, off1); \ + half4 c0 = texRECT(g_sMemory, off0.xy); \ + half4 c1 = texRECT(g_sMemory, off0.zw); \ + half4 c2 = texRECT(g_sMemory, off1.xy); \ + half4 c3 = texRECT(g_sMemory, off1.zw); \ + return lerp( lerp(c0, c1, ffrac.x), lerp(c2, c3, ffrac.x), ffrac.y ); \ +} \ + +decl_BilinearFilter(_32, ps2addr) +decl_BilinearFilter(_tex32, ps2addr) +decl_BilinearFilter(_clut32, ps2addr) +decl_BilinearFilter(_tex32to16, ps2addr) +decl_BilinearFilter(_tex16to8h, ps2addr) +decl_BilinearFilter(_tex16to32h, ps2addr) + +//TODO! For mip maps, only apply when LOD >= 0 +// lcm == 0, LOD = log(1/Q)*L + K, lcm == 1, LOD = K + +// bilinear +#define decl_ps2shade_1(bit) \ +half4 ps2shade1##bit(TEX_DECL tex) \ +{ \ + return BilinearFilter##bit(TEX_XY); \ +} \ + +// nearest, mip nearest +#define decl_ps2shade_2(bit) \ +half4 ps2shade2##bit(TEX_DECL tex) \ +{ \ + return tex2DPS##bit( ps2addr(TEX_XY)); \ +} \ + +// nearest, mip linear +#define decl_ps2shade_3(bit) \ +half4 ps2shade3##bit(TEX_DECL tex) \ +{ \ + return tex2DPS##bit(ps2addr(TEX_XY)); \ +} \ + +// linear, mip nearest +#define decl_ps2shade_4(bit) \ +half4 ps2shade4##bit(TEX_DECL tex) \ +{ \ + return BilinearFilter##bit(TEX_XY); \ +} \ + +// linear, mip linear +#define decl_ps2shade_5(bit) \ +half4 ps2shade5##bit(TEX_DECL tex) \ +{ \ + return BilinearFilter##bit(TEX_XY); \ +} \ + +decl_ps2shade(0) +decl_ps2shade(1) +decl_ps2shade(2) +decl_ps2shade(3) +decl_ps2shade(4) +decl_ps2shade(5) + +half4 ps2CalcShade(half4 texcol, half4 color) +{ +#ifdef TEST_AEM + if( dot(texcol.xyzw, g_fTestBlack.xyzw) <= g_fc0.z ) + texcol.w = g_fc0.x; + else +#endif + texcol.w = texcol.w * fTexAlpha.y + fTexAlpha.x; + + texcol = texcol * (fTexAlpha2.zzzw * color + fTexAlpha2.xxxy) + fTexAlpha.zzzw * color.wwww; + + return texcol; +} + +// final ops on the color +#ifdef EXACT_COLOR + +half4 ps2FinalColor(half4 col) +{ + // g_fOneColor has to scale by 255 + half4 temp = col * g_fOneColor.xxxy + g_fOneColor.zzzw; + temp.w = floor(temp.w)*g_fExactColor.w; + return temp; +} + +#else +half4 ps2FinalColor(half4 col) +{ + return col * g_fOneColor.xxxy + g_fOneColor.zzzw; +} +#endif + +//////////////// +// Techniques // +//////////////// + +// technique to copy a rectangle from source to target +struct VSOUT_ +{ + float4 pos : POSITION; + half4 color : COLOR0; + DOZWRITE(float4 z : TEXCOORD0;) +}; + +struct VSOUT_T +{ + float4 pos : POSITION; + half4 color : COLOR0; + TEX_DECL tex : TEXCOORD0; + DOZWRITE(float4 z : TEXCOORD1;) +}; + +struct VSOUT_F +{ + float4 pos : POSITION; + half4 color : COLOR0; + float fog : TEXCOORD0; + DOZWRITE(float4 z : TEXCOORD1;) +}; + +struct VSOUT_TF +{ + float4 pos : POSITION; + half4 color : COLOR0; + TEX_DECL tex : TEXCOORD0; + half fog : TEXCOORD1; + DOZWRITE(float4 z : TEXCOORD2;) +}; + +// just smooth shadering +VSOUT_ RegularVS(float4 pos : POSITION, + half4 color : COLOR0, + float4 z : COLOR1 + ) +{ + VSOUT_ o; + + o.pos.xy = pos.xy*g_fPosXY.xy+g_fPosXY.zw; + o.pos.z = (log(g_fc0.y+dot(g_fZ, z.zyxw))*g_fZNorm.x+g_fZNorm.y) * g_fZMin.y + dot(g_fZ, z.zyxw) * g_fZMin.x ; + o.pos.w = g_fc0.y; // 1 + o.color = color; + + DOZWRITE(o.z = z*g_fZBias.x+g_fZBias.y; o.z.w = g_fc0.y;) + return o; +} + +void RegularPS(VSOUT_ i, out float4 c0 : COLOR0 +#ifdef WRITE_DEPTH + , out float4 c1 : COLOR1 +#endif + ) +{ + // whenever outputting depth, make sure to mult by 255/256 and 1 + c0 = ps2FinalColor(i.color); + DOZWRITE(c1 = i.z;) +} + +// diffuse texture mapping +VSOUT_T TextureVS(float4 pos : POSITION, + half4 color : COLOR0, + float4 z : COLOR1, + float3 tex0 : TEXCOORD0) +{ + VSOUT_T o; + o.pos.xy = pos.xy*g_fPosXY.xy+g_fPosXY.zw; + o.pos.z = (log(g_fc0.y+dot(g_fZ, z.zyxw))*g_fZNorm.x + g_fZNorm.y) * g_fZMin.y + dot(g_fZ, z.zyxw) * g_fZMin.x ; + o.pos.w = g_fc0.y; + o.color = color; + DOZWRITE(o.z = z*g_fZBias.x+g_fZBias.y; o.z.w = g_fc0.y;) +#ifdef PERSPECTIVE_CORRECT_TEX + o.tex = tex0; +#else + o.tex = tex0.xy/tex0.z; +#endif + return o; +} + +#ifdef WRITE_DEPTH + +#define DECL_TEXPS(num, bit) \ +void Texture##num##bit##PS(VSOUT_T i, out half4 c0 : COLOR0, out float4 c1 : COLOR1) \ +{ \ + c0 = ps2FinalColor(ps2CalcShade(ps2shade##num##bit(i.tex), i.color)); \ + c1 = i.z; \ +} \ + +#else + +#define DECL_TEXPS(num, bit) \ +void Texture##num##bit##PS(VSOUT_T i, out half4 c0 : COLOR0) \ +{ \ + c0 = ps2FinalColor(ps2CalcShade(ps2shade##num##bit(i.tex), i.color)); \ +} \ + +#endif + +#define DECL_TEXPS_(num) \ +DECL_TEXPS(num, _32) \ +DECL_TEXPS(num, _tex32) \ +DECL_TEXPS(num, _clut32) \ +DECL_TEXPS(num, _tex32to16) \ +DECL_TEXPS(num, _tex16to8h) \ + +DECL_TEXPS_(0) +DECL_TEXPS_(1) +DECL_TEXPS_(2) +DECL_TEXPS_(3) +DECL_TEXPS_(4) +DECL_TEXPS_(5) + +VSOUT_F RegularFogVS(float4 pos : POSITION, + half4 color : COLOR0, + float4 z : COLOR1) +{ + VSOUT_F o; + + o.pos.xy = pos.xy*g_fPosXY.xy+g_fPosXY.zw; + o.pos.z = (log(g_fc0.y+dot(g_fZ, z.zyxw))*g_fZNorm.x+g_fZNorm.y) * g_fZMin.y + dot(g_fZ, z.zyxw) * g_fZMin.x ; + o.pos.w = g_fc0.y; + DOZWRITE(o.z = z*g_fZBias.x+g_fZBias.y; o.z.w = g_fc0.y;) + o.color = color; + o.fog = pos.z*g_fBilinear.w; + return o; +} + +void RegularFogPS(VSOUT_F i, out half4 c0 : COLOR0 +#ifdef WRITE_DEPTH + , out float4 c1 : COLOR1 +#endif + ) +{ + half4 c; + c.xyz = lerp(g_fFogColor.xyz, i.color.xyz, i.fog); + c.w = i.color.w; + c0 = ps2FinalColor(c); + DOZWRITE(c1 = i.z;) +} + +VSOUT_TF TextureFogVS(float4 pos : POSITION, + half4 color : COLOR0, + float4 z : COLOR1, + float3 tex0 : TEXCOORD0) +{ + VSOUT_TF o; + + o.pos.xy = pos.xy*g_fPosXY.xy+g_fPosXY.zw; + o.pos.z = (log(g_fc0.y+dot(g_fZ, z.zyxw))*g_fZNorm.x+g_fZNorm.y) * g_fZMin.y + dot(g_fZ, z.zyxw) * g_fZMin.x ; + o.pos.w = g_fc0.y; + o.color = color; + o.fog = pos.z*g_fBilinear.w; + DOZWRITE(o.z = z*g_fZBias.x+g_fZBias.y; o.z.w = g_fc0.y;) +#ifdef PERSPECTIVE_CORRECT_TEX + o.tex = tex0; +#else + o.tex = tex0.xy/tex0.z; +#endif + return o; +} + +#ifdef WRITE_DEPTH + +#define DECL_TEXFOGPS(num, bit) \ +void TextureFog##num##bit##PS(VSOUT_TF i, out half4 c0 : COLOR0, out float4 c1 : COLOR1 ) \ +{ \ + half4 c = ps2CalcShade(ps2shade##num##bit(i.tex), i.color); \ + c.xyz = lerp(g_fFogColor.xyz, c.xyz, i.fog); \ + c0 = ps2FinalColor(c); \ + c1 = i.z; \ +} \ + +#else + +#define DECL_TEXFOGPS(num, bit) \ +void TextureFog##num##bit##PS(VSOUT_TF i, out half4 c0 : COLOR0) \ +{ \ + half4 c = ps2CalcShade(ps2shade##num##bit(i.tex), i.color); \ + c.xyz = lerp(g_fFogColor.xyz, c.xyz, i.fog); \ + c0 = ps2FinalColor(c); \ +} \ + +#endif + +#define DECL_TEXFOGPS_(num) \ +DECL_TEXFOGPS(num, _32) \ +DECL_TEXFOGPS(num, _tex32) \ +DECL_TEXFOGPS(num, _clut32) \ +DECL_TEXFOGPS(num, _tex32to16) \ +DECL_TEXFOGPS(num, _tex16to8h) \ + +DECL_TEXFOGPS_(0) +DECL_TEXFOGPS_(1) +DECL_TEXFOGPS_(2) +DECL_TEXFOGPS_(3) +DECL_TEXFOGPS_(4) +DECL_TEXFOGPS_(5) + +//------------------------------------------------------- +// Techniques not related to the main primitive commands +half4 BilinearBitBlt(float2 tex0) +{ + float4 ftex; + float2 ffrac; + + ffrac.xy = frac(tex0*g_fRealTexDims.xy); + ftex.xy = tex0 - ffrac.xy * g_fRealTexDims.zw; + ftex.zw = ftex.xy + g_fRealTexDims.zw; + + float4 off0, off1; + ps2memcoord4_fast(ftex, off0, off1); + half4 c0 = texRECT(g_sMemory, off0.xy); + half4 c1 = texRECT(g_sMemory, off0.zw); + half4 c2 = texRECT(g_sMemory, off1.xy); + half4 c3 = texRECT(g_sMemory, off1.zw); + + return lerp( lerp(c0, c1, ffrac.x), lerp(c2, c3, ffrac.x), ffrac.y ); +} + +void BitBltVS(in float4 pos : POSITION, + in half4 tex0 : COLOR1, + in float3 tex : TEXCOORD0, + out float4 opos : POSITION, + out float2 otex0 : TEXCOORD0, + out float2 ointerpos : TEXCOORD1) +{ + opos.xy = pos.xy * g_fBitBltPos.xy + g_fBitBltPos.zw; + ointerpos = opos.xy * g_fBitBltTrans.xy + g_fBitBltTrans.zw; + opos.zw = g_fc0.xy; + otex0 = tex.xy * g_fBitBltTex.xy + g_fBitBltTex.zw; +} + +half4 BitBltPS(in float2 tex0 : TEXCOORD0) : COLOR +{ + return texRECT(g_sMemory, ps2memcoord(tex0).xy)*g_fOneColor.xxxy; +} + +// used when AA +half4 BitBltAAPS(in float2 tex0 : TEXCOORD0) : COLOR +{ + return BilinearBitBlt(tex0)*g_fOneColor.xxxy; +} + +void BitBltDepthPS(in float2 tex0 : TEXCOORD0, + out float4 c : COLOR0, + out float depth : DEPTH) +{ + c = texRECT(g_sMemory, ps2memcoord(tex0)); + + depth = (log(g_fc0.y+dot(c, g_fBitBltZ))*g_fOneColor.w) * g_fZMin.y + dot(c, g_fBitBltZ) * g_fZMin.x ; + c += g_fZBias.y; +} + +void BitBltDepthMRTPS(in float2 tex0 : TEXCOORD0, + out half4 c0 : COLOR0, + out float4 c1 : COLOR1, + out float depth : DEPTH) +{ + c1 = texRECT(g_sMemory, ps2memcoord(tex0)); + + depth = (log(g_fc0.y+dot(c1, g_fBitBltZ))*g_fOneColor.w) * g_fZMin.y + dot(c1, g_fBitBltZ) * g_fZMin.x ; + c1 += g_fZBias.y; + c0 = g_fc0.x; +} + +/*static const float BlurKernel[9] = { + 0.027601, + 0.066213, + 0.123701, + 0.179952, + 0.205065, + 0.179952, + 0.123701, + 0.066213, + 0.027601 +};*/ + +half4 BilinearFloat16(float2 tex0) +{ + return texRECT(g_sSrcFinal, tex0.xy); +} + +half4 CRTCTargInterPS(in float2 tex0 : TEXCOORD0, in float2 ointerpos : TEXCOORD1) : COLOR +{ + float finter = texRECT(g_sInterlace, ointerpos.yy).x * g_fOneColor.z + g_fOneColor.w + g_fc0.w; + half4 c = BilinearFloat16(tex0); + c.w = ( g_fc0.w*c.w * g_fOneColor.x + g_fOneColor.y ) * finter; + return c; +} + +half4 CRTCTargPS(in float2 tex0 : TEXCOORD0) : COLOR +{ + float4 c = BilinearFloat16(tex0); + c.w = g_fc0.w*c.w * g_fOneColor.x + g_fOneColor.y; + return c; +} + +half4 CRTCInterPS(in float2 tex0 : TEXCOORD0, in float2 ointerpos : TEXCOORD1) : COLOR +{ + float finter = texRECT(g_sInterlace, ointerpos.yy).x * g_fOneColor.z + g_fOneColor.w + g_fc0.w; + float2 filtcoord = (tex0-frac(tex0))*g_fInvTexDims.xy+g_fInvTexDims.zw; + half4 c = BilinearBitBlt(filtcoord); + c.w = (c.w * g_fOneColor.x + g_fOneColor.y)*finter; + + return c; +} + +// simpler +half4 CRTCInterPS_Nearest(in float2 tex0 : TEXCOORD0, in float2 ointerpos : TEXCOORD1) : COLOR +{ + float finter = texRECT(g_sInterlace, ointerpos.yy).x * g_fOneColor.z + g_fOneColor.w + g_fc0.w; + half4 c = texRECT(g_sMemory, ps2memcoord(tex0).xy); + c.w = (c.w * g_fOneColor.x + g_fOneColor.y)*finter; + return c; +} + +half4 CRTCPS(in float2 tex0 : TEXCOORD0) : COLOR +{ + float2 filtcoord = (tex0/*-frac(tex0)*/)*g_fInvTexDims.xy+g_fInvTexDims.zw; + half4 c = BilinearBitBlt(filtcoord); + c.w = c.w * g_fOneColor.x + g_fOneColor.y; + + return c; +} + +// simpler +half4 CRTCPS_Nearest(in float2 tex0 : TEXCOORD0) : COLOR +{ + half4 c = texRECT(g_sMemory, ps2memcoord(tex0).xy); + c.w = c.w * g_fOneColor.x + g_fOneColor.y; + return c; +} + +half4 CRTC24InterPS(in float2 tex0 : TEXCOORD0, in float2 ointerpos : TEXCOORD1) : COLOR +{ + float finter = texRECT(g_sInterlace, ointerpos.yy).x * g_fOneColor.z + g_fOneColor.w + g_fc0.w; + float2 filtcoord = (tex0-frac(tex0))*g_fInvTexDims.xy+g_fInvTexDims.zw; + + half4 c = texRECT(g_sMemory, ps2memcoord(filtcoord).xy).x; + c.w = (c.w * g_fOneColor.x + g_fOneColor.y)*finter; + + return c; +} + +half4 CRTC24PS(in float2 tex0 : TEXCOORD0) : COLOR +{ + float2 filtcoord = (tex0-frac(tex0))*g_fInvTexDims.xy+g_fInvTexDims.zw; + half4 c = texRECT(g_sMemory, ps2memcoord(filtcoord).xy).x; + c.w = c.w * g_fOneColor.x + g_fOneColor.y; + + return c; +} + +half4 ZeroPS() : COLOR +{ + return g_fOneColor.x; +} + +half4 BaseTexturePS(in float2 tex0 : TEXCOORD0) : COLOR +{ + return texRECT(g_sSrcFinal, tex0) * g_fOneColor; +} + +half4 Convert16to32PS(float2 tex0 : TEXCOORD0) : COLOR +{ + float4 final; + float2 ffrac = fmod(tex0+g_fTexDims.zw, g_fTexOffset.xy); + tex0.xy = g_fTexDims.xy * tex0.xy - ffrac * g_fc0.yw; + + if( ffrac.x > g_fTexOffset.x*g_fc0.w ) + tex0.x += g_fTexOffset.x*g_fc0.w; + if( tex0.x >= g_fc0.y ) tex0 += g_fTexOffset.zw; + + float4 lower = texRECT(g_sSrcFinal, tex0); + float4 upper = texRECT(g_sSrcFinal, tex0+g_fPageOffset.xy); + + final.zy = tex3D(g_sConv32to16, lower.zyx).xy + lower.ww*g_fPageOffset.zw; + final.xw = tex3D(g_sConv32to16, upper.zyx).xy + upper.ww*g_fPageOffset.zw; + + return final; +} + +// use when texture is not tiled and converting from 32bit to 16bit +// don't convert on the block level, only on the column level +// so every other 8 pixels, use the upper bits instead of lower +half4 Convert32to16PS(float2 tex0 : TEXCOORD0) : COLOR +{ + bool upper = false; + float2 ffrac = fmod(tex0+g_fTexDims.zw, g_fTexOffset.xy); + tex0.xy = g_fc0.ww * (tex0.xy + ffrac); + if( ffrac.x > g_fTexOffset.z ) { + tex0.x -= g_fTexOffset.z; + upper = true; + } + if( ffrac.y >= g_fTexOffset.w ) { + tex0.y -= g_fTexOffset.w; + tex0.x += g_fc0.w; + } + + half4 color = texRECT(g_sSrcFinal, tex0*g_fTexDims.xy)*g_fc0.yyyw; + float2 uv = upper ? color.xw : color.zy; + return tex2D(g_sConv16to32, uv*g_fPageOffset.xy+g_fPageOffset.zw)*g_fTexDims.xxxy; +} diff --git a/plugins/zzogl-pg/opengl/rasterfont.cpp b/plugins/zzogl-pg/opengl/rasterfont.cpp new file mode 100644 index 0000000000..243f4e09f6 --- /dev/null +++ b/plugins/zzogl-pg/opengl/rasterfont.cpp @@ -0,0 +1,147 @@ + +#ifdef _WIN32 +#include +#endif + +#include +#include + +#include "rasterfont.h" +// globals + +GLubyte rasters[][13] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36}, + {0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18}, + {0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70}, + {0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e}, + {0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c}, + {0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30}, + {0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03}, + {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e}, + {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06}, + {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60}, + {0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e}, + {0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18}, + {0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e}, + {0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3}, + {0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff}, + {0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c}, + {0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60}, + {0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18}, + {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03}, + {0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e}, + {0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00}, + {0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00}, + {0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78}, + {0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, + {0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00}, + {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f}, + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, + {0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00} +}; + +RasterFont::RasterFont() +{ + // set GL modes + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // create the raster font + fontOffset = glGenLists (128); + for (int i = 32; i < 127; i++) { + glNewList(i+fontOffset, GL_COMPILE); + glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i-32]); + glEndList(); + } +} + +RasterFont::~RasterFont() +{ + glDeleteLists(fontOffset, 128); +} + +void RasterFont::printString(const char *s, double x, double y, double z) +{ + // go to the right spot + glRasterPos3d(x, y, z); + + glPushAttrib (GL_LIST_BIT); + glListBase(fontOffset); + glCallLists(strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s); + glPopAttrib (); +} + +void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z) +{ + int length = strlen(s); + int x = int(screen_width/2.0 - (length/2.0)*char_width); + + printString(s, x, y, z); +} + diff --git a/plugins/zzogl-pg/opengl/rasterfont.h b/plugins/zzogl-pg/opengl/rasterfont.h new file mode 100644 index 0000000000..4a0c39a319 --- /dev/null +++ b/plugins/zzogl-pg/opengl/rasterfont.h @@ -0,0 +1,22 @@ +#ifndef RasterFont_Header +#define RasterFont_Header + +class RasterFont { +protected: + int fontOffset; + +public: + RasterFont(); + ~RasterFont(void); + static int debug; + + // some useful constants + enum {char_width = 10}; + enum {char_height = 15}; + + // and the happy helper functions + void printString(const char *s, double x, double y, double z=0.0); + void printCenteredString(const char *s, double y, int screen_width, double z=0.0); +}; + +#endif diff --git a/plugins/zzogl-pg/opengl/shaders.sh b/plugins/zzogl-pg/opengl/shaders.sh new file mode 100755 index 0000000000..7b6a8d1795 --- /dev/null +++ b/plugins/zzogl-pg/opengl/shaders.sh @@ -0,0 +1,3 @@ +#!/bin/sh +./zgsbuild ps2hw.fx +cp ps2hw.dat ../../../bin/plugins/ diff --git a/plugins/zzogl-pg/opengl/targets.cpp b/plugins/zzogl-pg/opengl/targets.cpp new file mode 100644 index 0000000000..10d53268c8 --- /dev/null +++ b/plugins/zzogl-pg/opengl/targets.cpp @@ -0,0 +1,3415 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GS.h" +#include +#include + +#include + +#include +#include +#include +#include + +#include "Mem.h" +#include "x86.h" +#include "zerogs.h" +#include "targets.h" + +#define RHA +//#define RW + +extern int g_GameSettings; +using namespace ZeroGS; +extern int g_TransferredToGPU; +extern bool g_bIsLost; +extern bool g_bUpdateStencil; +extern u32 s_uFramebuffer; + +#ifdef RELEASE_TO_PUBLIC +# define INC_RESOLVE() +#else +# define INC_RESOLVE() ++g_nResolve +#endif + +static int g_bSaveResolved = 0; +extern int s_nResolved; +extern u32 g_nResolve; +extern bool g_bSaveTrans; + +namespace ZeroGS { + CRenderTargetMngr s_RTs, s_DepthRTs; + CBitwiseTextureMngr s_BitwiseTextures; + CMemoryTargetMngr g_MemTargs; +} + +extern u32 s_ptexCurSet[2]; +extern u32 ptexBilinearBlocks; +extern u32 ptexConv32to16; +BOOL g_bSaveZUpdate = 0; + +// ------------------------- Usefull inlines ------------------------------------ + +// memory size for one row of texture. It's depends of windth of texture and number of bytes +// per pixel +inline u32 Pitch( int fbw ) { return (RW(fbw) * (GetRenderFormat() == RFT_float16 ? 8 : 4)) ; } + +// memory size of whole texture. It is number of rows multiplied by memory size of row +inline u32 Tex_Memory_Size ( int fbw, int fbh ) { return (RH(fbh) * Pitch(fbw)); } + +// Oftenly called for several reasons +// Call flush if renderer or depther target is equal to ptr +inline void FlushIfNecesary ( void* ptr ) { + if( vb[0].prndr == ptr || vb[0].pdepth == ptr ) + Flush(0); + if( vb[1].prndr == ptr || vb[1].pdepth == ptr ) + Flush(1); +} + +// This block was repreaded several times, so I inlined it. +inline void DestroyAllTargetsHelper( void* ptr ) { + for(int i = 0; i < 2; ++i) { + if( ptr == vb[i].prndr ) { vb[i].prndr = NULL; vb[i].bNeedFrameCheck = 1; } + if( ptr == vb[i].pdepth ) { vb[i].pdepth = NULL; vb[i].bNeedZCheck = 1; } + } +} + +// Made an empty rexture and bind it to $ptr_p +// return false if creating texture was uncuccessfull +// fbh and fdb should be properly shifter before calling this!. +// We should ignore framebuffer trouble here, we put textures of dufferent sized to it. +inline bool ZeroGS::CRenderTarget::InitialiseDefaultTexture ( u32 *ptr_p, int fbw, int fbh ) { + glGenTextures(1, ptr_p); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, *ptr_p); + // initialize to default + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GetRenderTargetFormat(), fbw, fbh, 0, GL_RGBA, GetRenderFormat()==RFT_float16?GL_FLOAT:GL_UNSIGNED_BYTE, NULL); + + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + GLenum Error = glGetError(); + return ((Error == GL_NO_ERROR) || (Error == GL_INVALID_FRAMEBUFFER_OPERATION_EXT)); +} + +// Draw 4 triangles from binded array using only stenclil buffer +inline void FillOnlyStencilBuffer() { + if( ZeroGS::IsWriteDestAlphaTest() && !(g_GameSettings&GAME_NOSTENCIL)) { + glColorMask(0,0,0,0); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GEQUAL, 1.0f); + + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 1, 0xff); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glColorMask(1,1,1,1); + } +} + +// used for transformation from vertex position in GS window.coords (I hope) +// to view coordinates (in range 0, 1). +inline Vector ZeroGS::CRenderTarget::DefaultBitBltPos() { + Vector v = Vector (1, -1, 0.5f/(float)RW(fbw), 0.5f/(float)RH(fbh) ); + v *= 1.0f/32767.0f; + ZZcgSetParameter4fv(pvsBitBlt.sBitBltPos, v, "g_sBitBltPos"); + return v ; +} + +// Used to transform texture coordinates from GS (when 0,0 is upper left) to +// OpenGL (0,0 - lower left). +inline Vector ZeroGS::CRenderTarget::DefaultBitBltTex() { + // I really sure that -0.5 is correct, because OpenGL have no half-offset + // issue, DirectX known for. + Vector v = Vector (1, -1, 0.5f/(float)RW(fbw), -0.5f/(float)RH(fbh) ); + ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, v, "g_sBitBltTex"); + return v ; +} + +inline void BindToSample ( u32 *p_ptr ) { + glBindTexture(GL_TEXTURE_RECTANGLE_NV, *p_ptr); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +} + +//////////////////// +// Render Targets // +//////////////////// +ZeroGS::CRenderTarget::CRenderTarget() : ptex(0), ptexFeedback(0), psys(NULL) +{ + FUNCLOG + nUpdateTarg = 0; +} + +ZeroGS::CRenderTarget::~CRenderTarget() +{ + FUNCLOG + Destroy(); +} + +bool ZeroGS::CRenderTarget::Create(const frameInfo& frame) +{ + FUNCLOG + Resolve(); + Destroy(); + created = 123; + + lastused = timeGetTime(); + fbp = frame.fbp; + fbw = frame.fbw; + fbh = frame.fbh; + psm = (u8)frame.psm; + fbm = frame.fbm; + + vposxy.x = 2.0f * (1.0f / 8.0f) / (float)fbw; + vposxy.y = 2.0f * (1.0f / 8.0f) / (float)fbh; + vposxy.z = -1-0.5f/(float)fbw; + vposxy.w = -1+0.5f/(float)fbh; + status = 0; + + if( fbw > 0 && fbh > 0 ) { + GetRectMemAddress(start, end, psm, 0, 0, fbw, fbh, fbp, fbw); + psys = _aligned_malloc( Tex_Memory_Size ( fbw, fbh ), 16 ); + + GL_REPORT_ERRORD(); + + if ( !InitialiseDefaultTexture( &ptex, RW(fbw), RH(fbh) )) { + Destroy(); + return false; + } + + status = TS_NeedUpdate; + } + else { + start = end = 0; + } + + return true; +} + +void ZeroGS::CRenderTarget::Destroy() +{ + FUNCLOG + created = 1; + _aligned_free(psys); psys = NULL; + SAFE_RELEASE_TEX(ptex); + SAFE_RELEASE_TEX(ptexFeedback); +} + +void ZeroGS::CRenderTarget::SetTarget(int fbplocal, const Rect2& scissor, int context) +{ + FUNCLOG + int dy = 0; + + if( fbplocal != fbp ) { + Vector v; + + // will be rendering to a subregion + u32 bpp = PSMT_ISHALF(psm) ? 2 : 4; + assert( ((256/bpp)*(fbplocal-fbp)) % fbw == 0 ); + assert( fbplocal >= fbp ); + + dy = ((256/bpp)*(fbplocal-fbp)) / fbw; + + v.x = vposxy.x; + v.y = vposxy.y; + v.z = vposxy.z; + v.w = vposxy.w - dy*2.0f/(float)fbh; + ZZcgSetParameter4fv(g_vparamPosXY[context], v, "g_fPosXY"); + } + else + ZZcgSetParameter4fv(g_vparamPosXY[context], vposxy, "g_fPosXY"); + + // set render states + scissorrect.x = scissor.x0>>3; + scissorrect.y = (scissor.y0>>3) + dy; + scissorrect.w = (scissor.x1>>3)+1; + scissorrect.h = (scissor.y1>>3)+1+dy; + scissorrect.w = min(scissorrect.w, fbw) - scissorrect.x; + scissorrect.h = min(scissorrect.h, fbh) - scissorrect.y; + + scissorrect.x = RW(scissorrect.x); + scissorrect.y = RH(scissorrect.y); + scissorrect.w = RW(scissorrect.w); + scissorrect.h = RH(scissorrect.h); +} + +void ZeroGS::CRenderTarget::SetViewport() +{ + FUNCLOG + glViewport(0, 0, RW(fbw), RH(fbh)); +} + +inline bool NotResolveHelper() { + return ((s_nResolved > 8 && (2 * s_nResolved > fFPS - 10)) || (g_GameSettings&GAME_NOTARGETRESOLVE)); +} + +void ZeroGS::CRenderTarget::Resolve() +{ + FUNCLOG + + if( ptex != 0 && !(status&TS_Resolved) && !(status&TS_NeedUpdate) ) { + + // flush if necessary + FlushIfNecesary ( this ) ; + + if ((IsDepth() && !ZeroGS::IsWriteDepth()) || NotResolveHelper()) { + // don't resolve if depths aren't used + status = TS_Resolved; + return; + } + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex); + GL_REPORT_ERRORD(); + // This code extremely slow on DC1. +// _aligned_free(psys); +// psys = _aligned_malloc( Tex_Memory_Size ( fbw, fbh ), 16 ); + + glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, psys); + + GL_REPORT_ERRORD(); + +#if !defined(RELEASE_TO_PUBLIC) && defined(_DEBUG) + if( g_bSaveResolved ) { + SaveTexture("resolved.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh)); + g_bSaveResolved = 0; + } +#endif + _Resolve(psys, fbp, fbw, fbh, psm, fbm, true); + status = TS_Resolved; + } +} + +void ZeroGS::CRenderTarget::Resolve(int startrange, int endrange) +{ + FUNCLOG + + assert( startrange < end && endrange > start ); // make sure it at least intersects + + if( ptex != 0 && !(status&TS_Resolved) && !(status&TS_NeedUpdate) ) { + + // flush if necessary + FlushIfNecesary ( this ) ; + +#if !defined(RELEASE_TO_PUBLIC) && defined(_DEBUG) + if( g_bSaveResolved ) { + SaveTexture("resolved.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh)); + g_bSaveResolved = 0; + } +#endif + + if(g_GameSettings&GAME_NOTARGETRESOLVE) { + status = TS_Resolved; + return; + } + + int blockheight = PSMT_ISHALF(psm) ? 64 : 32; + int resolvefbp = fbp, resolveheight = fbh; + + int scanlinewidth = 0x2000*(fbw>>6); + + // in now way should data be overwritten!, instead resolve less + if( endrange < end ) { + // round down to nearest block and scanline + resolveheight = ((endrange-start)/(0x2000*(fbw>>6))) * blockheight; + if( resolveheight <= 32 ) { + status = TS_Resolved; + return; + } + } + else if( startrange > start ) { + // round up to nearest block and scanline + resolvefbp = startrange + scanlinewidth - 1; + resolvefbp -= resolvefbp % scanlinewidth; + + resolveheight = fbh-((resolvefbp-fbp)*blockheight/scanlinewidth); + if( resolveheight <= 64 ) { // this is a total hack, but kh doesn't resolve now + status = TS_Resolved; + return; + } + + resolvefbp >>= 8; + } + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex); + glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, psys); + GL_REPORT_ERRORD(); + + u8* pbits = (u8*)psys; + if( fbp != resolvefbp ) + pbits += ((resolvefbp-fbp)*256/scanlinewidth)*blockheight*Pitch( fbw ); + + _Resolve(pbits, resolvefbp, fbw, resolveheight, psm, fbm, true); + status = TS_Resolved; + } +} + +void ZeroGS::CRenderTarget::Update(int context, ZeroGS::CRenderTarget* pdepth) +{ + FUNCLOG + + DisableAllgl(); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + // assume depth already set + //pd3dDevice->SetDepthStencilSurface(psurfDepth); + ResetRenderTarget(1); + SetRenderTarget(0); + assert( pdepth != NULL ); + ((CDepthTarget*)pdepth)->SetDepthStencilSurface(); + + SetShaderCaller("CRenderTarget::Update"); + Vector v = DefaultBitBltPos(); + + CRenderTargetMngr::MAPTARGETS::iterator ittarg; + if( nUpdateTarg ) { + ittarg = s_RTs.mapTargets.find(nUpdateTarg); + if( ittarg == s_RTs.mapTargets.end() ) { + ittarg = s_DepthRTs.mapTargets.find(nUpdateTarg); + if( ittarg == s_DepthRTs.mapTargets.end() ) + nUpdateTarg = 0; + else if( ittarg->second == this ) { + ERROR_LOG("updating self"); + nUpdateTarg = 0; + } + } + else if( ittarg->second == this ) { + ERROR_LOG("updating self"); + nUpdateTarg = 0; + } + } + + SetViewport(); + + if( nUpdateTarg ) { + + cgGLSetTextureParameter(ppsBaseTexture.sFinal, ittarg->second->ptex); + cgGLEnableTextureParameter(ppsBaseTexture.sFinal); + + //assert( ittarg->second->fbw == fbw ); + int offset = (fbp-ittarg->second->fbp)*64/fbw; + if (PSMT_ISHALF(psm)) // 16 bit + offset *= 2; + + v.x = (float)RW(fbw); + v.y = (float)RH(fbh); + v.z = 0.25f; + v.w = (float)RH(offset) + 0.25f; + ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, v, "g_fBitBltTex"); +// v = DefaultBitBltTex(); Maybe? + v = DefaultOneColor ( ppsBaseTexture ) ; + + SETPIXELSHADER(ppsBaseTexture.prog); + nUpdateTarg = 0; + } + else { + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + tex0Info texframe; + texframe.tbp0 = fbp; + texframe.tbw = fbw; + texframe.tw = fbw; + texframe.th = fbh; + texframe.psm = psm; + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(texframe, 1); + + // write color and zero out stencil buf, always 0 context! + // force bilinear if using AA + // Fix in r133 -- FFX movies and Gust backgrounds! + SetTexVariablesInt(0, 0*(s_AAx || s_AAy)?2:0, texframe, pmemtarg, &ppsBitBlt[!!s_AAx], 1); + cgGLSetTextureParameter(ppsBitBlt[!!s_AAx].sMemory, pmemtarg->ptex->tex); + cgGLEnableTextureParameter(ppsBitBlt[!!s_AAx].sMemory); + + v = Vector(1,1,0.0f,0.0f); + ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, v, "g_fBitBltTex"); + + v.x = 1; + v.y = 2; + ZZcgSetParameter4fv(ppsBitBlt[!!s_AAx].sOneColor, v, "g_fOneColor"); + + assert( ptex != 0 ); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + if( ZeroGS::IsWriteDestAlphaTest() ) { + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 0, 0xff); + glStencilMask(0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); + } + + // render with an AA shader if possible (bilinearly interpolates data) + //cgGLLoadProgram(ppsBitBlt[!!s_AAx].prog); + SETPIXELSHADER(ppsBitBlt[!!s_AAx].prog); + } + + SETVERTEXSHADER(pvsBitBlt.prog); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + // fill stencil buf only + FillOnlyStencilBuffer(); + glEnable(GL_SCISSOR_TEST); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + if( conf.mrtdepth && pdepth != NULL && ZeroGS::IsWriteDepth() ) + pdepth->SetRenderTarget(1); + + status = TS_Resolved; + + // reset since settings changed + vb[0].bVarsTexSync = 0; + ZeroGS::ResetAlphaVariables(); +} + +void ZeroGS::CRenderTarget::ConvertTo32() +{ + FUNCLOG + + u32 ptexConv; +// ERROR_LOG("ZZogl: Convert to 32, report if something missing\n"); + // create new target + if ( ! InitialiseDefaultTexture ( &ptexConv, RW(fbw), RH(fbh)/2 ) ) { + ERROR_LOG("Failed to create target for ConvertTo32 %dx%d\n", RW(fbw), RH(fbh)/2); + return; + } + + DisableAllgl(); + SetShaderCaller("CRenderTarget::ConvertTo32"); + + // tex coords, test ffx bikanel island when changing these + Vector v = DefaultBitBltPos(); + v = DefaultBitBltTex(); + + v.x = (float)RW(16); + v.y = (float)RH(16); + v.z = -(float)RW(fbw); + v.w = (float)RH(8); + ZZcgSetParameter4fv(ppsConvert16to32.fTexOffset, v, "g_fTexOffset"); + + v.x = (float)RW(8); + v.y = 0; + v.z = 0; + v.w = 0.25f; + ZZcgSetParameter4fv(ppsConvert16to32.fPageOffset, v, "g_fPageOffset"); + + v.x = (float)RW(2 * fbw); + v.y = (float)RH(fbh); + v.z = 0; + v.w = 0.0001f * (float)RH(fbh); + ZZcgSetParameter4fv(ppsConvert16to32.fTexDims, v, "g_fTexDims"); + +// v.x = 0; +// ZZcgSetParameter4fv(ppsConvert16to32.fTexBlock, v, "g_fTexBlock"); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + // assume depth already set !? + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, ptexConv, 0 ); + ZeroGS::ResetRenderTarget(1); + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); + + BindToSample( &ptex ) ; + + cgGLSetTextureParameter(ppsConvert16to32.sFinal, ptex); + cgGLEnableTextureParameter(ppsBitBlt[!!s_AAx].sMemory); + + fbh /= 2; // have 16 bit surfaces are usually 2x higher + SetViewport(); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + // render with an AA shader if possible (bilinearly interpolates data) + SETVERTEXSHADER(pvsBitBlt.prog); + SETPIXELSHADER(ppsConvert16to32.prog); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + +#ifdef _DEBUG + if( g_bSaveZUpdate ) { + // buggy + SaveTexture("tex1.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh)*2); + SaveTexture("tex3.tga", GL_TEXTURE_RECTANGLE_NV, ptexConv, RW(fbw), RH(fbh)); + } +#endif + + vposxy.y = -2.0f * (32767.0f / 8.0f) / (float)fbh; + vposxy.w = 1+0.5f/fbh; + + // restore + SAFE_RELEASE_TEX(ptex); + SAFE_RELEASE_TEX(ptexFeedback); + ptex = ptexConv; + + // no need to free psys since the render target is getting shrunk + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + // reset textures + BindToSample ( &ptex ) ; + + glEnable(GL_SCISSOR_TEST); + status = TS_Resolved; + + // TODO, reset depth? + if( ZeroGS::icurctx >= 0 ) { + // reset since settings changed + vb[icurctx].bVarsTexSync = 0; + vb[icurctx].bVarsSetTarg = 0; + } + vb[0].bVarsTexSync = 0; +} + +void ZeroGS::CRenderTarget::ConvertTo16() +{ + FUNCLOG + + u32 ptexConv; + +// ERROR_LOG("ZZogl: Convert to 16, report if something missing\n"); + // create new target + if ( ! InitialiseDefaultTexture ( &ptexConv, RW(fbw), RH(fbh)*2 ) ) { + ERROR_LOG("Failed to create target for ConvertTo16 %dx%d\n", RW(fbw), RH(fbh)*2); + return; + } + + DisableAllgl(); + SetShaderCaller("CRenderTarget::ConvertTo16"); + + // tex coords, test ffx bikanel island when changing these + Vector v = DefaultBitBltPos(); + v = DefaultBitBltTex(); + + v.x = 16.0f / (float)fbw; + v.y = 8.0f / (float)fbh; + v.z = 0.5f * v.x; + v.w = 0.5f * v.y; + ZZcgSetParameter4fv(ppsConvert32to16.fTexOffset, v, "g_fTexOffset"); + + v.x = 256.0f / 255.0f; + v.y = 256.0f / 255.0f; + v.z = 0.05f / 256.0f; + v.w = -0.001f / 256.0f; + ZZcgSetParameter4fv(ppsConvert32to16.fPageOffset, v, "g_fPageOffset"); + + v.x = (float)RW(fbw); + v.y = (float)RH(2 * fbh); + v.z = 0; + v.w = -0.1f/RH(fbh); + ZZcgSetParameter4fv(ppsConvert32to16.fTexDims, v, "g_fTexDims"); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + // assume depth already set !? + // assume depth already set !? + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, ptexConv, 0 ); + ZeroGS::ResetRenderTarget(1); + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); + + BindToSample ( &ptex ) ; + + cgGLSetTextureParameter(ppsConvert32to16.sFinal, ptex); + cgGLEnableTextureParameter(ppsConvert32to16.sFinal); + +// fbh *= 2; // have 16 bit surfaces are usually 2x higher + + SetViewport(); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + // render with an AA shader if possible (bilinearly interpolates data) + SETVERTEXSHADER(pvsBitBlt.prog); + SETPIXELSHADER(ppsConvert32to16.prog); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + +#ifdef _DEBUG + //g_bSaveZUpdate = 1; + if( g_bSaveZUpdate ) { + SaveTexture("tex1.tga", GL_TEXTURE_RECTANGLE_NV, ptexConv, RW(fbw), RH(fbh)); + } +#endif + + vposxy.y = -2.0f * (32767.0f / 8.0f) / (float)fbh; + vposxy.w = 1+0.5f/fbh; + + // restore + SAFE_RELEASE_TEX(ptex); + SAFE_RELEASE_TEX(ptexFeedback); + ptex = ptexConv; + + _aligned_free(psys); + psys = _aligned_malloc( Tex_Memory_Size ( fbw, fbh ), 16 ); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + // reset textures + BindToSample ( &ptex ) ; + glEnable(GL_SCISSOR_TEST); + + status = TS_Resolved; + + // TODO, reset depth? + if( ZeroGS::icurctx >= 0 ) { + // reset since settings changed + vb[icurctx].bVarsTexSync = 0; + vb[icurctx].bVarsSetTarg = 0; + } + vb[0].bVarsTexSync = 0; +} + +void ZeroGS::CRenderTarget::_CreateFeedback() +{ + FUNCLOG + + if( ptexFeedback == 0 ) { + // create + if ( ! InitialiseDefaultTexture( &ptexFeedback, RW(fbw), RH(fbh) ) ) { + ERROR_LOG("Failed to create feedback %dx%d\n", RW(fbw), RH(fbh)); + return; + } + } + + DisableAllgl(); + SetShaderCaller("CRenderTarget::_CreateFeedback"); + + // assume depth already set + ResetRenderTarget(1); + + // tex coords, test ffx bikanel island when changing these +/* Vector v = DefaultBitBltPos(); + v = Vector ((float)(RW(fbw+4)), (float)(RH(fbh+4)), +0.25f, -0.25f); + ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, v, "BitBltTex");*/ + + // tex coords, test ffx bikanel island when changing these + +// Vector v = Vector(1, -1, 0.5f / (fbw<= 0 ) { + // reset since settings changed + vb[icurctx].bVarsTexSync = 0; + } + + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); +} + +void ZeroGS::CRenderTarget::SetRenderTarget(int targ) +{ + FUNCLOG + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+targ, GL_TEXTURE_RECTANGLE_NV, ptex, 0 ); + +// if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) +// ERROR_LOG_SPAM("Too bad Framebuffer not compele, glitches could appear onscreen!\n"); +} + +ZeroGS::CDepthTarget::CDepthTarget() : CRenderTarget(), pdepth(0), pstencil(0), icount(0) {} + +ZeroGS::CDepthTarget::~CDepthTarget() +{ + FUNCLOG + + Destroy(); +} + +bool ZeroGS::CDepthTarget::Create(const frameInfo& frame) +{ + FUNCLOG + + if( !CRenderTarget::Create(frame) ) + return false; + + GL_REPORT_ERROR(); + + glGenRenderbuffersEXT( 1, &pdepth ); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pdepth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, RW(fbw), RH(fbh)); + + if (glGetError() != GL_NO_ERROR) { + // try a separate depth and stencil buffer + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pdepth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, RW(fbw), RH(fbh)); + + if (g_bUpdateStencil) { + glGenRenderbuffersEXT( 1, &pstencil ); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pstencil); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, RW(fbw), RH(fbh)); + + if( glGetError() != GL_NO_ERROR ) { + ERROR_LOG("failed to create depth buffer %dx%d\n", RW(fbw), RH(fbh)); + return false; + } + } + else pstencil = 0; + } + else + pstencil = pdepth; + + status = TS_NeedUpdate; + + return true; +} + +void ZeroGS::CDepthTarget::Destroy() +{ + FUNCLOG + + if ( status ) { // In this case Framebuffer extension is off-use and lead to segfault + ResetRenderTarget(1); + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0 ); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0 ); + GL_REPORT_ERRORD(); + + if( pstencil != 0 ) { + if( pstencil != pdepth ) + glDeleteRenderbuffersEXT( 1, &pstencil ); + pstencil = 0; + } + + if( pdepth != 0 ) { + glDeleteRenderbuffersEXT( 1, &pdepth ); + pdepth = 0; + } + GL_REPORT_ERRORD(); + } + + CRenderTarget::Destroy(); +} + + +extern int g_nDepthUsed; // > 0 if depth is used + +void ZeroGS::CDepthTarget::Resolve() +{ + FUNCLOG + + if( g_nDepthUsed > 0 && conf.mrtdepth && !(status&TS_Virtual) && ZeroGS::IsWriteDepth() && !(g_GameSettings&GAME_NODEPTHRESOLVE) ) + CRenderTarget::Resolve(); + else { + // flush if necessary + FlushIfNecesary ( this ) ; + if( !(status & TS_Virtual) ) + status |= TS_Resolved; + } + + if( !(status&TS_Virtual) ) { + ZeroGS::SetWriteDepth(); + } +} + +void ZeroGS::CDepthTarget::Resolve(int startrange, int endrange) +{ + FUNCLOG + + if( g_nDepthUsed > 0 && conf.mrtdepth && !(status&TS_Virtual) && ZeroGS::IsWriteDepth() ) + CRenderTarget::Resolve(startrange, endrange); + else { + // flush if necessary + FlushIfNecesary ( this ) ; + if( !(status & TS_Virtual) ) + status |= TS_Resolved; + } + + if( !(status&TS_Virtual) ) { + ZeroGS::SetWriteDepth(); + } +} + +extern int g_nDepthUpdateCount; + +void ZeroGS::CDepthTarget::Update(int context, ZeroGS::CRenderTarget* prndr) +{ + FUNCLOG + + assert( !(status & TS_Virtual) ); + + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + tex0Info texframe; + texframe.tbp0 = fbp; + texframe.tbw = fbw; + texframe.tw = fbw; + texframe.th = fbh; + texframe.psm = psm; + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(texframe, 1); + + DisableAllgl () ; + + ZeroGS::VB& curvb = vb[context]; + if (curvb.test.zte == 0) + return; + + SetShaderCaller("CDepthTarget::Update"); + glEnable(GL_DEPTH_TEST); + glDepthMask(!curvb.zbuf.zmsk); + + static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER }; + glDepthFunc(g_dwZCmp[curvb.test.ztst]); + + // write color and zero out stencil buf, always 0 context! + SetTexVariablesInt(0, 0, texframe, pmemtarg, &ppsBitBltDepth, 1); + cgGLSetTextureParameter(ppsBitBltDepth.sMemory, pmemtarg->ptex->tex); + cgGLEnableTextureParameter(ppsBaseTexture.sFinal); + + Vector v = DefaultBitBltPos() ; + v = DefaultBitBltTex() ; + + v.x = 1; + v.y = 2; + v.z = PSMT_IS16Z(psm)?1.0f:0.0f; + v.w = g_filog32; + ZZcgSetParameter4fv(ppsBitBltDepth.sOneColor, v, "g_fOneColor"); + + Vector vdepth = g_vdepth; + if (psm == PSMT24Z) + vdepth.w = 0; + else if (psm != PSMT32Z) { + vdepth.z = vdepth.w = 0; + } + + assert( ppsBitBltDepth.sBitBltZ != 0 ); + ZZcgSetParameter4fv(ppsBitBltDepth.sBitBltZ, ((255.0f/256.0f)*vdepth), "g_fBitBltZ"); + + assert( pdepth != 0 ); + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, ptex, 0 ); + SetDepthStencilSurface(); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, 0, 0 ); + GLenum buffer = GL_COLOR_ATTACHMENT0_EXT; + if( glDrawBuffers != NULL ) + glDrawBuffers(1, &buffer); + int stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); + + SetViewport(); + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + SETVERTEXSHADER(pvsBitBlt.prog); + SETPIXELSHADER(ppsBitBltDepth.prog); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + status = TS_Resolved; + + if( !ZeroGS::IsWriteDepth() ) { + ResetRenderTarget(1); + } + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glEnable(GL_SCISSOR_TEST); + +#ifdef _DEBUG + if( g_bSaveZUpdate ) { + SaveTex(&texframe, 1); + SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh)); + } +#endif +} + +void ZeroGS::CDepthTarget::SetDepthStencilSurface() +{ + FUNCLOG + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, pdepth ); + + if( pstencil ) { + // there's a bug with attaching stencil and depth buffers + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, pstencil ); + + if( icount++ < 8 ) { // not going to fail if succeeded 4 times + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) { + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0 ); + if( pstencil != pdepth ) + glDeleteRenderbuffersEXT(1, &pstencil); + pstencil = 0; + g_bUpdateStencil = 0; + } + } + } + else + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0 ); +} + +void ZeroGS::CRenderTargetMngr::Destroy() +{ + FUNCLOG + for(MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) + delete it->second; + mapTargets.clear(); + for(MAPTARGETS::iterator it = mapDummyTargs.begin(); it != mapDummyTargs.end(); ++it) + delete it->second; + mapDummyTargs.clear(); +} + +void ZeroGS::CRenderTargetMngr::DestroyAllTargs(int start, int end, int fbw) +{ + FUNCLOG + for(MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end();) { + if( it->second->start < end && start < it->second->end ) { + // if is depth, only resolve if fbw is the same + if( !it->second->IsDepth() ) { + // only resolve if the widths are the same or it->second has bit outside the range + // shadow of colossus swaps between fbw=256,fbh=256 and fbw=512,fbh=448. This kills the game if doing || it->second->end > end + + // kh hack, sometimes kh movies do this to clear the target, so have a static count that periodically checks end + static int count = 0; + + if( it->second->fbw == fbw || (it->second->fbw != fbw && (it->second->start < start || ((count++&0xf)?0:it->second->end > end) )) ) + it->second->Resolve(); + else { + FlushIfNecesary ( it->second ) ; + it->second->status |= CRenderTarget::TS_Resolved; + } + } + else { + if( it->second->fbw == fbw ) + it->second->Resolve(); + else { + FlushIfNecesary ( it->second ) ; + it->second->status |= CRenderTarget::TS_Resolved; + } + } + + DestroyAllTargetsHelper( it->second ) ; + + u32 dummykey = GetFrameKeyDummy(it->second); + if( mapDummyTargs.find(dummykey) == mapDummyTargs.end() ) { + mapDummyTargs[dummykey] = it->second; + } + else + delete it->second; + mapTargets.erase(it++); + } + else ++it; + } +} + +void ZeroGS::CRenderTargetMngr::DestroyTarg(CRenderTarget* ptarg) +{ + FUNCLOG + DestroyAllTargetsHelper ( ptarg ) ; + delete ptarg; +} + +void ZeroGS::CRenderTargetMngr::DestroyIntersecting(CRenderTarget* prndr) +{ + FUNCLOG + assert( prndr != NULL ); + + int start, end; + GetRectMemAddress(start, end, prndr->psm, 0, 0, prndr->fbw, prndr->fbh, prndr->fbp, prndr->fbw); + + for(MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end();) { + if( it->second != prndr && it->second->start < end && start < it->second->end ) { + it->second->Resolve(); + + DestroyAllTargetsHelper( it->second ) ; + + u32 dummykey = GetFrameKeyDummy(it->second); + if( mapDummyTargs.find(dummykey) == mapDummyTargs.end() ) { + mapDummyTargs[dummykey] = it->second; + } + else + delete it->second; + mapTargets.erase(it++); + } + else ++it; + } +} + +//-------------------------------------------------- + + +inline bool CheckWidthIsSame (const frameInfo& frame, CRenderTarget* ptarg) { + if (PSMT_ISHALF(frame.psm) == PSMT_ISHALF(ptarg->psm)) + return (frame.fbw == ptarg->fbw); + if (PSMT_ISHALF(frame.psm)) + return (frame.fbw == 2 * ptarg->fbw); + else + return (2 * frame.fbw == ptarg->fbw); +} + +CRenderTarget* ZeroGS::CRenderTargetMngr::GetTarg(const frameInfo& frame, u32 opts, int maxposheight) +{ + FUNCLOG + if( frame.fbw <= 0 || frame.fbh <= 0 ) + return NULL; + + GL_REPORT_ERRORD(); + + u32 key = GetFrameKey(frame); + MAPTARGETS::iterator it = mapTargets.find(key); + + // only enforce height if frame.fbh <= 0x1c0 + bool bfound = it != mapTargets.end(); + if( bfound ) { + if( opts&TO_StrictHeight ) { + bfound = it->second->fbh == frame.fbh; + + if( (g_GameSettings&GAME_PARTIALDEPTH) && !bfound ) { + MAPTARGETS::iterator itnew = mapTargets.find(key+1); + if( itnew != mapTargets.end() && itnew->second->fbh == frame.fbh ) { + // found! delete the previous and restore + delete it->second; + mapTargets.erase(it); + + it = mapTargets.insert(MAPTARGETS::value_type(key, itnew->second)).first; // readd + mapTargets.erase(itnew); // delete old + + bfound = true; + } + } + } + else { + if( PSMT_ISHALF(frame.psm)==PSMT_ISHALF(it->second->psm) && !(g_GameSettings & GAME_FULL16BITRES) ) + bfound = (frame.fbh > 0x1c0 || it->second->fbh >= frame.fbh) && it->second->fbh <= maxposheight; + } + } + + if( !bfound ) { + // might be a virtual target + it = mapTargets.find(key|TARGET_VIRTUAL_KEY); + bfound = it != mapTargets.end() && ((opts&TO_StrictHeight) ? it->second->fbh == frame.fbh : it->second->fbh >= frame.fbh) && it->second->fbh <= maxposheight; + } + + if( bfound && PSMT_ISHALF(frame.psm) && PSMT_ISHALF(it->second->psm) && (g_GameSettings&GAME_FULL16BITRES) ) { + // mgs3 + if( frame.fbh > it->second->fbh ) { + bfound = false; + } + } + + if( bfound ) { + + // can be both 16bit and 32bit + if( PSMT_ISHALF(frame.psm) != PSMT_ISHALF(it->second->psm) ) { + // a lot of games do this actually... +#ifdef _DEBUG + WARN_LOG("Really bad formats! %d %d\n", frame.psm, it->second->psm); +#endif + +// This code SHOULD be commented, until I redone _Resolve function + if( !(opts&TO_StrictHeight) ) { + if( (g_GameSettings & GAME_VSSHACKOFF) ) { + if (PSMT_ISHALF(it->second->psm)) { + it->second->status |= CRenderTarget::TS_NeedConvert32; + it->second->fbh /= 2; + } + else { + it->second->status |= CRenderTarget::TS_NeedConvert16; + it->second->fbh *= 2; + } + } + } + + // recalc extents + GetRectMemAddress(it->second->start, it->second->end, frame.psm, 0, 0, frame.fbw, it->second->fbh, it->second->fbp, frame.fbw); + } + else { + // certain variables have to be reset every time + if( (it->second->psm&~1) != (frame.psm&~1) ) { +#ifndef RELEASE_TO_PUBLIC + WARN_LOG("bad formats 2: %d %d\n", frame.psm, it->second->psm); +#endif + it->second->psm = frame.psm; + + // recalc extents + GetRectMemAddress(it->second->start, it->second->end, frame.psm, 0, 0, frame.fbw, it->second->fbh, it->second->fbp, frame.fbw); + } + } + + if( it->second->fbm != frame.fbm ) { + //WARN_LOG("bad fbm: 0x%8.8x 0x%8.8x, psm: %d\n", frame.fbm, it->second->fbm, frame.psm); + } + + it->second->fbm &= frame.fbm; + it->second->psm = frame.psm; // have to convert (ffx2) + + if( (it->first & TARGET_VIRTUAL_KEY) && !(opts&TO_Virtual) ) { + // switch + it->second->lastused = timeGetTime(); + return Promote(it->first&~TARGET_VIRTUAL_KEY); + } + + // check if there exists a more recent target that this target could update from + // only update if target isn't mirrored + bool bCheckHalfCovering = (g_GameSettings&GAME_FULL16BITRES) && PSMT_ISHALF(it->second->psm) && it->second->fbh +32 < frame.fbh; + + for(MAPTARGETS::iterator itnew = mapTargets.begin(); itnew != mapTargets.end(); ++itnew) { + if( itnew->second != it->second && itnew->second->ptex != it->second->ptex && itnew->second->ptexFeedback != it->second->ptex && + itnew->second->lastused > it->second->lastused && !(itnew->second->status & CRenderTarget::TS_NeedUpdate) ) { + + // if new target totally encompasses the current one + if( itnew->second->start <= it->second->start && itnew->second->end >= it->second->end ) { + it->second->status |= CRenderTarget::TS_NeedUpdate; + it->second->nUpdateTarg = itnew->first; + break; + } + + // if 16bit, then check for half encompassing targets + if( bCheckHalfCovering && itnew->second->start > it->second->start && itnew->second->start < it->second->end && itnew->second->end <= it->second->end+0x2000 ) { + it->second->status |= CRenderTarget::TS_NeedUpdate; + it->second->nUpdateTarg = itnew->first; + break; + } + } + } + + it->second->lastused = timeGetTime(); + + return it->second; + } + + // NOTE: instead of resolving, if current render targ is completely outside of old, can transfer + // the data like that. + + // first search for the target + CRenderTarget* ptarg = NULL; + + // have to change, so recreate (find all intersecting targets and Resolve) + u32 besttarg = 0; + + if( !(opts & CRenderTargetMngr::TO_Virtual) ) { + + int start, end; + GetRectMemAddress(start, end, frame.psm, 0, 0, frame.fbw, frame.fbh, frame.fbp, frame.fbw); + CRenderTarget* pbesttarg = NULL; + + + if( besttarg == 0 ) { + // if there is only one intersecting target and it encompasses the current one, update the new render target with + // its data instead of resolving then updating (ffx2). Do not change the original target. + for(MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) { + if( it->second->start < end && start < it->second->end ) { + if((g_GameSettings&GAME_FASTUPDATE) || + (frame.fbw == it->second->fbw) + && + // check depth targets only if partialdepth option + ((it->second->fbp != frame.fbp) || ((g_GameSettings&GAME_PARTIALDEPTH)&&(opts&CRenderTargetMngr::TO_DepthBuffer)))) + + { + if( besttarg != 0 ) { + besttarg = 0; + break; + } + + if( start >= it->second->start && end <= it->second->end ) { + besttarg = it->first; + pbesttarg = it->second; + } + } + } + } + } + + if (besttarg != 0 && pbesttarg->fbw != frame.fbw) { +// printf ("A %d %d %d %d\n", frame.psm, frame.fbw, pbesttarg->psm, pbesttarg->fbw); + + vb[0].frame.fbw = pbesttarg->fbw; + // Something should be here, but what? + } + + if( besttarg == 0 ) { + // if none found, resolve all + DestroyAllTargs(start, end, frame.fbw); + } + else if( key == besttarg && pbesttarg != NULL ) { + // add one and store in a different location until best targ is processed + mapTargets.erase(besttarg); + besttarg++; + mapTargets[besttarg] = pbesttarg; + } + } + + if( mapTargets.size() > 8 ) { + // release some resources + it = GetOldestTarg(mapTargets); + + // if more than 5s passed since target used, destroy + if( it->second != vb[0].prndr && it->second != vb[1].prndr && it->second != vb[0].pdepth && it->second != vb[1].pdepth && + timeGetTime()-it->second->lastused > 5000 ) { + delete it->second; + mapTargets.erase(it); + } + } + + if( ptarg == NULL ) { + // not found yet, so create + + if( mapDummyTargs.size() > 8 ) { + it = GetOldestTarg(mapDummyTargs); + + delete it->second; + mapDummyTargs.erase(it); + } + + it = mapDummyTargs.find(GetFrameKeyDummy(frame)); + + if (it != mapDummyTargs.end()) { +#ifdef DEBUG + printf ("A %x %x %x %x\n", frame.fbw, frame.fbh, frame.psm, frame.fbp); + for(MAPTARGETS::iterator it1 = mapDummyTargs.begin(); it1 != mapDummyTargs.end(); ++it1) + printf ("\t %x %x %x %x\n", it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp); + for(MAPTARGETS::iterator it1 = mapTargets.begin(); it1 != mapTargets.end(); ++it1) + printf ("\t ! %x %x %x %x\n", it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp); + printf ("\t\t %x %x %x %x\n", it->second->fbw, it->second->fbh, it->second->psm, it->second->fbp); +#endif + ptarg = it->second; + mapDummyTargs.erase(it); + + // restore all setttings + ptarg->psm = frame.psm; + ptarg->fbm = frame.fbm; + ptarg->fbp = frame.fbp; + GetRectMemAddress(ptarg->start, ptarg->end, frame.psm, 0, 0, frame.fbw, frame.fbh, frame.fbp, frame.fbw); + + ptarg->status = CRenderTarget::TS_NeedUpdate; + } + else { +#ifdef DEBUG + printf ("A %x %x %x %x\n", frame.fbw, frame.fbh, frame.psm, frame.fbp); + for(MAPTARGETS::iterator it1 = mapDummyTargs.begin(); it1 != mapDummyTargs.end(); ++it1) + printf ("\t %x %x %x %x\n", it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp); + for(MAPTARGETS::iterator it1 = mapTargets.begin(); it1 != mapTargets.end(); ++it1) + printf ("\t ! %x %x %x %x\n", it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp); +#endif + // create anew + ptarg = (opts&TO_DepthBuffer) ? new CDepthTarget : new CRenderTarget; + CRenderTargetMngr* pmngrs[2] = { &s_DepthRTs, this == &s_RTs ? &s_RTs : NULL }; + int cur = 0; + + while( !ptarg->Create(frame) ) { + + // destroy unused targets + if( mapDummyTargs.size() > 0 ) { + it = mapDummyTargs.begin(); + delete it->second; + mapDummyTargs.erase(it); + continue; + } + + if( g_MemTargs.listClearedTargets.size() > 0 ) { + g_MemTargs.DestroyCleared(); + continue; + } + else + if( g_MemTargs.listTargets.size() > 32 ) { + g_MemTargs.DestroyOldest(); + continue; + } + + if( pmngrs[cur] == NULL ) { + cur = !cur; + if( pmngrs[cur] == NULL ) { + WARN_LOG("Out of memory!\n"); + delete ptarg; + return NULL; + } + } + + if( pmngrs[cur]->mapTargets.size() == 0 ) + { + pmngrs[cur] = NULL; + cur = !cur; + continue; + } + + it = GetOldestTarg(pmngrs[cur]->mapTargets); + + DestroyTarg(it->second); + pmngrs[cur]->mapTargets.erase(it); + cur = !cur; + } + } + } + + if( (opts & CRenderTargetMngr::TO_Virtual) ) { + ptarg->status = CRenderTarget::TS_Virtual; + key |= TARGET_VIRTUAL_KEY; + + if( (it = mapTargets.find(key)) != mapTargets.end() ) { + + DestroyTarg(it->second); + it->second = ptarg; + ptarg->nUpdateTarg = besttarg; + return ptarg; + } + } + else + assert( mapTargets.find(key) == mapTargets.end()); + + ptarg->nUpdateTarg = besttarg; + mapTargets[key] = ptarg; + return ptarg; +} + +ZeroGS::CRenderTargetMngr::MAPTARGETS::iterator ZeroGS::CRenderTargetMngr::GetOldestTarg(MAPTARGETS& m) +{ + FUNCLOG + if( m.size() == 0 ) { + return m.end(); + } + + // release some resources + u32 curtime = timeGetTime(); + MAPTARGETS::iterator itmaxtarg = m.begin(); + for(MAPTARGETS::iterator it = ++m.begin(); it != m.end(); ++it) { + if( itmaxtarg->second->lastused-curtime < it->second->lastused-curtime ) itmaxtarg = it; + } + + return itmaxtarg; +} + +void ZeroGS::CRenderTargetMngr::GetTargs(int start, int end, list& listTargets) const +{ + FUNCLOG + for(MAPTARGETS::const_iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) { + if( it->second->start < end && start < it->second->end ) listTargets.push_back(it->second); + } +} + +void ZeroGS::CRenderTargetMngr::Resolve(int start, int end) +{ + FUNCLOG + for(MAPTARGETS::const_iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) { + if( it->second->start < end && start < it->second->end ) + it->second->Resolve(); + } +} + +void ZeroGS::CMemoryTargetMngr::Destroy() +{ + FUNCLOG + listTargets.clear(); + listClearedTargets.clear(); +} + +int memcmp_clut16(u16* pSavedBuffer, u16* pClutBuffer, int clutsize) +{ + FUNCLOG + assert( (clutsize&31) == 0 ); + + // left > 0 only when csa < 16 + int left = ((u32)(uptr)pClutBuffer & 2) ? 0 : (((u32)(uptr)pClutBuffer & 0x3ff)/2) + clutsize - 512; + if( left > 0 ) clutsize -= left; + + while(clutsize > 0) { + for(int i = 0; i < 16; ++i) { + if( pSavedBuffer[i] != pClutBuffer[2*i] ) + return 1; + } + + clutsize -= 32; + pSavedBuffer += 16; + pClutBuffer += 32; + } + + if( left > 0 ) { + pClutBuffer = (u16*)(g_pbyGSClut + 2); + + while(left > 0) { + for(int i = 0; i < 16; ++i) { + if( pSavedBuffer[i] != pClutBuffer[2*i] ) + return 1; + } + + left -= 32; + pSavedBuffer += 16; + pClutBuffer += 32; + } + } + + return 0; +} + +bool ZeroGS::CMemoryTarget::ValidateClut(const tex0Info& tex0) +{ + FUNCLOG + assert( tex0.psm == psm && PSMT_ISCLUT(psm) && cpsm == tex0.cpsm ); + + int nClutOffset = 0; + int clutsize = 0; + + int entries = PSMT_IS8CLUT(tex0.psm) ? 256 : 16; + if( tex0.cpsm <= 1 ) { // 32 bit + nClutOffset = 64 * tex0.csa; + clutsize = min(entries, 256-tex0.csa*16)*4; + } + else { + nClutOffset = 32 * (tex0.csa&15) + (tex0.csa>=16?2:0); + clutsize = min(entries, 512-tex0.csa*16)*2; + } + + assert( clutsize == clut.size() ); + + if( cpsm <= 1 ) { + if( memcmp_mmx(&clut[0], g_pbyGSClut+nClutOffset, clutsize) ) + return false; + } + else { + if( memcmp_clut16((u16*)&clut[0], (u16*)(g_pbyGSClut+nClutOffset), clutsize) ) + return false; + } + + return true; +} + +int VALIDATE_THRESH = 8; +u32 TEXDESTROY_THRESH = 16; + +bool ZeroGS::CMemoryTarget::ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex) +{ + FUNCLOG + if( clearmaxy == 0 ) + return true; + + int checkstarty = max(starttex, clearminy); + int checkendy = min(endtex, clearmaxy); + if( checkstarty >= checkendy ) + return true; + + if( validatecount++ > VALIDATE_THRESH ) { + height = 0; + return false; + } + + // lock and compare + assert( ptex != NULL && ptex->memptr != NULL); + + int result = memcmp_mmx(ptex->memptr + (checkstarty-realy)*4*GPU_TEXWIDTH, g_pbyGSMemory+checkstarty*4*GPU_TEXWIDTH, (checkendy-checkstarty)*4*GPU_TEXWIDTH); + + if( result == 0 || !bDeleteBadTex ) { + if( result == 0 ) clearmaxy = 0; + return result == 0; + } + + // delete clearminy, clearmaxy range (not the checkstarty, checkendy range) + int newstarty = 0; + if( clearminy <= starty ) { + if( clearmaxy < starty + height) { + // preserve end + height = starty+height-clearmaxy; + starty = clearmaxy; + assert(height > 0); + } + else { + // destroy + height = 0; + } + } + else { + // beginning can be preserved + height = clearminy-starty; + } + + clearmaxy = 0; + assert( starty >= realy && starty+height<=realy+realheight ); + + return false; +} + +// used to build clut textures (note that this is for both 16 and 32 bit cluts) +#define BUILDCLUT() { \ + switch(tex0.psm) { \ + case PSMT8: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH/2; ++j) { \ + pdst[0] = pclut[psrc[0]]; \ + pdst[1] = pclut[psrc[1]]; \ + pdst[2] = pclut[psrc[2]]; \ + pdst[3] = pclut[psrc[3]]; \ + pdst[4] = pclut[psrc[4]]; \ + pdst[5] = pclut[psrc[5]]; \ + pdst[6] = pclut[psrc[6]]; \ + pdst[7] = pclut[psrc[7]]; \ + pdst += 8; \ + psrc += 8; \ + } \ + } \ + break; \ + case PSMT4: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH; ++j) { \ + pdst[0] = pclut[psrc[0]&15]; \ + pdst[1] = pclut[psrc[0]>>4]; \ + pdst[2] = pclut[psrc[1]&15]; \ + pdst[3] = pclut[psrc[1]>>4]; \ + pdst[4] = pclut[psrc[2]&15]; \ + pdst[5] = pclut[psrc[2]>>4]; \ + pdst[6] = pclut[psrc[3]&15]; \ + pdst[7] = pclut[psrc[3]>>4]; \ + \ + pdst += 8; \ + psrc += 4; \ + } \ + } \ + break; \ + case PSMT8H: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH/8; ++j) { \ + pdst[0] = pclut[psrc[3]]; \ + pdst[1] = pclut[psrc[7]]; \ + pdst[2] = pclut[psrc[11]]; \ + pdst[3] = pclut[psrc[15]]; \ + pdst[4] = pclut[psrc[19]]; \ + pdst[5] = pclut[psrc[23]]; \ + pdst[6] = pclut[psrc[27]]; \ + pdst[7] = pclut[psrc[31]]; \ + pdst += 8; \ + psrc += 32; \ + } \ + } \ + break; \ + case PSMT4HH: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH/8; ++j) { \ + pdst[0] = pclut[psrc[3]>>4]; \ + pdst[1] = pclut[psrc[7]>>4]; \ + pdst[2] = pclut[psrc[11]>>4]; \ + pdst[3] = pclut[psrc[15]>>4]; \ + pdst[4] = pclut[psrc[19]>>4]; \ + pdst[5] = pclut[psrc[23]>>4]; \ + pdst[6] = pclut[psrc[27]>>4]; \ + pdst[7] = pclut[psrc[31]>>4]; \ + pdst += 8; \ + psrc += 32; \ + } \ + } \ + break; \ + case PSMT4HL: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH/8; ++j) { \ + pdst[0] = pclut[psrc[3]&15]; \ + pdst[1] = pclut[psrc[7]&15]; \ + pdst[2] = pclut[psrc[11]&15]; \ + pdst[3] = pclut[psrc[15]&15]; \ + pdst[4] = pclut[psrc[19]&15]; \ + pdst[5] = pclut[psrc[23]&15]; \ + pdst[6] = pclut[psrc[27]&15]; \ + pdst[7] = pclut[psrc[31]&15]; \ + pdst += 8; \ + psrc += 32; \ + } \ + } \ + break; \ + default: \ + assert(0); \ + } \ +} \ + +#define TARGET_THRESH 0x500 + +extern int g_MaxTexWidth, g_MaxTexHeight; + +//#define SORT_TARGETS +inline list::iterator ZeroGS::CMemoryTargetMngr::DestroyTargetIter(list::iterator& it) +{ + // find the target and destroy + list::iterator itprev = it; ++it; + listClearedTargets.splice(listClearedTargets.end(), listTargets, itprev); + + if( listClearedTargets.size() > TEXDESTROY_THRESH ) { + listClearedTargets.pop_front(); + } + + return it; +} + +#if defined(_MSC_VER) && defined(__x86_64__) +extern "C" void UnswizzleZ16Target(void* dst, void* src, int iters); +#endif + +int MemoryTarget_CompareTarget (list::iterator& it, const tex0Info& tex0, int clutsize, int nClutOffset) { + if( PSMT_ISCLUT(it->psm) != PSMT_ISCLUT(tex0.psm) ) { + return 1; + } + + if( PSMT_ISCLUT(tex0.psm) ) { + assert( it->clut.size() > 0 ); + + if( it->psm != tex0.psm || it->cpsm != tex0.cpsm || it->clut.size() != clutsize ) { + return 1; + } + + if( tex0.cpsm <= 1 ) { + if (memcmp_mmx(&it->clut[0], g_pbyGSClut+nClutOffset, clutsize)) { + return 2; + } + } + else { + if (memcmp_clut16((u16*)&it->clut[0], (u16*)(g_pbyGSClut+nClutOffset), clutsize)) { + return 2; + } + } + + } + else + if ( PSMT_IS16BIT(tex0.psm) != PSMT_IS16BIT(it->psm) ) { + return 1; + } + return 0; +} + +void MemoryTarget_GetClutVariables (int& nClutOffset, int& clutsize, const tex0Info& tex0) { + nClutOffset = 0; + clutsize = 0; + + if( PSMT_ISCLUT(tex0.psm) ) { + int entries = PSMT_IS8CLUT(tex0.psm) ? 256 : 16; + if( tex0.cpsm <= 1 ) { + nClutOffset = 64 * tex0.csa; + clutsize = min(entries, 256-tex0.csa*16)*4; + } + else { + nClutOffset = 64 * (tex0.csa&15) + (tex0.csa>=16?2:0); + clutsize = min(entries, 512-tex0.csa*16)*2; + } + } +} + +void MemoryTarget_GetMemAddress(int& start, int& end, const tex0Info& tex0) { + int nbStart, nbEnd; + GetRectMemAddress(nbStart, nbEnd, tex0.psm, 0, 0, tex0.tw, tex0.th, tex0.tbp0, tex0.tbw); + assert( nbStart < nbEnd ); + nbEnd = min(nbEnd, 0x00400000); + + start = nbStart / (4*GPU_TEXWIDTH); + end = (nbEnd + GPU_TEXWIDTH*4 - 1) / (4*GPU_TEXWIDTH); + assert( start < end ); + +} + +ZeroGS::CMemoryTarget* ZeroGS::CMemoryTargetMngr::MemoryTarget_SearchExistTarget (int start, int end, int nClutOffset, int clutsize, const tex0Info& tex0, int forcevalidate) { + for(list::iterator it = listTargets.begin(); it != listTargets.end(); ) { + + if( it->starty <= start && it->starty+it->height >= end ) { + + int res = MemoryTarget_CompareTarget (it, tex0, clutsize, nClutOffset); + + if (res == 1) { + if( it->validatecount++ > VALIDATE_THRESH ) { + it = DestroyTargetIter(it); + if( listTargets.size() == 0 ) + break; + } + else + ++it; + continue; + } + else if (res == 2) { + ++it; + continue; + } + + if( forcevalidate ) {//&& listTargets.size() < TARGET_THRESH ) { + // do more validation checking. delete if not been used for a while + if( !it->ValidateTex(tex0, start, end, curstamp > it->usedstamp + 3) ) { + + if( it->height <= 0 ) { + it = DestroyTargetIter(it); + if( listTargets.size() == 0 ) + break; + } + else + ++it; + continue; + } + } + + it->usedstamp = curstamp; + it->validatecount = 0; + + return &(*it); + } +#ifdef SORT_TARGETS + else if( it->starty >= end ) + break; +#endif + + ++it; + } + return NULL; +} + + +ZeroGS::CMemoryTarget* ZeroGS::CMemoryTargetMngr::MemoryTarget_ClearedTargetsSearch(int fmt, int widthmult, int channels, int height) { + CMemoryTarget* targ = NULL; + + if( listClearedTargets.size() > 0 ) { + + list::iterator itbest = listClearedTargets.begin(); + while(itbest != listClearedTargets.end()) { + + if( height <= itbest->realheight && itbest->fmt == fmt && itbest->widthmult == widthmult && itbest->channels == channels ) { + // check channels + int targchannels = 1; + if( PSMT_ISCLUT(itbest->psm) ) { + if( itbest->psm == PSMT8 ) targchannels = 4; + else if( itbest->psm == PSMT4 ) targchannels = 8; + } + else if( PSMT_IS16BIT(itbest->psm) ) { + targchannels = 2; + } + if( targchannels == channels ) + break; + } + ++itbest; + } + + if( itbest != listClearedTargets.end()) { + listTargets.splice(listTargets.end(), listClearedTargets, itbest); + targ = &listTargets.back(); + targ->validatecount = 0; + } + else { + // create a new + listTargets.push_back(CMemoryTarget()); + targ = &listTargets.back(); + } + } + else { + listTargets.push_back(CMemoryTarget()); + targ = &listTargets.back(); + } + return targ; +} + +ZeroGS::CMemoryTarget* ZeroGS::CMemoryTargetMngr::GetMemoryTarget(const tex0Info& tex0, int forcevalidate) +{ + FUNCLOG + int start, end, nClutOffset, clutsize; + + MemoryTarget_GetClutVariables (nClutOffset, clutsize, tex0); + MemoryTarget_GetMemAddress(start, end, tex0); + + ZeroGS::CMemoryTarget* it = MemoryTarget_SearchExistTarget (start, end, nClutOffset, clutsize, tex0, forcevalidate); + if (it != NULL) return it; + + // couldn't find so create + CMemoryTarget* targ; + + u32 fmt = GL_UNSIGNED_BYTE; +// if ((PSMT_ISCLUT(tex0.psm) && tex0.cpsm > 1) || tex0.psm == PSMCT16 || tex0.psm == PSMCT16S) { + if (PSMT_ISHALF_STORAGE(tex0)) { + fmt = GL_UNSIGNED_SHORT_1_5_5_5_REV; + } + + int widthmult = 1; + if ((g_MaxTexHeight < 4096) && (end-start > g_MaxTexHeight)) + widthmult = 2; + + int channels = 1; + if( PSMT_ISCLUT(tex0.psm) ) { + if( tex0.psm == PSMT8 ) channels = 4; + else if( tex0.psm == PSMT4 ) channels = 8; + } + else { + if( PSMT_IS16BIT(tex0.psm) ) { + // 16z needs to be a8r8g8b8 + channels = 2; + } + } + + targ = MemoryTarget_ClearedTargetsSearch(fmt, widthmult, channels, end - start) ; + + // fill local clut + if( PSMT_ISCLUT(tex0.psm) ) { + assert( clutsize > 0 ); + targ->cpsm = tex0.cpsm; + targ->clut.reserve(256*4); // no matter what + targ->clut.resize(clutsize); + + if( tex0.cpsm <= 1 ) { // 32 bit + memcpy_amd(&targ->clut[0], g_pbyGSClut+nClutOffset, clutsize); + } + else { + u16* pClutBuffer = (u16*)(g_pbyGSClut + nClutOffset); + u16* pclut = (u16*)&targ->clut[0]; + int left = ((u32)nClutOffset & 2) ? 0 : ((nClutOffset&0x3ff)/2)+clutsize-512; + if( left > 0 ) clutsize -= left; + + while(clutsize > 0) { + pclut[0] = pClutBuffer[0]; + pclut++; + pClutBuffer+=2; + clutsize -= 2; + } + + if( left > 0) { + pClutBuffer = (u16*)(g_pbyGSClut + 2); + while(left > 0) { + pclut[0] = pClutBuffer[0]; + left -= 2; + pClutBuffer += 2; + pclut++; + } + } + } + } + + if( targ->ptex != NULL ) { + + assert( end-start <= targ->realheight && targ->fmt == fmt && targ->widthmult == widthmult ); + // good enough, so init + targ->realy = targ->starty = start; + targ->usedstamp = curstamp; + targ->psm = tex0.psm; + targ->cpsm = tex0.cpsm; + targ->height = end-start; + } + + if( targ->ptex == NULL ) { + + // not initialized yet + targ->fmt = fmt; + targ->realy = targ->starty = start; + targ->realheight = targ->height = end-start; + targ->usedstamp = curstamp; + targ->psm = tex0.psm; + targ->cpsm = tex0.cpsm; + targ->widthmult = widthmult; + targ->channels = channels; + + // alloc the mem + targ->ptex = new CMemoryTarget::TEXTURE(); + targ->ptex->ref = 1; + } + +#ifndef RELEASE_TO_PUBLIC + g_TransferredToGPU += GPU_TEXWIDTH * channels * 4 * targ->height; +#endif + + // fill with data + if( targ->ptex->memptr == NULL ) { + targ->ptex->memptr = (u8*)_aligned_malloc(4 * GPU_TEXWIDTH * targ->realheight, 16); + assert(targ->ptex->ref > 0 ); + } + + memcpy_amd(targ->ptex->memptr, g_pbyGSMemory + 4 * GPU_TEXWIDTH * targ->realy, 4 * GPU_TEXWIDTH * targ->height); + vector texdata; + u8* ptexdata = NULL; + + if( PSMT_ISCLUT(tex0.psm) ) { + + texdata.resize( (tex0.cpsm <= 1?4:2) *GPU_TEXWIDTH*channels*widthmult*(targ->realheight+widthmult-1)/widthmult); + ptexdata = &texdata[0]; + + u8* psrc = (u8*)(g_pbyGSMemory + 4 * GPU_TEXWIDTH * targ->realy); + + if( tex0.cpsm <= 1 ) { // 32bit + u32* pclut = (u32*)&targ->clut[0]; + u32* pdst = (u32*)ptexdata; + + BUILDCLUT(); + } + else { + u16* pclut = (u16*)&targ->clut[0]; + u16* pdst = (u16*)ptexdata; + + BUILDCLUT(); + } + } + else { + if( tex0.psm == PSMT16Z || tex0.psm == PSMT16SZ ) { + + texdata.resize(4*GPU_TEXWIDTH*channels*widthmult*(targ->realheight+widthmult-1)/widthmult +#if defined(ZEROGS_SSE2) + + 15 // reserve additional elements for alignment if SSE2 used. + // better do it now, so less resizing would be needed +#endif + ); + + ptexdata = &texdata[0]; + // needs to be 8 bit, use xmm for unpacking + u16* dst = (u16*)ptexdata; + u16* src = (u16*)(g_pbyGSMemory + 4 * GPU_TEXWIDTH * targ->realy); + +#if defined(ZEROGS_SSE2) + if ( ((u32)(uptr)dst)%16 != 0 ) { + // This is not unusual situation, when vector does not 16bit alignment, that is destructive for SSE2 + // instruction movdqa [%eax], xmm0 + // The idea would be resise vector to 15 elements, that set ptxedata to aligned position. + // Later we would move eax by 16, so only we should verify is first element align + // FIXME. As I see, texdata used only once here, it does not have any impact on other code. + // Probably, usage of _aligned_maloc() would be preferable. + int disalignment = 16 - ((u32)(uptr)dst)%16 ; // This is value of shift. It could be 0 < disalignment <= 15 + ptexdata = &texdata[disalignment]; // Set pointer to aligned element + dst = (u16*)ptexdata; + GS_LOG("Made alignment for texdata, 0x%x\n", dst ); + assert( ((u32)(uptr)dst)%16 == 0 ); // Assert, because at future could be vectors with uncontigious spaces + } + + int iters = targ->height*GPU_TEXWIDTH/16; + SSE2_UnswizzleZ16Target( dst, src, iters ) ; +#else // ZEROGS_SSE2 + for(int i = 0; i < targ->height; ++i) { + for(int j = 0; j < GPU_TEXWIDTH; ++j) { + dst[0] = src[0]; dst[1] = 0; + dst[2] = src[1]; dst[3] = 0; + dst += 4; + src += 2; + } + } +#endif // ZEROGS_SSE2 + } + else { + ptexdata = targ->ptex->memptr; + } + } + + // create the texture + GL_REPORT_ERRORD(); + assert(ptexdata != NULL); + if( targ->ptex->tex == 0 ) + glGenTextures(1, &targ->ptex->tex); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, targ->ptex->tex); + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, fmt==GL_UNSIGNED_BYTE?4:GL_RGB5_A1, GPU_TEXWIDTH*channels*widthmult, + (targ->realheight+widthmult-1)/widthmult, 0, GL_RGBA, fmt, ptexdata); + + int realheight = targ->realheight; + while( glGetError() != GL_NO_ERROR ) { + + // release resources until can create + if( listClearedTargets.size() > 0 ) + listClearedTargets.pop_front(); + else { + if( listTargets.size() == 0 ) { + ERROR_LOG("Failed to create %dx%x texture\n", GPU_TEXWIDTH*channels*widthmult, (realheight+widthmult-1)/widthmult); + channels = 1; + return NULL; + } + DestroyOldest(); + } + + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, GPU_TEXWIDTH*channels*widthmult, (targ->realheight+widthmult-1)/widthmult, 0, GL_RGBA, fmt, ptexdata); + } + + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); + + assert( tex0.psm != 0xd ); + if( PSMT_ISCLUT(tex0.psm) ) + assert( targ->clut.size() > 0 ); + + return targ; +} + +void ZeroGS::CMemoryTargetMngr::ClearRange(int nbStartY, int nbEndY) +{ + FUNCLOG + int starty = nbStartY / (4*GPU_TEXWIDTH); + int endy = (nbEndY+4*GPU_TEXWIDTH-1) / (4*GPU_TEXWIDTH); + //int endy = (nbEndY+4096-1) / 4096; + + //if( listTargets.size() < TARGET_THRESH ) { + for(list::iterator it = listTargets.begin(); it != listTargets.end(); ) { + + if( it->starty < endy && (it->starty+it->height) > starty ) { + + // intersects, reduce valid texture mem (or totally delete texture) + // there are 4 cases + int miny = max(it->starty, starty); + int maxy = min(it->starty+it->height, endy); + assert(miny < maxy); + + if( it->clearmaxy == 0 ) { + it->clearminy = miny; + it->clearmaxy = maxy; + } + else { + if( it->clearminy > miny ) it->clearminy = miny; + if( it->clearmaxy < maxy ) it->clearmaxy = maxy; + } + } + + ++it; + } +// } +// else { +// for(list::iterator it = listTargets.begin(); it != listTargets.end(); ) { +// +// if( it->starty < endy && (it->starty+it->height) > starty ) { +// int newstarty = 0; +// if( starty <= it->starty ) { +// if( endy < it->starty + it->height) { +// // preserve end +// it->height = it->starty+it->height-endy; +// it->starty = endy; +// assert(it->height > 0); +// } +// else { +// // destroy +// it->height = 0; +// } +// } +// else { +// // beginning can be preserved +// it->height = starty-it->starty; +// } +// +// assert( it->starty >= it->realy && it->starty+it->height<=it->realy+it->realheight ); +// if( it->height <= 0 ) { +// list::iterator itprev = it; ++it; +// listClearedTargets.splice(listClearedTargets.end(), listTargets, itprev); +// continue; +// } +// } +// +// ++it; +// } +// } +} + +void ZeroGS::CMemoryTargetMngr::DestroyCleared() +{ + FUNCLOG + for(list::iterator it = listClearedTargets.begin(); it != listClearedTargets.end(); ) { + if( it->usedstamp < curstamp - 2 ) { + it = listClearedTargets.erase(it); + continue; + } + + ++it; + } + + if( (curstamp % 3) == 0 ) { + // purge old targets every 3 frames + for(list::iterator it = listTargets.begin(); it != listTargets.end(); ) { + if( it->usedstamp < curstamp - 3 ) { + it = listTargets.erase(it); + continue; + } + + ++it; + } + } + + ++curstamp; +} + +void ZeroGS::CMemoryTargetMngr::DestroyOldest() +{ + FUNCLOG + if( listTargets.size() == 0 ) + return; + + list::iterator it, itbest; + it = itbest = listTargets.begin(); + + while(it != listTargets.end()) { + if( it->usedstamp < itbest->usedstamp ) + itbest = it; + ++it; + } + + listTargets.erase(itbest); +} + +////////////////////////////////////// +// Texture Mngr For Bitwise AND Ops // +////////////////////////////////////// +void ZeroGS::CBitwiseTextureMngr::Destroy() +{ + FUNCLOG + for(map::iterator it = mapTextures.begin(); it != mapTextures.end(); ++it) + glDeleteTextures(1, &it->second); + mapTextures.clear(); +} + +u32 ZeroGS::CBitwiseTextureMngr::GetTexInt(u32 bitvalue, u32 ptexDoNotDelete) +{ + FUNCLOG + if( mapTextures.size() > 32 ) { + // randomly delete 8 + for(map::iterator it = mapTextures.begin(); it != mapTextures.end();) { + if( !(rand()&3) && it->second != ptexDoNotDelete) { + glDeleteTextures(1, &it->second); + mapTextures.erase(it++); + } + else ++it; + } + } + + if (glGetError() != GL_NO_ERROR ) + ERROR_LOG ("Error before creation of bitmask texture\n"); + + // create a new tex + u32 ptex; + glGenTextures(1, &ptex); + + if (glGetError() != GL_NO_ERROR ) + ERROR_LOG ("Error on generation of bitmask texture\n"); + + vector data(GPU_TEXMASKWIDTH+1); + for(u32 i = 0; i < GPU_TEXMASKWIDTH; ++i) + data[i] = (((i << MASKDIVISOR) & bitvalue)<<6); // add the 1/2 offset so that + data[GPU_TEXMASKWIDTH] = 0; + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex); + + if (glGetError() != GL_NO_ERROR ) + ERROR_LOG ("Error on binding bitmask texture\n"); + + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_LUMINANCE16, GPU_TEXMASKWIDTH+1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, &data[0]); + + if (glGetError() != GL_NO_ERROR ) + ERROR_LOG ("Error on puting bitmask texture\n"); + + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_REPEAT); + + GLint Error = glGetError(); + if( Error != GL_NO_ERROR ) { + ERROR_LOG_SPAM_TEST("Failed to create bitmask texture; \t"); + if (SPAM_PASS) { + ERROR_LOG("bitmask cache %d; \t", mapTextures.size()); + switch (Error) { + case GL_INVALID_ENUM: ERROR_LOG("Invalid enumerator\n") ; break; + case GL_INVALID_VALUE: ERROR_LOG("Invalid value\n"); break; + case GL_INVALID_OPERATION: ERROR_LOG("Invalid operation\n"); break; + default: ERROR_LOG("Error number: %d \n", Error); + } + } + return 0; + } + + mapTextures[bitvalue] = ptex; + return ptex; +} + +void ZeroGS::CRangeManager::Insert(int start, int end) +{ + FUNCLOG + int imin = 0, imax = (int)ranges.size(), imid; + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + + switch( ranges.size() ) { + case 0: + ranges.push_back(RANGE(start, end)); + return; + + case 1: + if( end < ranges.front().start ) { + ranges.insert(ranges.begin(), RANGE(start, end)); + } + else if( start > ranges.front().end ) { + ranges.push_back(RANGE(start, end)); + } + else { + if( start < ranges.front().start ) ranges.front().start = start; + if( end > ranges.front().end ) ranges.front().end = end; + } + + return; + } + + // find where start is + while(imin < imax) { + imid = (imin+imax)>>1; + + assert( imid < (int)ranges.size() ); + + if( ranges[imid].end >= start && (imid == 0 || ranges[imid-1].end < start) ) { + imin = imid; + break; + } + else if( ranges[imid].start > start ) imax = imid; + else imin = imid+1; + } + + int startindex = imin; + + if( startindex >= (int)ranges.size() ) { + // non intersecting + assert( start > ranges.back().end ); + ranges.push_back(RANGE(start, end)); + return; + } + if( startindex == 0 && end < ranges.front().start ) { + ranges.insert(ranges.begin(), RANGE(start, end)); + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + return; + } + + imin = 0; imax = (int)ranges.size(); + + // find where end is + while(imin < imax) { + imid = (imin+imax)>>1; + + assert( imid < (int)ranges.size() ); + + if( ranges[imid].end <= end && (imid == ranges.size()-1 || ranges[imid+1].start > end ) ) { + imin = imid; + break; + } + else if( ranges[imid].start >= end ) imax = imid; + else imin = imid+1; + } + + int endindex = imin; + + if( startindex > endindex ) { + // create a new range + ranges.insert(ranges.begin()+startindex, RANGE(start, end)); + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + return; + } + + if( endindex >= (int)ranges.size()-1 ) { + // pop until startindex is reached + int lastend = ranges.back().end; + int numpop = (int)ranges.size() - startindex - 1; + while(numpop-- > 0 ) ranges.pop_back(); + + assert( start <= ranges.back().end ); + if( start < ranges.back().start ) ranges.back().start = start; + if( lastend > ranges.back().end ) ranges.back().end = lastend; + if( end > ranges.back().end ) ranges.back().end = end; + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + + return; + } + + if( endindex == 0 ) { + assert( end >= ranges.front().start ); + if( start < ranges.front().start ) ranges.front().start = start; + if( end > ranges.front().end ) ranges.front().end = end; + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + } + + // somewhere in the middle + if( ranges[startindex].start < start ) start = ranges[startindex].start; + + if( startindex < endindex ) { + ranges.erase(ranges.begin() + startindex, ranges.begin() + endindex ); + } + + if( start < ranges[startindex].start ) ranges[startindex].start = start; + if( end > ranges[startindex].end ) ranges[startindex].end = end; + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif +} + +namespace ZeroGS { + +CRangeManager s_RangeMngr; // manages overwritten memory +static int gs_imageEnd = 0; + +void ResolveInRange(int start, int end) +{ + FUNCLOG + list listTargs = CreateTargetsList(start, end); +/* s_DepthRTs.GetTargs(start, end, listTargs); + s_RTs.GetTargs(start, end, listTargs);*/ + if( listTargs.size() > 0 ) { + Flush(0); + Flush(1); + + // We need another list, because old one could be brocken by Flush(). + listTargs.clear(); + listTargs = CreateTargetsList(start, end); +/* s_DepthRTs.GetTargs(start, end, listTargs_1); + s_RTs.GetTargs(start, end, listTargs_1);*/ + + for(list::iterator it = listTargs.begin(); it != listTargs.end(); ++it) { + // only resolve if not completely covered + if ((*it)->created == 123 ) + (*it)->Resolve(); + else + ERROR_LOG("Resolving non-existing object! Destroy code %d\n", (*it)->created); + } + } +} + +////////////////// +// Transferring // +////////////////// +void FlushTransferRanges(const tex0Info* ptex) +{ + FUNCLOG + assert( s_RangeMngr.ranges.size() > 0 ); + bool bHasFlushed = false; + list listTransmissionUpdateTargs; + + int texstart = -1, texend = -1; + if( ptex != NULL ) { + GetRectMemAddress(texstart, texend, ptex->psm, 0, 0, ptex->tw, ptex->th, ptex->tbp0, ptex->tbw); + } + + for(vector::iterator itrange = s_RangeMngr.ranges.begin(); itrange != s_RangeMngr.ranges.end(); ++itrange ) { + + int start = itrange->start; + int end = itrange->end; + + listTransmissionUpdateTargs.clear(); + listTransmissionUpdateTargs = CreateTargetsList(start, end); + +/* s_DepthRTs.GetTargs(start, end, listTransmissionUpdateTargs); + s_RTs.GetTargs(start, end, listTransmissionUpdateTargs);*/ + +// if( !bHasFlushed && listTransmissionUpdateTargs.size() > 0 ) { +// Flush(0); +// Flush(1); +// +//#ifdef _DEBUG +// // make sure targets are still the same +// list::iterator it; +// FORIT(it, listTransmissionUpdateTargs) { +// CRenderTargetMngr::MAPTARGETS::iterator itmap; +// for(itmap = s_RTs.mapTargets.begin(); itmap != s_RTs.mapTargets.end(); ++itmap) { +// if( itmap->second == *it ) +// break; +// } +// +// if( itmap == s_RTs.mapTargets.end() ) { +// +// for(itmap = s_DepthRTs.mapTargets.begin(); itmap != s_DepthRTs.mapTargets.end(); ++itmap) { +// if( itmap->second == *it ) +// break; +// } +// +// assert( itmap != s_DepthRTs.mapTargets.end() ); +// } +// } +//#endif +// } + + for(list::iterator it = listTransmissionUpdateTargs.begin(); it != listTransmissionUpdateTargs.end(); ++it) { + + CRenderTarget* ptarg = *it; + + if( (ptarg->status & CRenderTarget::TS_Virtual) ) + continue; + + if( !(ptarg->start < texend && ptarg->end > texstart) ) { + // chekc if target is currently being used + + if( !(g_GameSettings & GAME_NOQUICKRESOLVE) ) { + if( ptarg->fbp != vb[0].gsfb.fbp ) {//&& (vb[0].prndr == NULL || ptarg->fbp != vb[0].prndr->fbp) ) { + + if( ptarg->fbp != vb[1].gsfb.fbp ) { //&& (vb[1].prndr == NULL || ptarg->fbp != vb[1].prndr->fbp) ) { + // this render target currently isn't used and is not in the texture's way, so can safely ignore + // resolving it. Also the range has to be big enough compared to the target to really call it resolved + // (ffx changing screens, shadowhearts) + // start == ptarg->start, used for kh to transfer text + if( ptarg->IsDepth() || end-start > 0x50000 || ((g_GameSettings&GAME_QUICKRESOLVE1)&&start == ptarg->start) ) + ptarg->status |= CRenderTarget::TS_NeedUpdate|CRenderTarget::TS_Resolved; + + continue; + } + } + } + } + else { +// if( start <= texstart && end >= texend ) { +// // texture taken care of so can skip!? +// continue; +// } + } + + // the first range check was very rough; some games (dragonball z) have the zbuf in the same page as textures (but not overlapping) + // so detect that condition + if( ptarg->fbh % m_Blocks[ptarg->psm].height ) { + + // get start of left-most boundry page + int targstart, targend; + ZeroGS::GetRectMemAddress(targstart, targend, ptarg->psm, 0, 0, ptarg->fbw, ptarg->fbh & ~(m_Blocks[ptarg->psm].height-1), ptarg->fbp, ptarg->fbw); + + if( start >= targend ) { + + // don't bother + if( (ptarg->fbh % m_Blocks[ptarg->psm].height) <= 2 ) + continue; + + // calc how many bytes of the block that the page spans + } + } + + if( !(ptarg->status & CRenderTarget::TS_Virtual) ) { + + if( start < ptarg->end && end > ptarg->start ) { + + // suikoden5 is faster with check, but too big of a value and kh screens mess up + /* Zeydlitz remove this check, it does not do anything good + if ((end - start > 0x8000) && (!(g_GameSettings & GAME_GUSTHACK) || (end-start > 0x40000))) { + // intersects, do only one sided resolves + if( end-start > 4*ptarg->fbw ) { // at least it be greater than one scanline (spiro is faster) + if( start > ptarg->start ) { + ptarg->Resolve(ptarg->start, start); + + } + else if( end < ptarg->end ) { + ptarg->Resolve(end, ptarg->end); + } + } + }*/ + + ptarg->status |= CRenderTarget::TS_Resolved; + if( (!ptarg->IsDepth() || (!(g_GameSettings & GAME_NODEPTHUPDATE) || end-start > 0x1000)) && ((end-start > 0x40000) || !(g_GameSettings & GAME_GUSTHACK))) + ptarg->status |= CRenderTarget::TS_NeedUpdate; + } + } + } + + ZeroGS::g_MemTargs.ClearRange(start, end); + } + + s_RangeMngr.Clear(); +} + +static vector s_vTempBuffer, s_vTransferCache; + +void InitTransferHostLocal() +{ + FUNCLOG + if( g_bIsLost ) + return; + +#ifndef RELEASE_TO_PUBLIC + if( gs.trxpos.dx+gs.imageWnew > gs.dstbuf.bw ) + WARN_LOG("Transfer error, width exceeds\n"); +#endif + + bool bHasFlushed = false; + + gs.imageX = gs.trxpos.dx; + gs.imageY = gs.trxpos.dy; + gs.imageEndX = gs.imageX + gs.imageWnew; + gs.imageEndY = gs.imageY + gs.imageHnew; + + assert( gs.imageEndX < 2048 && gs.imageEndY < 2048 ); + + // hack! viewful joe + if( gs.dstbuf.psm == 63 ) + gs.dstbuf.psm = 0; + + int start, end; + GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + + if( end > 0x00400000 ) { + WARN_LOG("host local out of bounds!\n"); + //gs.imageTransfer = -1; + end = 0x00400000; + } + + gs_imageEnd = end; + + if( vb[0].nCount > 0 ) + Flush(0); + if( vb[1].nCount > 0 ) + Flush(1); + + //PRIM_LOG("trans: bp:%x x:%x y:%x w:%x h:%x\n", gs.dstbuf.bp, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew); + +// if( !bHasFlushed && (vb[0].bNeedFrameCheck || vb[0].bNeedZCheck || vb[1].bNeedFrameCheck || vb[1].bNeedZCheck)) { +// Flush(0); +// Flush(1); +// bHasFlushed = 1; +// } +// +// // for all ranges, flush the targets +// // check if new rect intersects with current rendering texture, if so, flush +// if( vb[0].nCount > 0 && vb[0].curprim.tme ) { +// int tstart, tend; +// GetRectMemAddress(tstart, tend, vb[0].tex0.psm, 0, 0, vb[0].tex0.tw, vb[0].tex0.th, vb[0].tex0.tbp0, vb[0].tex0.tbw); +// +// if( start < tend && end > tstart ) { +// Flush(0); +// Flush(1); +// bHasFlushed = 1; +// } +// } +// +// if( !bHasFlushed && vb[1].nCount > 0 && vb[1].curprim.tme ) { +// int tstart, tend; +// GetRectMemAddress(tstart, tend, vb[1].tex0.psm, 0, 0, vb[1].tex0.tw, vb[1].tex0.th, vb[1].tex0.tbp0, vb[1].tex0.tbw); +// +// if( start < tend && end > tstart ) { +// Flush(0); +// Flush(1); +// bHasFlushed = 1; +// } +// } + + //ZeroGS::g_MemTargs.ClearRange(start, end); + //s_RangeMngr.Insert(start, end); +} + +void TransferHostLocal(const void* pbyMem, u32 nQWordSize) +{ + FUNCLOG + if( g_bIsLost ) + return; + + int start, end; + GetRectMemAddress(start, end, gs.dstbuf.psm, gs.imageX, gs.imageY, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + assert( start < gs_imageEnd ); + + end = gs_imageEnd; + + // sometimes games can decompress to alpha channel of render target only, in this case + // do a resolve right away. wolverine x2 + if ((gs.dstbuf.psm == PSMT8H || gs.dstbuf.psm == PSMT4HL || gs.dstbuf.psm == PSMT4HH) && !(g_GameSettings & GAME_GUSTHACK)) { + list listTransmissionUpdateTargs; + s_RTs.GetTargs(start, end, listTransmissionUpdateTargs); + + for(list::iterator it = listTransmissionUpdateTargs.begin(); it != listTransmissionUpdateTargs.end(); ++it) { + + CRenderTarget* ptarg = *it; + + if( (ptarg->status & CRenderTarget::TS_Virtual) ) + continue; + + //ERROR_LOG("resolving to alpha channel\n"); + ptarg->Resolve(); + } + } + + s_RangeMngr.Insert(start, min(end, start+(int)nQWordSize*16)); + + const u8* porgend = (const u8*)pbyMem + 4 * nQWordSize; + + if( s_vTransferCache.size() > 0 ) { + + int imagecache = s_vTransferCache.size(); + s_vTempBuffer.resize(imagecache + nQWordSize*4); + memcpy(&s_vTempBuffer[0], &s_vTransferCache[0], imagecache); + memcpy(&s_vTempBuffer[imagecache], pbyMem, nQWordSize*4); + + pbyMem = (const void*)&s_vTempBuffer[0]; + porgend = &s_vTempBuffer[0]+s_vTempBuffer.size(); + + int wordinc = imagecache / 4; + if( (nQWordSize * 4 + imagecache)/3 == ((nQWordSize+wordinc) * 4) / 3 ) { + // can use the data + nQWordSize += wordinc; + } + } + + int leftover = m_Blocks[gs.dstbuf.psm].TransferHostLocal(pbyMem, nQWordSize); + + if( leftover > 0 ) { + // copy the last gs.image24bitOffset to the cache + s_vTransferCache.resize(leftover); + memcpy(&s_vTransferCache[0], porgend - leftover, leftover); + } + else s_vTransferCache.resize(0); + +#if !defined(RELEASE_TO_PUBLIC) && defined(_DEBUG) + if( g_bSaveTrans ) { + tex0Info t; + t.tbp0 = gs.dstbuf.bp; + t.tw = gs.imageWnew; + t.th = gs.imageHnew; + t.tbw = gs.dstbuf.bw; + t.psm = gs.dstbuf.psm; + SaveTex(&t, 0); + } +#endif +} + +#if 0 +// left/right, top/down +//void TransferHostLocal(const void* pbyMem, u32 nQWordSize) +//{ +// assert( gs.imageTransfer == 0 ); +// u8* pstart = g_pbyGSMemory + gs.dstbuf.bp*256; +// +// const u8* pendbuf = (const u8*)pbyMem + nQWordSize*4; +// int i = gs.imageY, j = gs.imageX; +// +//#define DSTPSM gs.dstbuf.psm +// +//#define TRANSFERHOSTLOCAL(psm, T, widthlimit) { \ +// const T* pbuf = (const T*)pbyMem; \ +// u32 nSize = nQWordSize*(4/sizeof(T)); \ +// assert( (nSize%widthlimit) == 0 && widthlimit <= 4 ); \ +// if( ((gs.imageEndX-gs.trxpos.dx)%widthlimit) ) ERROR_LOG("Bad Transmission! %d %d, psm: %d\n", gs.trxpos.dx, gs.imageEndX, DSTPSM); \ +// for(; i < gs.imageEndY; ++i) { \ +// for(; j < gs.imageEndX && nSize > 0; j += widthlimit, nSize -= widthlimit, pbuf += widthlimit) { \ +// /* write as many pixel at one time as possible */ \ +// writePixel##psm##_0(pstart, j%2048, i%2048, pbuf[0], gs.dstbuf.bw); \ +// \ +// if( widthlimit > 1 ) { \ +// writePixel##psm##_0(pstart, (j+1)%2048, i%2048, pbuf[1], gs.dstbuf.bw); \ +// \ +// if( widthlimit > 2 ) { \ +// writePixel##psm##_0(pstart, (j+2)%2048, i%2048, pbuf[2], gs.dstbuf.bw); \ +// \ +// if( widthlimit > 3 ) { \ +// writePixel##psm##_0(pstart, (j+3)%2048, i%2048, pbuf[3], gs.dstbuf.bw); \ +// } \ +// } \ +// } \ +// } \ +// \ +// if( j >= gs.imageEndX ) { assert(j == gs.imageEndX); j = gs.trxpos.dx; } \ +// else { assert( nSize == 0 ); goto End; } \ +// } \ +//} \ +// +//#define TRANSFERHOSTLOCAL_4(psm) { \ +// const u8* pbuf = (const u8*)pbyMem; \ +// u32 nSize = nQWordSize*8; \ +// for(; i < gs.imageEndY; ++i) { \ +// for(; j < gs.imageEndX && nSize > 0; j += 8, nSize -= 8) { \ +// /* write as many pixel at one time as possible */ \ +// writePixel##psm##_0(pstart, j%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ +// writePixel##psm##_0(pstart, (j+1)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ +// pbuf++; \ +// writePixel##psm##_0(pstart, (j+2)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ +// writePixel##psm##_0(pstart, (j+3)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ +// pbuf++; \ +// writePixel##psm##_0(pstart, (j+4)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ +// writePixel##psm##_0(pstart, (j+5)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ +// pbuf++; \ +// writePixel##psm##_0(pstart, (j+6)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ +// writePixel##psm##_0(pstart, (j+7)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ +// pbuf++; \ +// } \ +// \ +// if( j >= gs.imageEndX ) { /*assert(j == gs.imageEndX);*/ j = gs.trxpos.dx; } \ +// else { assert( nSize == 0 ); goto End; } \ +// } \ +//} \ +// +// switch (gs.dstbuf.psm) { +// case 0x0: TRANSFERHOSTLOCAL(32, u32, 2); break; +// case 0x1: TRANSFERHOSTLOCAL(24, u32, 4); break; +// case 0x2: TRANSFERHOSTLOCAL(16, u16, 4); break; +// case 0xA: TRANSFERHOSTLOCAL(16S, u16, 4); break; +// case 0x13: +// if( ((gs.imageEndX-gs.trxpos.dx)%4) ) { +// TRANSFERHOSTLOCAL(8, u8, 1); +// } +// else { +// TRANSFERHOSTLOCAL(8, u8, 4); +// } +// break; +// +// case 0x14: +//// if( (gs.imageEndX-gs.trxpos.dx)%8 ) { +//// // hack +//// if( abs((int)nQWordSize*8 - (gs.imageEndY-i)*(gs.imageEndX-gs.trxpos.dx)+(j-gs.trxpos.dx)) <= 8 ) { +//// // don't transfer +//// ERROR_LOG("bad texture 4: %d %d %d\n", gs.trxpos.dx, gs.imageEndX, nQWordSize); +//// gs.imageEndX = gs.trxpos.dx + (gs.imageEndX-gs.trxpos.dx)&~7; +//// //i = gs.imageEndY; +//// //goto End; +//// gs.imageTransfer = -1; +//// } +//// } +// TRANSFERHOSTLOCAL_4(4); +// break; +// case 0x1B: TRANSFERHOSTLOCAL(8H, u8, 4); break; +// case 0x24: TRANSFERHOSTLOCAL_4(4HL); break; +// case 0x2C: TRANSFERHOSTLOCAL_4(4HH); break; +// case 0x30: TRANSFERHOSTLOCAL(32Z, u32, 2); break; +// case 0x31: TRANSFERHOSTLOCAL(24Z, u32, 4); break; +// case 0x32: TRANSFERHOSTLOCAL(16Z, u16, 4); break; +// case 0x3A: TRANSFERHOSTLOCAL(16SZ, u16, 4); break; +// } +// +//End: +// if( i >= gs.imageEndY ) { +// assert( i == gs.imageEndY ); +// gs.imageTransfer = -1; +// +// if( g_bSaveTrans ) { +// tex0Info t; +// t.tbp0 = gs.dstbuf.bp; +// t.tw = gs.imageWnew; +// t.th = gs.imageHnew; +// t.tbw = gs.dstbuf.bw; +// t.psm = gs.dstbuf.psm; +// SaveTex(&t, 0); +// } +// } +// else { +// /* update new params */ +// gs.imageY = i; +// gs.imageX = j; +// } +//} +#endif //if 0 + +void InitTransferLocalHost() +{ + FUNCLOG + assert( gs.trxpos.sx+gs.imageWnew <= 2048 && gs.trxpos.sy+gs.imageHnew <= 2048 ); + +#ifndef RELEASE_TO_PUBLIC + if( gs.trxpos.sx+gs.imageWnew > gs.srcbuf.bw ) + WARN_LOG("Transfer error, width exceeds\n"); +#endif + + gs.imageX = gs.trxpos.sx; + gs.imageY = gs.trxpos.sy; + gs.imageEndX = gs.imageX + gs.imageWnew; + gs.imageEndY = gs.imageY + gs.imageHnew; + s_vTransferCache.resize(0); + + int start, end; + GetRectMemAddress(start, end, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw); + ResolveInRange(start, end); +} + +// left/right, top/down +void TransferLocalHost(void* pbyMem, u32 nQWordSize) +{ + FUNCLOG + assert( gs.imageTransfer == 1 ); + + u8* pstart = g_pbyGSMemory + 256*gs.srcbuf.bp; + int i = gs.imageY, j = gs.imageX; + +#define TRANSFERLOCALHOST(psm, T) { \ + T* pbuf = (T*)pbyMem; \ + u32 nSize = nQWordSize*16/sizeof(T); \ + for(; i < gs.imageEndY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; ++j, --nSize) { \ + *pbuf++ = readPixel##psm##_0(pstart, j%2048, i%2048, gs.srcbuf.bw); \ + } \ + \ + if( j >= gs.imageEndX ) { assert( j == gs.imageEndX); j = gs.trxpos.sx; } \ + else { assert( nSize == 0 ); break; } \ + } \ +} \ + +#define TRANSFERLOCALHOST_24(psm) { \ + u8* pbuf = (u8*)pbyMem; \ + u32 nSize = nQWordSize*16/3; \ + for(; i < gs.imageEndY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; ++j, --nSize) { \ + u32 p = readPixel##psm##_0(pstart, j%2048, i%2048, gs.srcbuf.bw); \ + pbuf[0] = (u8)p; \ + pbuf[1] = (u8)(p>>8); \ + pbuf[2] = (u8)(p>>16); \ + pbuf += 3; \ + } \ + \ + if( j >= gs.imageEndX ) { assert( j == gs.imageEndX); j = gs.trxpos.sx; } \ + else { assert( nSize == 0 ); break; } \ + } \ +} \ + + switch (gs.srcbuf.psm) { + case 0x0: TRANSFERLOCALHOST(32, u32); break; + case 0x1: TRANSFERLOCALHOST_24(24); break; + case 0x2: TRANSFERLOCALHOST(16, u16); break; + case 0xA: TRANSFERLOCALHOST(16S, u16); break; + case 0x13: TRANSFERLOCALHOST(8, u8); break; + case 0x1B: TRANSFERLOCALHOST(8H, u8); break; + case 0x30: TRANSFERLOCALHOST(32Z, u32); break; + case 0x31: TRANSFERLOCALHOST_24(24Z); break; + case 0x32: TRANSFERLOCALHOST(16Z, u16); break; + case 0x3A: TRANSFERLOCALHOST(16SZ, u16); break; + default: assert(0); + } + + gs.imageY = i; + gs.imageX = j; + + if( gs.imageY >= gs.imageEndY ) { + assert( gs.imageY == gs.imageEndY ); + gs.imageTransfer = -1; + } +} + +// dir depends on trxpos.dir +void TransferLocalLocal() +{ + FUNCLOG + assert( gs.imageTransfer == 2 ); + assert( gs.trxpos.sx+gs.imageWnew < 2048 && gs.trxpos.sy+gs.imageHnew < 2048 ); + assert( gs.trxpos.dx+gs.imageWnew < 2048 && gs.trxpos.dy+gs.imageHnew < 2048 ); + assert( (gs.srcbuf.psm&0x7) == (gs.dstbuf.psm&0x7) ); + if( gs.trxpos.sx+gs.imageWnew > gs.srcbuf.bw ) + WARN_LOG("Transfer error, src width exceeds\n"); + if( gs.trxpos.dx+gs.imageWnew > gs.dstbuf.bw ) + WARN_LOG("Transfer error, dst width exceeds\n"); + + int srcstart, srcend, dststart, dstend; + + GetRectMemAddress(srcstart, srcend, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw); + GetRectMemAddress(dststart, dstend, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + + // resolve the targs + ResolveInRange(srcstart, srcend); + + list listTargs; + s_RTs.GetTargs(dststart, dstend, listTargs); + for(list::iterator it = listTargs.begin(); it != listTargs.end(); ++it) { + if( !((*it)->status & CRenderTarget::TS_Virtual) ) { + (*it)->Resolve(); + //(*it)->status |= CRenderTarget::TS_NeedUpdate; + } + } + + u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp*256; + u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp*256; + +#define TRANSFERLOCALLOCAL(srcpsm, dstpsm, widthlimit) { \ + if( (gs.imageWnew&widthlimit)!=0 ) break; \ + assert( (gs.imageWnew&widthlimit)==0 && widthlimit <= 4); \ + for(int i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < gs.trxpos.sy+gs.imageHnew; i++, i2++) { \ + for(int j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < gs.trxpos.sx+gs.imageWnew; j+=widthlimit, j2+=widthlimit) { \ + \ + writePixel##dstpsm##_0(pDstBuf, j2%2048, i2%2048, \ + readPixel##srcpsm##_0(pSrcBuf, j%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); \ + \ + if( widthlimit > 1 ) { \ + writePixel##dstpsm##_0(pDstBuf, (j2+1)%2048, i2%2048, \ + readPixel##srcpsm##_0(pSrcBuf, (j+1)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); \ + \ + if( widthlimit > 2 ) { \ + writePixel##dstpsm##_0(pDstBuf, (j2+2)%2048, i2%2048, \ + readPixel##srcpsm##_0(pSrcBuf, (j+2)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); \ + \ + if( widthlimit > 3 ) { \ + writePixel##dstpsm##_0(pDstBuf, (j2+3)%2048, i2%2048, \ + readPixel##srcpsm##_0(pSrcBuf, (j+3)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); \ + } \ + } \ + } \ + } \ + } \ +} \ + +#define TRANSFERLOCALLOCAL_4(srcpsm, dstpsm) { \ + assert( (gs.imageWnew%8) == 0 ); \ + for(int i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < gs.trxpos.sy+gs.imageHnew; ++i, ++i2) { \ + for(int j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < gs.trxpos.sx+gs.imageWnew; j+=8, j2+=8) { \ + /* NOTE: the 2 conseq 4bit values are in NOT in the same byte */ \ + u32 read = getPixelAddress##srcpsm##_0(j%2048, i%2048, gs.srcbuf.bw); \ + u32 write = getPixelAddress##dstpsm##_0(j2%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); \ + \ + read = getPixelAddress##srcpsm##_0((j+1)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+1)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); \ + \ + read = getPixelAddress##srcpsm##_0((j+2)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+2)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); \ + \ + read = getPixelAddress##srcpsm##_0((j+3)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+3)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); \ + \ + read = getPixelAddress##srcpsm##_0((j+2)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+2)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); \ + \ + read = getPixelAddress##srcpsm##_0((j+3)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+3)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); \ + \ + read = getPixelAddress##srcpsm##_0((j+2)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+2)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); \ + \ + read = getPixelAddress##srcpsm##_0((j+3)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+3)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); \ + } \ + } \ +} \ + + switch (gs.srcbuf.psm) { + case PSMCT32: + if( gs.dstbuf.psm == PSMCT32 ) { + TRANSFERLOCALLOCAL(32, 32, 2); + } + else { + TRANSFERLOCALLOCAL(32, 32Z, 2); + } + break; + + case PSMCT24: + if( gs.dstbuf.psm == PSMCT24 ) { + TRANSFERLOCALLOCAL(24, 24, 4); + } + else { + TRANSFERLOCALLOCAL(24, 24Z, 4); + } + break; + + case PSMCT16: + switch(gs.dstbuf.psm) { + case PSMCT16: TRANSFERLOCALLOCAL(16, 16, 4); break; + case PSMCT16S: TRANSFERLOCALLOCAL(16, 16S, 4); break; + case PSMT16Z: TRANSFERLOCALLOCAL(16, 16Z, 4); break; + case PSMT16SZ: TRANSFERLOCALLOCAL(16, 16SZ, 4); break; + } + break; + + case PSMCT16S: + switch(gs.dstbuf.psm) { + case PSMCT16: TRANSFERLOCALLOCAL(16S, 16, 4); break; + case PSMCT16S: TRANSFERLOCALLOCAL(16S, 16S, 4); break; + case PSMT16Z: TRANSFERLOCALLOCAL(16S, 16Z, 4); break; + case PSMT16SZ: TRANSFERLOCALLOCAL(16S, 16SZ, 4); break; + } + break; + + case PSMT8: + if( gs.dstbuf.psm == PSMT8 ) { + TRANSFERLOCALLOCAL(8, 8, 4); + } + else { + TRANSFERLOCALLOCAL(8, 8H, 4); + } + break; + + case PSMT4: + + switch(gs.dstbuf.psm ) { + case PSMT4: TRANSFERLOCALLOCAL_4(4, 4); break; + case PSMT4HL: TRANSFERLOCALLOCAL_4(4, 4HL); break; + case PSMT4HH: TRANSFERLOCALLOCAL_4(4, 4HH); break; + } + break; + + case PSMT8H: + if( gs.dstbuf.psm == PSMT8 ) { + TRANSFERLOCALLOCAL(8H, 8, 4); + } + else { + TRANSFERLOCALLOCAL(8H, 8H, 4); + } + break; + + case PSMT4HL: + switch(gs.dstbuf.psm ) { + case PSMT4: TRANSFERLOCALLOCAL_4(4HL, 4); break; + case PSMT4HL: TRANSFERLOCALLOCAL_4(4HL, 4HL); break; + case PSMT4HH: TRANSFERLOCALLOCAL_4(4HL, 4HH); break; + } + break; + case PSMT4HH: + switch(gs.dstbuf.psm ) { + case PSMT4: TRANSFERLOCALLOCAL_4(4HH, 4); break; + case PSMT4HL: TRANSFERLOCALLOCAL_4(4HH, 4HL); break; + case PSMT4HH: TRANSFERLOCALLOCAL_4(4HH, 4HH); break; + } + break; + + case PSMT32Z: + if( gs.dstbuf.psm == PSMCT32 ) { + TRANSFERLOCALLOCAL(32Z, 32, 2); + } + else { + TRANSFERLOCALLOCAL(32Z, 32Z, 2); + } + break; + + case PSMT24Z: + if( gs.dstbuf.psm == PSMCT24 ) { + TRANSFERLOCALLOCAL(24Z, 24, 4); + } + else { + TRANSFERLOCALLOCAL(24Z, 24Z, 4); + } + break; + + case PSMT16Z: + switch(gs.dstbuf.psm) { + case PSMCT16: TRANSFERLOCALLOCAL(16Z, 16, 4); break; + case PSMCT16S: TRANSFERLOCALLOCAL(16Z, 16S, 4); break; + case PSMT16Z: TRANSFERLOCALLOCAL(16Z, 16Z, 4); break; + case PSMT16SZ: TRANSFERLOCALLOCAL(16Z, 16SZ, 4); break; + } + break; + + case PSMT16SZ: + switch(gs.dstbuf.psm) { + case PSMCT16: TRANSFERLOCALLOCAL(16SZ, 16, 4); break; + case PSMCT16S: TRANSFERLOCALLOCAL(16SZ, 16S, 4); break; + case PSMT16Z: TRANSFERLOCALLOCAL(16SZ, 16Z, 4); break; + case PSMT16SZ: TRANSFERLOCALLOCAL(16SZ, 16SZ, 4); break; + } + break; + } + + g_MemTargs.ClearRange(dststart, dstend); + +#ifdef DEVBUILD + if( g_bSaveTrans ) { + tex0Info t; + t.tbp0 = gs.dstbuf.bp; + t.tw = gs.imageWnew; + t.th = gs.imageHnew; + t.tbw = gs.dstbuf.bw; + t.psm = gs.dstbuf.psm; + SaveTex(&t, 0); + + t.tbp0 = gs.srcbuf.bp; + t.tw = gs.imageWnew; + t.th = gs.imageHnew; + t.tbw = gs.srcbuf.bw; + t.psm = gs.srcbuf.psm; + SaveTex(&t, 0); + } +#endif +} + +void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw) +{ + FUNCLOG + if( m_Blocks[psm].bpp == 0 ) { + ERROR_LOG("ZeroGS: Bad psm 0x%x\n", psm); + start = 0; + end = 0x00400000; + return; + } + + if( PSMT_ISZTEX(psm) || psm == PSMCT16S ) { + + const BLOCK& b = m_Blocks[psm]; + + bw = (bw + b.width - 1)/b.width; + start = bp*256 + ((y/b.height) * bw + (x/b.width) )*0x2000; + end = bp*256 + (((y+h-1)/b.height) * bw + (x + w + b.width - 1)/b.width)*0x2000; + } + else { + // just take the addresses + switch(psm) { + case PSMCT32: + case PSMCT24: + case PSMT8H: + case PSMT4HL: + case PSMT4HH: + start = 4*getPixelAddress32(x, y, bp, bw); + end = 4*getPixelAddress32(x+w-1, y+h-1, bp, bw) + 4; + break; + case PSMCT16: + start = 2*getPixelAddress16(x, y, bp, bw); + end = 2*getPixelAddress16(x+w-1, y+h-1, bp, bw)+2; + break; + case PSMT8: + start = getPixelAddress8(x, y, bp, bw); + end = getPixelAddress8(x+w-1, y+h-1, bp, bw)+1; + break; + case PSMT4: + { + start = getPixelAddress4(x, y, bp, bw)/2; + int newx = ((x+w-1+31)&~31)-1; + int newy = ((y+h-1+15)&~15)-1; + end = (getPixelAddress4(max(newx,x), max(newy,y), bp, bw)+2)/2; + break; + } + } + } +} + +void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm, bool mode) +{ + FUNCLOG + //assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); + s_nResolved += 2; + + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + int start, end; + GetRectMemAddress(start, end, psm, 0, 0, fbw, fbh, fbp, fbw); + + int i, j; + short smask1 = gs.smask&1; + short smask2 = gs.smask&2; + u32 mask, imask; + + if (PSMT_ISHALF(psm)) { // 16 bit + // mask is shifted + imask = RGBA32to16(fbm); + mask = (~imask)&0xffff; + } + else { + mask = ~fbm; + imask = fbm; + + if( (psm&0xf)>0 && 0) { + // preserve the alpha? + mask &= 0x00ffffff; + imask |= 0xff000000; + } + } + + // Targets over 2000 should be shuffle. FFX and KH2 (0x2100) + int X = (psm == 0) ? 0 : 0; +//if (X == 1) +//ERROR_LOG("resolve: %x %x %x %x (%x-%x)\n", psm, fbp, fbw, fbh, start, end); + + +#define RESOLVE_32BIT(psm, T, Tsrc, blockbits, blockwidth, blockheight, convfn, frame, aax, aay) \ + { \ + Tsrc* src = (Tsrc*)(psrc); \ + T* pPageOffset = (T*)g_pbyGSMemory + fbp*(256/sizeof(T)), *dst; \ + int srcpitch = Pitch(fbw) * blockheight/sizeof(Tsrc); \ + int maxfbh = (0x00400000-fbp*256) / (sizeof(T) * fbw); \ + if( maxfbh > fbh ) maxfbh = fbh; \ + for(i = 0; i < (maxfbh&~(blockheight-1))*X; i += blockheight) { \ + /*if( smask2 && (i&1) == smask1 ) continue; */ \ + for(j = 0; j < fbw; j += blockwidth) { \ + /* have to write in the tiled format*/ \ + frame##SwizzleBlock##blockbits(pPageOffset + getPixelAddress##psm##_0(j, i, fbw), \ + src+RW(j), Pitch(fbw)/sizeof(Tsrc), mask); \ + } \ + src += RH(srcpitch); \ + } \ + for(; i < maxfbh; ++i) { \ + for(j = 0; j < fbw; ++j) { \ + T dsrc = convfn(src[RW(j)]); \ + dst = pPageOffset + getPixelAddress##psm##_0(j, i, fbw); \ + *dst = (dsrc & mask) | (*dst & imask); \ + } \ + src += RH(Pitch(fbw))/sizeof(Tsrc); \ + } \ + } \ + + if( GetRenderFormat() == RFT_byte8 ) { + // start the conversion process A8R8G8B8 -> psm + switch(psm) { + case PSMCT32: + case PSMCT24: + if( s_AAy ) { + RESOLVE_32BIT(32, u32, u32, 32A4, 8, 8, (u32), Frame, s_AAx, s_AAy); + } + else if( s_AAx ) { + RESOLVE_32BIT(32, u32, u32, 32A2, 8, 8, (u32), Frame, 1, 0); + } + else { + RESOLVE_32BIT(32, u32, u32, 32, 8, 8, (u32), Frame, 0, 0); + } + break; + case PSMCT16: + if( s_AAy ) { + RESOLVE_32BIT(16, u16, u32, 16A4, 16, 8, RGBA32to16, Frame, s_AAx, s_AAy); + } + else if( s_AAx ) { + RESOLVE_32BIT(16, u16, u32, 16A2, 16, 8, RGBA32to16, Frame, 1, 0); + } + else { + RESOLVE_32BIT(16, u16, u32, 16, 16, 8, RGBA32to16, Frame, 0, 0); + } + + break; + case PSMCT16S: + if( s_AAy ) { + RESOLVE_32BIT(16S, u16, u32, 16A4, 16, 8, RGBA32to16, Frame, s_AAx, s_AAy); + } + else if( s_AAx ) { + RESOLVE_32BIT(16S, u16, u32, 16A2, 16, 8, RGBA32to16, Frame, 1, 0); + } + else { + RESOLVE_32BIT(16S, u16, u32, 16, 16, 8, RGBA32to16, Frame, 0, 0); + } + + break; + case PSMT32Z: + case PSMT24Z: + if( s_AAy ) { + RESOLVE_32BIT(32Z, u32, u32, 32A4, 8, 8, (u32), Frame, s_AAx, s_AAy); + } + else if( s_AAx ) { + RESOLVE_32BIT(32Z, u32, u32, 32A2, 8, 8, (u32), Frame, 1, 0); + } + else { + RESOLVE_32BIT(32Z, u32, u32, 32, 8, 8, (u32), Frame, 0, 0); + } + + break; + case PSMT16Z: + if( s_AAy ) { + RESOLVE_32BIT(16Z, u16, u32, 16A4, 16, 8, (u16), Frame, s_AAx, s_AAy); + } + else if( s_AAx ) { + RESOLVE_32BIT(16Z, u16, u32, 16A2, 16, 8, (u16), Frame, 1, 0); + } + else { + RESOLVE_32BIT(16Z, u16, u32, 16, 16, 8, (u16), Frame, 0, 0); + } + + break; + case PSMT16SZ: + if( s_AAy ) { + RESOLVE_32BIT(16SZ, u16, u32, 16A4, 16, 8, (u16), Frame, s_AAx, s_AAy); + } + else if( s_AAx ) { + RESOLVE_32BIT(16SZ, u16, u32, 16A2, 16, 8, (u16), Frame, 1, 0); + } + else { + RESOLVE_32BIT(16SZ, u16, u32, 16, 16, 8, (u16), Frame, 0, 0); + } + + break; + } + } + else { // float16 + switch(psm) { + case PSMCT32: + case PSMCT24: + if( s_AAy ) { + RESOLVE_32BIT(32, u32, Vector_16F, 32A4, 8, 8, Float16ToARGB, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(32, u32, Vector_16F, 32A2, 8, 8, Float16ToARGB, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(32, u32, Vector_16F, 32, 8, 8, Float16ToARGB, Frame16, 0, 0); + } + + break; + case PSMCT16: + if( s_AAy ) { + RESOLVE_32BIT(16, u16, Vector_16F, 16A4, 16, 8, Float16ToARGB16, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16, u16, Vector_16F, 16A2, 16, 8, Float16ToARGB16, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(16, u16, Vector_16F, 16, 16, 8, Float16ToARGB16, Frame16, 0, 0); + } + + break; + case PSMCT16S: + if( s_AAy ) { + RESOLVE_32BIT(16S, u16, Vector_16F, 16A4, 16, 8, Float16ToARGB16, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16S, u16, Vector_16F, 16A2, 16, 8, Float16ToARGB16, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(16S, u16, Vector_16F, 16, 16, 8, Float16ToARGB16, Frame16, 0, 0); + } + + break; + case PSMT32Z: + case PSMT24Z: + if( s_AAy ) { + RESOLVE_32BIT(32Z, u32, Vector_16F, 32ZA4, 8, 8, Float16ToARGB_Z, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(32Z, u32, Vector_16F, 32ZA2, 8, 8, Float16ToARGB_Z, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(32Z, u32, Vector_16F, 32Z, 8, 8, Float16ToARGB_Z, Frame16, 0, 0); + } + + break; + case PSMT16Z: + if( s_AAy ) { + RESOLVE_32BIT(16Z, u16, Vector_16F, 16ZA4, 16, 8, Float16ToARGB16_Z, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16Z, u16, Vector_16F, 16ZA2, 16, 8, Float16ToARGB16_Z, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(16Z, u16, Vector_16F, 16Z, 16, 8, Float16ToARGB16_Z, Frame16, 0, 0); + } + + break; + case PSMT16SZ: + if( s_AAy ) { + RESOLVE_32BIT(16SZ, u16, Vector_16F, 16ZA4, 16, 8, Float16ToARGB16_Z, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16SZ, u16, Vector_16F, 16ZA2, 16, 8, Float16ToARGB16_Z, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(16SZ, u16, Vector_16F, 16Z, 16, 8, Float16ToARGB16_Z, Frame16, 0, 0); + } + + break; + } + } + + g_MemTargs.ClearRange(start, end); + INC_RESOLVE(); +} + +} // End of namespece ZeroGS diff --git a/plugins/zzogl-pg/opengl/targets.h b/plugins/zzogl-pg/opengl/targets.h new file mode 100644 index 0000000000..5849fbc245 --- /dev/null +++ b/plugins/zzogl-pg/opengl/targets.h @@ -0,0 +1,263 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ZEROGS_TARGETS_H__ +#define __ZEROGS_TARGETS_H__ + +#define TARGET_VIRTUAL_KEY 0x80000000 +#include "PS2Edefs.h" + +inline Vector DefaultOneColor( FRAGMENTSHADER ptr ) { + Vector v = Vector ( 1, 1, 1, 1 ); + cgGLSetParameter4fv( ptr.sOneColor, v); + return v ; +} + +namespace ZeroGS { + + inline u32 GetFrameKey (int fbp, int fbw, VB& curvb); + + // manages render targets + class CRenderTargetMngr + { + public: + typedef map MAPTARGETS; + + enum TargetOptions { + TO_DepthBuffer = 1, + TO_StrictHeight = 2, // height returned has to be the same as requested + TO_Virtual = 4 + }; + + ~CRenderTargetMngr() { Destroy(); } + + void Destroy(); + static MAPTARGETS::iterator GetOldestTarg(MAPTARGETS& m); + + CRenderTarget* GetTarg(const frameInfo& frame, u32 Options, int maxposheight); + inline CRenderTarget* GetTarg(int fbp, int fbw, VB& curvb) { + MAPTARGETS::iterator it = mapTargets.find (GetFrameKey(fbp, fbw, curvb)); + +/* if (fbp == 0x3600 && fbw == 0x100 && it == mapTargets.end()) + { + printf("%x\n", GetFrameKey(fbp, fbw, curvb)) ; + printf("%x %x\n", fbp, fbw); + for(MAPTARGETS::iterator it1 = mapTargets.begin(); it1 != mapTargets.end(); ++it1) + printf ("\t %x %x %x %x\n", it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp); + }*/ + return it != mapTargets.end() ? it->second : NULL; + } + + // gets all targets with a range + void GetTargs(int start, int end, list& listTargets) const; + + // resolves all targets within a range + __forceinline void Resolve(int start, int end); + __forceinline void ResolveAll() { + for(MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it ) + it->second->Resolve(); + } + + void DestroyAllTargs(int start, int end, int fbw); + void DestroyIntersecting(CRenderTarget* prndr); + + // promotes a target from virtual to real + inline CRenderTarget* Promote(u32 key) { + assert( !(key & TARGET_VIRTUAL_KEY) ); + + // promote to regular targ + CRenderTargetMngr::MAPTARGETS::iterator it = mapTargets.find(key|TARGET_VIRTUAL_KEY); + assert( it != mapTargets.end() ); + + CRenderTarget* ptarg = it->second; + mapTargets.erase(it); + + DestroyIntersecting(ptarg); + + it = mapTargets.find(key); + if( it != mapTargets.end() ) { + DestroyTarg(it->second); + it->second = ptarg; + } + else + mapTargets[key] = ptarg; + + if( g_GameSettings & GAME_RESOLVEPROMOTED ) + ptarg->status = CRenderTarget::TS_Resolved; + else + ptarg->status = CRenderTarget::TS_NeedUpdate; + return ptarg; + } + + static void DestroyTarg(CRenderTarget* ptarg); + + MAPTARGETS mapTargets, mapDummyTargs; + }; + + class CMemoryTargetMngr + { + public: + CMemoryTargetMngr() : curstamp(0) {} + CMemoryTarget* GetMemoryTarget(const tex0Info& tex0, int forcevalidate); // pcbp is pointer to start of clut + CMemoryTarget* MemoryTarget_SearchExistTarget (int start, int end, int nClutOffset, int clutsize, const tex0Info& tex0, int forcevalidate); + CMemoryTarget* MemoryTarget_ClearedTargetsSearch(int fmt, int widthmult, int channels, int height); + + void Destroy(); // destroy all targs + + void ClearRange(int starty, int endy); // set all targets to cleared + void DestroyCleared(); // flush all cleared targes + void DestroyOldest(); + + list listTargets, listClearedTargets; + u32 curstamp; + + private: + list::iterator DestroyTargetIter(list::iterator& it); + }; + + class CBitwiseTextureMngr + { + public: + ~CBitwiseTextureMngr() { Destroy(); } + + void Destroy(); + + // since GetTex can delete textures to free up mem, it is dangerous if using that texture, so specify at least one other tex to save + __forceinline u32 GetTex(u32 bitvalue, u32 ptexDoNotDelete) { + map::iterator it = mapTextures.find(bitvalue); + if( it != mapTextures.end() ) + return it->second; + return GetTexInt(bitvalue, ptexDoNotDelete); + } + + private: + u32 GetTexInt(u32 bitvalue, u32 ptexDoNotDelete); + + map mapTextures; + }; + + // manages + class CRangeManager + { + public: + CRangeManager() { + ranges.reserve(16); + } + + // [start, end) + struct RANGE { + RANGE() {} + inline RANGE(int start, int end) : start(start), end(end) {} + int start, end; + }; + + // works in semi logN + void Insert(int start, int end); + inline void Clear() { + ranges.resize(0); + } + + vector ranges; // organized in ascending order, non-intersecting + }; + + extern CRenderTargetMngr s_RTs, s_DepthRTs; + extern CBitwiseTextureMngr s_BitwiseTextures; + extern CMemoryTargetMngr g_MemTargs; + + extern u8 s_AAx, s_AAy, s_AAz, s_AAw; + + // Real rendered width, depends on AA and AAneg. + inline int RW(int tbw) { + if (s_AAx >= s_AAz) + return (tbw << ( s_AAx - s_AAz )); + else + return (tbw >> ( s_AAz - s_AAx )); + } + + // Real rendered height, depends on AA and AAneg. + inline int RH(int tbh) { + if (s_AAy >= s_AAw) + return (tbh << ( s_AAy - s_AAw )); + else + return (tbh >> ( s_AAw - s_AAy )); + } + +/* inline void CreateTargetsList(int start, int end, list& listTargs) { + s_DepthRTs.GetTargs(start, end, listTargs); + s_RTs.GetTargs(start, end, listTargs); + }*/ + + // This pattern of functions is called 3 times, so I add creating Targets list into one. + inline list CreateTargetsList(int start, int end) { + list listTargs; + s_DepthRTs.GetTargs(start, end, listTargs); + s_RTs.GetTargs(start, end, listTargs); + return listTargs; + } + + extern Vector g_vdepth; + extern int icurctx; + + extern VERTEXSHADER pvsBitBlt; + extern FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne; + extern FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16; + extern GLuint vboRect; + +// Unworking +#define PSMPOSITION 28 + +// Code width and height of frame into key, that used in targetmanager +// This is 3 variants of one function, Key dependant on fbp and fbw. +inline u32 GetFrameKey (const frameInfo& frame) { + return (((frame.fbw) << 16) | (frame.fbp)); +} +inline u32 GetFrameKey ( CRenderTarget* frame ) { + return (((frame->fbw) << 16) | (frame->fbp)); +} + +inline u32 GetFrameKey (int fbp, int fbw, VB& curvb) { + return (((fbw) << 16) | (fbp)); +} + +inline u16 ShiftHeight (int fbh, int fbp, int fbhCalc) { + return fbh; +} + +//FIXME: this code for P4 ad KH1. It should not be such strange! +//Dummy targets was deleted from mapTargets, but not erased. +inline u32 GetFrameKeyDummy (const frameInfo& frame) { +// if (frame.fbp > 0x2000 && ZZOgl_fbh_Calc(frame) < 0x400 && ZZOgl_fbh_Calc(frame) != frame.fbh) +// printf ("Z %x %x %x %x\n", frame.fbh, frame.fbhCalc, frame.fbp, ZZOgl_fbh_Calc(frame)); + // height over 1024 would shrink to 1024, so dummy targets with calculated size more than 0x400 should be + // distinct by real height. But in FFX there is 3e0 height target, so I put 0x300 as limit + if (/*frame.fbp > 0x2000 && */ZZOgl_fbh_Calc(frame) < 0x300) + return (((frame.fbw) << 16) | ZZOgl_fbh_Calc(frame)); + else + return (((frame.fbw) << 16) | frame.fbh); +} + +inline u32 GetFrameKeyDummy ( CRenderTarget* frame ) { + if (/*frame->fbp > 0x2000 && */ZZOgl_fbh_Calc(frame->fbp, frame->fbw, frame->psm) < 0x300) + return (((frame->fbw) << 16) | ZZOgl_fbh_Calc(frame->fbp, frame->fbw, frame->psm)); + else + return (((frame->fbw) << 16) | frame->fbh); +} + +} // End of namespace + +#endif diff --git a/plugins/zzogl-pg/opengl/x86-32.S b/plugins/zzogl-pg/opengl/x86-32.S new file mode 100644 index 0000000000..73b11f11d6 --- /dev/null +++ b/plugins/zzogl-pg/opengl/x86-32.S @@ -0,0 +1,1002 @@ +# Copyright (C) 2005-2006 zerofrog(@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 ve%rsion 2, or (at your option) +# any later ve%rsion. +# +# 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 GNU Make see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +# +# +.intel_syntax + +## mmx memcpy implementation, size has to be a multiple of 8 +## returns 0 is equal, nonzero value if not equal +## ~10 times faster than standard memcmp +## (zerofrog) +#u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +.globl memcmp_mmx + .type memcmp_mmx, @function +memcmp_mmx: + push %esi + mov %ecx, dword ptr [%esp+16] + mov %edx, dword ptr [%esp+8] + mov %esi, dword ptr [%esp+12] + + cmp %ecx, 32 + jl Done4 + + // custom test first 8 to make sure things are ok + movq %mm0, [%esi] + movq %mm1, [%esi+8] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pand %mm0, %mm1 + movq %mm2, [%esi+16] + pmovmskb %eax, %mm0 + movq %mm3, [%esi+24] + + // check if eq + cmp %eax, 0xff + je NextComp + mov %eax, 1 + jmp End + +NextComp: + pcmpeqd %mm2, [%edx+16] + pcmpeqd %mm3, [%edx+24] + pand %mm2, %mm3 + pmovmskb %eax, %mm2 + + sub %ecx, 32 + add %esi, 32 + add %edx, 32 + + // check if eq + cmp %eax, 0xff + je ContinueTest + mov %eax, 1 + jmp End + + cmp %ecx, 64 + jl Done8 + +Cmp8: + movq %mm0, [%esi] + movq %mm1, [%esi+8] + movq %mm2, [%esi+16] + movq %mm3, [%esi+24] + movq %mm4, [%esi+32] + movq %mm5, [%esi+40] + movq %mm6, [%esi+48] + movq %mm7, [%esi+56] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pcmpeqd %mm2, [%edx+16] + pcmpeqd %mm3, [%edx+24] + pand %mm0, %mm1 + pcmpeqd %mm4, [%edx+32] + pand %mm0, %mm2 + pcmpeqd %mm5, [%edx+40] + pand %mm0, %mm3 + pcmpeqd %mm6, [%edx+48] + pand %mm0, %mm4 + pcmpeqd %mm7, [%edx+56] + pand %mm0, %mm5 + pand %mm0, %mm6 + pand %mm0, %mm7 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je Continue + mov %eax, 1 + jmp End + +Continue: + sub %ecx, 64 + add %esi, 64 + add %edx, 64 +ContinueTest: + cmp %ecx, 64 + jge Cmp8 + +Done8: + test %ecx, 0x20 + jz Done4 + movq %mm0, [%esi] + movq %mm1, [%esi+8] + movq %mm2, [%esi+16] + movq %mm3, [%esi+24] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pcmpeqd %mm2, [%edx+16] + pcmpeqd %mm3, [%edx+24] + pand %mm0, %mm1 + pand %mm0, %mm2 + pand %mm0, %mm3 + pmovmskb %eax, %mm0 + sub %ecx, 32 + add %esi, 32 + add %edx, 32 + + // check if eq + cmp %eax, 0xff + je Done4 + mov %eax, 1 + jmp End + +Done4: + cmp %ecx, 24 + jne Done2 + movq %mm0, [%esi] + movq %mm1, [%esi+8] + movq %mm2, [%esi+16] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pcmpeqd %mm2, [%edx+16] + pand %mm0, %mm1 + pand %mm0, %mm2 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + setne %al + jmp End + +Done2: + cmp %ecx, 16 + jne Done1 + + movq %mm0, [%esi] + movq %mm1, [%esi+8] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pand %mm0, %mm1 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + setne %al + jmp End + +Done1: + cmp %ecx, 8 + jne Done + + mov %eax, [%esi] + mov %esi, [%esi+4] + cmp %eax, [%edx] + je Next + mov %eax, 1 + jmp End + +Next: + cmp %esi, [%edx+4] + setne %al + jmp End + +Done: + xor %eax, %eax + +End: + pop %esi + emms + ret + + +#ifdef ZEROGS_SSE2 +// SSE2 extensions +#define punpck(op, sd0, sd2, s1, s3, d1, d3) \ + movdqa %xmm##d1, %xmm##sd0; \ + pshufd %xmm##d3, %xmm##sd2, 0xe4; \ + punpckl##op %xmm##sd0, %xmm##s1; \ + punpckh##op %xmm##d1, %xmm##s1; \ + punpckl##op %xmm##sd2, %xmm##s3; \ + punpckh##op %xmm##d3, %xmm##s3; \ + + +#define punpcknb \ + movdqa %xmm4, %xmm0; \ + pshufd %xmm5, %xmm1, 0xe4; \ + \ + psllq %xmm1, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm0, %xmm7; \ + pandn %xmm6, %xmm1; \ + por %xmm0, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm1, %xmm4; \ + \ + movdqa %xmm4, %xmm2; \ + pshufd %xmm5, %xmm3, 0xe4; \ + \ + psllq %xmm3, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm2, %xmm7; \ + pandn %xmm6, %xmm3; \ + por %xmm2, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm3, %xmm4; \ + \ + punpck(bw, 0, 2, 1, 3, 4, 6); \ + + +// +// swizzling +// + +// +// SwizzleBlock32 +// + +.globl SwizzleBlock32_sse2 + .type SwizzleBlock32_sse2, @function +SwizzleBlock32_sse2: + + push %esi + push %edi + + mov %edi, %ecx + mov %esi, %edx + mov %edx, [%esp+4+8] + mov %ecx, 4 + + mov %eax, [%esp+8+8] + cmp %eax, 0xffffffff + jne SwizzleBlock32_sse2_2 + + .align 16 +SwizzleBlock32_sse2_1: + movdqa %xmm0, [%esi] + movdqa %xmm4, [%esi+16] + movdqa %xmm1, [%esi+%edx] + movdqa %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movntps [%edi+16*0], %xmm0 + movntps [%edi+16*1], %xmm2 + movntps [%edi+16*2], %xmm4 + movntps [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32_sse2_1 + + pop %edi + pop %esi + + ret 8 + +SwizzleBlock32_sse2_2: + + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32_sse2_3: + movdqa %xmm0, [%esi] + movdqa %xmm4, [%esi+16] + movdqa %xmm1, [%esi+%edx] + movdqa %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*0] + pand %xmm0, %xmm7 + por %xmm0, %xmm3 + movntps [%edi+16*0], %xmm0 + + pandn %xmm5, [%edi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movntps [%edi+16*1], %xmm2 + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm3 + movntps [%edi+16*2], %xmm4 + + pandn %xmm5, [%edi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm5 + movntps [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32_sse2_3 + + pop %edi + pop %esi + + ret 8 + +// +// SwizzleBlock16 +// + +.globl SwizzleBlock16_sse2 + .type SwizzleBlock16_sse2, @function +SwizzleBlock16_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 4 + + .align 16 +SwizzleBlock16_sse2_1: + movdqa %xmm0, [%edx] + movdqa %xmm1, [%edx+16] + movdqa %xmm2, [%edx+%ebx] + movdqa %xmm3, [%edx+%ebx+16] + + punpck(wd, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm5 + + lea %edx, [%edx+%ebx*2] + add %ecx, 64 + + dec %eax + jnz SwizzleBlock16_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock8 +// + +.globl SwizzleBlock8_sse2 + .type SwizzleBlock8_sse2, @function +SwizzleBlock8_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock8_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%edx] + movdqa %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshufd %xmm1, [%edx], 0xb1 + pshufd %xmm3, [%edx+%ebx], 0xb1 + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm4 + movntps [%ecx+16*2], %xmm1 + movntps [%ecx+16*3], %xmm5 + + // col 1, 3 + + pshufd %xmm0, [%edx], 0xb1 + pshufd %xmm2, [%edx+%ebx], 0xb1 + lea %edx, [%edx+%ebx*2] + + movdqa %xmm1, [%edx] + movdqa %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm4 + movntps [%ecx+16*6], %xmm1 + movntps [%ecx+16*7], %xmm5 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock8_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock4 +// + +.globl SwizzleBlock4_sse2 + .type SwizzleBlock4_sse2, @function +SwizzleBlock4_sse2: + + push %ebx + + mov %eax, 0xf0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock4_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%edx] + movdqa %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqa %xmm1, [%edx] + movdqa %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm3 + + // col 1, 3 + + movdqa %xmm0, [%edx] + movdqa %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqa %xmm1, [%edx] + movdqa %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm1 + movntps [%ecx+16*6], %xmm4 + movntps [%ecx+16*7], %xmm3 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock4_sse2_1 + + pop %ebx + + ret 4 + +// +// swizzling with unaligned reads +// + +// +// SwizzleBlock32u +// + +.globl SwizzleBlock32u_sse2 + .type SwizzleBlock32u_sse2, @function +SwizzleBlock32u_sse2: + + push %esi + push %edi + + mov %edi, %ecx + mov %esi, %edx + mov %edx, [%esp+4+8] + mov %ecx, 4 + + mov %eax, [%esp+8+8] + cmp %eax, 0xffffffff + jne SwizzleBlock32u_sse2_2 + + .align 16 +SwizzleBlock32u_sse2_1: + movdqu %xmm0, [%esi] + movdqu %xmm4, [%esi+16] + movdqu %xmm1, [%esi+%edx] + movdqu %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movntps [%edi+16*0], %xmm0 + movntps [%edi+16*1], %xmm2 + movntps [%edi+16*2], %xmm4 + movntps [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32u_sse2_1 + + pop %edi + pop %esi + + ret 8 + +SwizzleBlock32u_sse2_2: + + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32u_sse2_3: + movdqu %xmm0, [%esi] + movdqu %xmm4, [%esi+16] + movdqu %xmm1, [%esi+%edx] + movdqu %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*0] + pand %xmm0, %xmm7 + por %xmm0, %xmm3 + movdqa [%edi+16*0], %xmm0 + + pandn %xmm5, [%edi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movdqa [%edi+16*1], %xmm2 + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm3 + movdqa [%edi+16*2], %xmm4 + + pandn %xmm5, [%edi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm5 + movdqa [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32u_sse2_3 + + pop %edi + pop %esi + + ret 8 + +// +// SwizzleBlock16u +// + +.globl SwizzleBlock16u_sse2 + .type SwizzleBlock16u_sse2, @function +SwizzleBlock16u_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 4 + + .align 16 +SwizzleBlock16u_sse2_1: + movdqu %xmm0, [%edx] + movdqu %xmm1, [%edx+16] + movdqu %xmm2, [%edx+%ebx] + movdqu %xmm3, [%edx+%ebx+16] + + punpck(wd, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm5 + + lea %edx, [%edx+%ebx*2] + add %ecx, 64 + + dec %eax + jnz SwizzleBlock16u_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock8u +// + +.globl SwizzleBlock8u_sse2 + .type SwizzleBlock8u_sse2, @function +SwizzleBlock8u_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock8u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + pshufd %xmm1, %xmm1, 0xb1 + pshufd %xmm3, %xmm3, 0xb1 + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm4 + movntps [%ecx+16*2], %xmm1 + movntps [%ecx+16*3], %xmm5 + + // col 1, 3 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + pshufd %xmm0, %xmm0, 0xb1 + pshufd %xmm2, %xmm2, 0xb1 + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm4 + movntps [%ecx+16*6], %xmm1 + movntps [%ecx+16*7], %xmm5 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock8u_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock4u +// + +.globl SwizzleBlock4u_sse2 + .type SwizzleBlock4u_sse2, @function +SwizzleBlock4u_sse2: + + push %ebx + + mov %eax, 0xf0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock4u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm3 + + // col 1, 3 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm1 + movntps [%ecx+16*6], %xmm4 + movntps [%ecx+16*7], %xmm3 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock4u_sse2_1 + + pop %ebx + + ret 4 + + + .align 16 +s_clut16mask: + .long 0xffff0000 + .long 0xffff0000 + .long 0xffff0000 + .long 0xffff0000 + + .align 16 +s_clut16mask2: + .long 0x0000ffff + .long 0x0000ffff + .long 0x0000ffff + .long 0x0000ffff + +.globl WriteCLUT_T16_I4_CSM1_sse2 + .type WriteCLUT_T16_I4_CSM1_sse2, @function +WriteCLUT_T16_I4_CSM1_sse2: + movdqa %xmm0, xmmword ptr [%ecx] + movdqa %xmm1, xmmword ptr [%ecx+16] + movdqa %xmm2, xmmword ptr [%ecx+32] + movdqa %xmm3, xmmword ptr [%ecx+48] + + // rearrange + pshuflw %xmm0, %xmm0, 0x88 + pshufhw %xmm0, %xmm0, 0x88 + pshuflw %xmm1, %xmm1, 0x88 + pshufhw %xmm1, %xmm1, 0x88 + pshuflw %xmm2, %xmm2, 0x88 + pshufhw %xmm2, %xmm2, 0x88 + pshuflw %xmm3, %xmm3, 0x88 + pshufhw %xmm3, %xmm3, 0x88 + + shufps %xmm0, %xmm1, 0x88 + shufps %xmm2, %xmm3, 0x88 + + pshufd %xmm0, %xmm0, 0xd8 + pshufd %xmm2, %xmm2, 0xd8 + + pxor %xmm6, %xmm6 + + test %edx, 15 + jnz WriteUnaligned + + movdqa %xmm7, [s_clut16mask] // saves upper 16 bits + + // have to save interlaced with the old data + movdqa %xmm4, [%edx] + movdqa %xmm5, [%edx+32] + movhlps %xmm1, %xmm0 + movlhps %xmm0, %xmm2 // lower 8 colors + + pand %xmm4, %xmm7 + pand %xmm5, %xmm7 + + shufps %xmm1, %xmm2, 0xe4 // upper 8 colors + movdqa %xmm2, %xmm0 + movdqa %xmm3, %xmm1 + + punpcklwd %xmm0, %xmm6 + punpcklwd %xmm1, %xmm6 + por %xmm0, %xmm4 + por %xmm1, %xmm5 + + punpckhwd %xmm2, %xmm6 + punpckhwd %xmm3, %xmm6 + + movdqa [%edx], %xmm0 + movdqa [%edx+32], %xmm1 + + movdqa %xmm5, %xmm7 + pand %xmm7, [%edx+16] + pand %xmm5, [%edx+48] + + por %xmm2, %xmm7 + por %xmm3, %xmm5 + + movdqa [%edx+16], %xmm2 + movdqa [%edx+48], %xmm3 + jmp WriteCLUT_T16_I4_CSM1_End + +WriteUnaligned: + // %edx is offset by 2 + sub %edx, 2 + + movdqa %xmm7, [s_clut16mask2] // saves lower 16 bits + + // have to save interlaced with the old data + movdqa %xmm4, [%edx] + movdqa %xmm5, [%edx+32] + movhlps %xmm1, %xmm0 + movlhps %xmm0, %xmm2 // lower 8 colors + + pand %xmm4, %xmm7 + pand %xmm5, %xmm7 + + shufps %xmm1, %xmm2, 0xe4 // upper 8 colors + movdqa %xmm2, %xmm0 + movdqa %xmm3, %xmm1 + + punpcklwd %xmm0, %xmm6 + punpcklwd %xmm1, %xmm6 + pslld %xmm0, 16 + pslld %xmm1, 16 + por %xmm0, %xmm4 + por %xmm1, %xmm5 + + punpckhwd %xmm2, %xmm6 + punpckhwd %xmm3, %xmm6 + pslld %xmm2, 16 + pslld %xmm3, 16 + + movdqa [%edx], %xmm0 + movdqa [%edx+32], %xmm1 + + movdqa %xmm5, %xmm7 + pand %xmm7, [%edx+16] + pand %xmm5, [%edx+48] + + por %xmm2, %xmm7 + por %xmm3, %xmm5 + + movdqa [%edx+16], %xmm2 + movdqa [%edx+48], %xmm3 +WriteCLUT_T16_I4_CSM1_End: + ret + + +.globl WriteCLUT_T32_I8_CSM1_sse2 + .type WriteCLUT_T32_I8_CSM1_sse2, @function +WriteCLUT_T32_I8_CSM1_sse2: + push %ebx + xor %ebx, %ebx +.L231: + xor %eax, %eax + .align 16 +.L232: + movdqa %xmm3, XMMWORD PTR [%eax+16+%ecx] + movdqa %xmm4, XMMWORD PTR [%eax+48+%ecx] + movdqa %xmm1, XMMWORD PTR [%eax+%ecx] + movdqa %xmm2, XMMWORD PTR [%eax+32+%ecx] + movdqa %xmm0, %xmm1 + punpckhqdq %xmm1, %xmm3 + punpcklqdq %xmm0, %xmm3 + movdqa XMMWORD PTR [%edx+32+%eax*2], %xmm1 + movdqa XMMWORD PTR [%edx+%eax*2], %xmm0 + movdqa %xmm0, %xmm2 + punpckhqdq %xmm2, %xmm4 + punpcklqdq %xmm0, %xmm4 + movdqa XMMWORD PTR [%edx+48+%eax*2], %xmm2 + movdqa XMMWORD PTR [%edx+16+%eax*2], %xmm0 + movdqa %xmm1, XMMWORD PTR [%eax+256+%ecx] + movdqa %xmm3, XMMWORD PTR [%eax+272+%ecx] + movdqa %xmm2, XMMWORD PTR [%eax+288+%ecx] + movdqa %xmm4, XMMWORD PTR [%eax+304+%ecx] + movdqa %xmm0, %xmm1 + punpckhqdq %xmm1, %xmm3 + punpcklqdq %xmm0, %xmm3 + movdqa XMMWORD PTR [%edx+96+%eax*2], %xmm1 + movdqa XMMWORD PTR [%edx+64+%eax*2], %xmm0 + movdqa %xmm0, %xmm2 + punpckhqdq %xmm2, %xmm4 + punpcklqdq %xmm0, %xmm4 + movdqa XMMWORD PTR [%edx+112+%eax*2], %xmm2 + movdqa XMMWORD PTR [%edx+80+%eax*2], %xmm0 + add %eax, 64 + cmp %eax, 256 + jne .L232 + add %edx, 512 + add %ecx, 512 + add %ebx, 512 + cmp %ebx, 1024 + jne .L231 + pop %ebx + ret + +.globl WriteCLUT_T32_I4_CSM1_sse2 + .type WriteCLUT_T32_I4_CSM1_sse2, @function +WriteCLUT_T32_I4_CSM1_sse2: + movdqa %xmm1, XMMWORD PTR [%ecx] + movdqa %xmm3, XMMWORD PTR [%ecx+16] + movdqa %xmm2, XMMWORD PTR [%ecx+32] + movdqa %xmm4, XMMWORD PTR [%ecx+48] + movdqa %xmm0, %xmm1 + punpckhqdq %xmm1, %xmm3 + punpcklqdq %xmm0, %xmm3 + movdqa XMMWORD PTR [%edx+32], %xmm1 + movdqa XMMWORD PTR [%edx], %xmm0 + movdqa %xmm0, %xmm2 + punpckhqdq %xmm2, %xmm4 + punpcklqdq %xmm0, %xmm4 + movdqa XMMWORD PTR [%edx+48], %xmm2 + movdqa XMMWORD PTR [%edx+16], %xmm0 + ret + +#endif diff --git a/plugins/zzogl-pg/opengl/x86-32.asm b/plugins/zzogl-pg/opengl/x86-32.asm new file mode 100644 index 0000000000..1507d2192d --- /dev/null +++ b/plugins/zzogl-pg/opengl/x86-32.asm @@ -0,0 +1,652 @@ +; Copyright (C) 2003-2005 Gabest +; http://www.gabest.org +; +; 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, 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 GNU Make; see the file COPYING. If not, write to +; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +; http://www.gnu.org/copyleft/gpl.html +; +; + .686 + .model flat + .mmx + .xmm + + .const + + __uvmin DD 0d01502f9r ; -1e+010 + __uvmax DD 0501502f9r ; +1e+010 + + .code + +; +; swizzling +; + +punpck macro op, sd0, sd2, s1, s3, d1, d3 + + movdqa @CatStr(xmm, %d1), @CatStr(xmm, %sd0) + pshufd @CatStr(xmm, %d3), @CatStr(xmm, %sd2), 0e4h + + @CatStr(punpckl, op) @CatStr(xmm, %sd0), @CatStr(xmm, %s1) + @CatStr(punpckh, op) @CatStr(xmm, %d1), @CatStr(xmm, %s1) + @CatStr(punpckl, op) @CatStr(xmm, %sd2), @CatStr(xmm, %s3) + @CatStr(punpckh, op) @CatStr(xmm, %d3), @CatStr(xmm, %s3) + + endm + +punpcknb macro + + movdqa xmm4, xmm0 + pshufd xmm5, xmm1, 0e4h + + psllq xmm1, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm0, xmm7 + pandn xmm6, xmm1 + por xmm0, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm1, xmm4 + + movdqa xmm4, xmm2 + pshufd xmm5, xmm3, 0e4h + + psllq xmm3, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm2, xmm7 + pandn xmm6, xmm3 + por xmm2, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm3, xmm4 + + punpck bw, 0, 2, 1, 3, 4, 6 + + endm + + +; +; swizzling +; + +; +; SwizzleBlock32 +; + +@SwizzleBlock32_sse2@16 proc public + + + push esi + push edi + + mov edi, ecx + mov esi, edx + mov edx, [esp+4+8] + mov ecx, 4 + + mov eax, [esp+8+8] + cmp eax, 0ffffffffh + jne SwizzleBlock32_sse2@WM + + align 16 +@@: + movdqa xmm0, [esi] + movdqa xmm4, [esi+16] + movdqa xmm1, [esi+edx] + movdqa xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movntps [edi+16*0], xmm0 + movntps [edi+16*1], xmm2 + movntps [edi+16*2], xmm4 + movntps [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +SwizzleBlock32_sse2@WM: + + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqa xmm0, [esi] + movdqa xmm4, [esi+16] + movdqa xmm1, [esi+edx] + movdqa xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movntps [edi+16*0], xmm0 + + pandn xmm5, [edi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movntps [edi+16*1], xmm2 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*2] + pand xmm4, xmm7 + por xmm4, xmm3 + movntps [edi+16*2], xmm4 + + pandn xmm5, [edi+16*3] + pand xmm6, xmm7 + por xmm6, xmm5 + movntps [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +@SwizzleBlock32_sse2@16 endp + +; +; SwizzleBlock16 +; + +@SwizzleBlock16_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 4 + + align 16 +@@: + movdqa xmm0, [edx] + movdqa xmm1, [edx+16] + movdqa xmm2, [edx+ebx] + movdqa xmm3, [edx+ebx+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm5 + + lea edx, [edx+ebx*2] + add ecx, 64 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock16_sse2@12 endp + +; +; SwizzleBlock8 +; + +@SwizzleBlock8_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [edx] + movdqa xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + pshufd xmm1, [edx], 0b1h + pshufd xmm3, [edx+ebx], 0b1h + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm4 + movntps [ecx+16*2], xmm1 + movntps [ecx+16*3], xmm5 + + ; col 1, 3 + + pshufd xmm0, [edx], 0b1h + pshufd xmm2, [edx+ebx], 0b1h + lea edx, [edx+ebx*2] + + movdqa xmm1, [edx] + movdqa xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm4 + movntps [ecx+16*6], xmm1 + movntps [ecx+16*7], xmm5 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock8_sse2@12 endp + +; +; SwizzleBlock4 +; + +@SwizzleBlock4_sse2@12 proc public + + push ebx + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [edx] + movdqa xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqa xmm1, [edx] + movdqa xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm3 + + ; col 1, 3 + + movdqa xmm0, [edx] + movdqa xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqa xmm1, [edx] + movdqa xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm1 + movntps [ecx+16*6], xmm4 + movntps [ecx+16*7], xmm3 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock4_sse2@12 endp + +; +; swizzling with unaligned reads +; + +; +; SwizzleBlock32u +; + +@SwizzleBlock32u_sse2@16 proc public + + push esi + push edi + + mov edi, ecx + mov esi, edx + mov edx, [esp+4+8] + mov ecx, 4 + + mov eax, [esp+8+8] + cmp eax, 0ffffffffh + jne SwizzleBlock32u_sse2@WM + + align 16 +@@: + movdqu xmm0, [esi] + movdqu xmm4, [esi+16] + movdqu xmm1, [esi+edx] + movdqu xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movntps [edi+16*0], xmm0 + movntps [edi+16*1], xmm2 + movntps [edi+16*2], xmm4 + movntps [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +SwizzleBlock32u_sse2@WM: + + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqu xmm0, [esi] + movdqu xmm4, [esi+16] + movdqu xmm1, [esi+edx] + movdqu xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movdqa [edi+16*0], xmm0 + + pandn xmm5, [edi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movdqa [edi+16*1], xmm2 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*2] + pand xmm4, xmm7 + por xmm4, xmm3 + movdqa [edi+16*2], xmm4 + + pandn xmm5, [edi+16*3] + pand xmm6, xmm7 + por xmm6, xmm5 + movdqa [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +@SwizzleBlock32u_sse2@16 endp + +; +; SwizzleBlock16u +; + +@SwizzleBlock16u_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 4 + + align 16 +@@: + movdqu xmm0, [edx] + movdqu xmm1, [edx+16] + movdqu xmm2, [edx+ebx] + movdqu xmm3, [edx+ebx+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm5 + + lea edx, [edx+ebx*2] + add ecx, 64 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock16u_sse2@12 endp + +; +; SwizzleBlock8u +; + +@SwizzleBlock8u_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + pshufd xmm1, xmm1, 0b1h + pshufd xmm3, xmm3, 0b1h + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm4 + movntps [ecx+16*2], xmm1 + movntps [ecx+16*3], xmm5 + + ; col 1, 3 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + pshufd xmm0, xmm0, 0b1h + pshufd xmm2, xmm2, 0b1h + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm4 + movntps [ecx+16*6], xmm1 + movntps [ecx+16*7], xmm5 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock8u_sse2@12 endp + +; +; SwizzleBlock4u +; + +@SwizzleBlock4u_sse2@12 proc public + + push ebx + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm3 + + ; col 1, 3 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm1 + movntps [ecx+16*6], xmm4 + movntps [ecx+16*7], xmm3 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock4u_sse2@12 endp + + end \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/x86-64.S b/plugins/zzogl-pg/opengl/x86-64.S new file mode 100644 index 0000000000..6f221e7b33 --- /dev/null +++ b/plugins/zzogl-pg/opengl/x86-64.S @@ -0,0 +1,906 @@ +## Copyright (C) 2005-2006 zerofrog(@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 ve%rsion 2, or (at your option) +# any later ve%rsion. +# +# 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 GNU Make see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +# +# +.intel_syntax + +## mmx memcpy implementation, size has to be a multiple of 8 +## returns 0 is equal, nonzero value if not equal +## ~10 times faster than standard memcmp +## (zerofrog) +## u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +## %rdi - src1 +## %rsi - src2 +## edx - cmpsize +.globl memcmp_mmx + .type memcmp_mmx, @function +memcmp_mmx: + cmp %edx, 32 + jl Done4 + + ## custom test first 8 to make sure things are ok + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pand %mm0, %mm1 + movq %mm2, [%rsi+16] + pmovmskb %eax, %mm0 + movq %mm3, [%rsi+24] + + // check if eq + cmp %eax, 0xff + je NextComp + mov %eax, 1 + jmp End + +NextComp: + pcmpeqd %mm2, [%rdi+16] + pcmpeqd %mm3, [%rdi+24] + pand %mm2, %mm3 + pmovmskb %eax, %mm2 + + sub %edx, 32 + add %rsi, 32 + add %rdi, 32 + + // check if eq + cmp %eax, 0xff + je ContinueTest + mov %eax, 1 + jmp End + + cmp %edx, 64 + jl Done8 + +Cmp8: + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + movq %mm2, [%rsi+16] + movq %mm3, [%rsi+24] + movq %mm4, [%rsi+32] + movq %mm5, [%rsi+40] + movq %mm6, [%rsi+48] + movq %mm7, [%rsi+56] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pcmpeqd %mm2, [%rdi+16] + pcmpeqd %mm3, [%rdi+24] + pand %mm0, %mm1 + pcmpeqd %mm4, [%rdi+32] + pand %mm0, %mm2 + pcmpeqd %mm5, [%rdi+40] + pand %mm0, %mm3 + pcmpeqd %mm6, [%rdi+48] + pand %mm0, %mm4 + pcmpeqd %mm7, [%rdi+56] + pand %mm0, %mm5 + pand %mm0, %mm6 + pand %mm0, %mm7 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je Continue + mov %eax, 1 + jmp End + +Continue: + sub %edx, 64 + add %rsi, 64 + add %rdi, 64 +ContinueTest: + cmp %edx, 64 + jge Cmp8 + +Done8: + test %edx, 0x20 + jz Done4 + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + movq %mm2, [%rsi+16] + movq %mm3, [%rsi+24] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pcmpeqd %mm2, [%rdi+16] + pcmpeqd %mm3, [%rdi+24] + pand %mm0, %mm1 + pand %mm0, %mm2 + pand %mm0, %mm3 + pmovmskb %eax, %mm0 + sub %edx, 32 + add %rsi, 32 + add %rdi, 32 + + // check if eq + cmp %eax, 0xff + je Done4 + mov %eax, 1 + jmp End + +Done4: + cmp %edx, 24 + jne Done2 + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + movq %mm2, [%rsi+16] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pcmpeqd %mm2, [%rdi+16] + pand %mm0, %mm1 + pand %mm0, %mm2 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je Done + mov %eax, 1 + jmp End + +Done2: + cmp %edx, 16 + jne Done1 + + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pand %mm0, %mm1 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je Done + mov %eax, 1 + jmp End + +Done1: + cmp %edx, 8 + jne Done + + mov %eax, [%rsi] + mov %rsi, [%rsi+4] + cmp %eax, [%rdi] + je Next + mov %eax, 1 + jmp End + +Next: + cmp %rsi, [%rdi+4] + je Done + mov %eax, 1 + jmp End + +Done: + xor %eax, %eax + +End: + emms + ret + +#ifdef ZEROGS_SSE2 +// SSE2 extensions + +#define punpck(op, sd0, sd2, s1, s3, d1, d3) \ + movdqa %xmm##d1, %xmm##sd0; \ + pshufd %xmm##d3, %xmm##sd2, 0xe4; \ + punpckl##op %xmm##sd0, %xmm##s1; \ + punpckh##op %xmm##d1, %xmm##s1; \ + punpckl##op %xmm##sd2, %xmm##s3; \ + punpckh##op %xmm##d3, %xmm##s3; \ + +#define punpcknbl \ + movdqa %xmm4, %xmm0; \ + pshufd %xmm5, %xmm1, 0xe4; \ + \ + psllq %xmm1, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm0, %xmm7; \ + pandn %xmm6, %xmm1; \ + por %xmm0, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm1, %xmm4; \ + \ + movdqa %xmm4, %xmm2; \ + pshufd %xmm5, %xmm3, 0xe4; \ + \ + psllq %xmm3, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm2, %xmm7; \ + pandn %xmm6, %xmm3; \ + por %xmm2, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm3, %xmm4; \ + \ + punpck(bw, 0, 2, 1, 3, 4, 6); \ + +#define punpcknbh \ + movdqa %xmm12, %xmm8; \ + pshufd %xmm13, %xmm9, 0xe4; \ + \ + psllq %xmm9, 4; \ + psrlq %xmm12, 4; \ + \ + movdqa %xmm14, %xmm15; \ + pand %xmm8, %xmm15; \ + pandn %xmm14, %xmm9; \ + por %xmm8, %xmm14; \ + \ + movdqa %xmm14, %xmm15; \ + pand %xmm12, %xmm15; \ + pandn %xmm14, %xmm13; \ + por %xmm12, %xmm14; \ + \ + movdqa %xmm9, %xmm12; \ + \ + movdqa %xmm12, %xmm10; \ + pshufd %xmm13, %xmm11, 0xe4; \ + \ + psllq %xmm11, 4; \ + psrlq %xmm12, 4; \ + \ + movdqa %xmm14, %xmm15; \ + pand %xmm10, %xmm15; \ + pandn %xmm14, %xmm11; \ + por %xmm10, %xmm14; \ + \ + movdqa %xmm14, %xmm15; \ + pand %xmm12, %xmm15; \ + pandn %xmm14, %xmm13; \ + por %xmm12, %xmm14; \ + \ + movdqa %xmm11, %xmm12; \ + \ + punpck(bw, 8, 10, 9, 11, 12, 14); \ + +// +// SwizzleBlock32_sse2 +// + +.globl SwizzleBlock32_sse2 + .type SwizzleBlock32_sse2, @function +SwizzleBlock32_sse2: + + mov %eax, 4 + + cmp %ecx, 0xffffffff + jne SwizzleBlock32_sse2_2 + + .align 16 +SwizzleBlock32_sse2_1: + movdqa %xmm0, [%rsi] + movdqa %xmm4, [%rsi+16] + movdqa %xmm1, [%rsi+%rdx] + movdqa %xmm5, [%rsi+%rdx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm2 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm6 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock32_sse2_1 + + ret + +SwizzleBlock32_sse2_2: + + movd %xmm7, %rcx + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32_sse2_3: + movdqa %xmm0, [%rsi] + movdqa %xmm4, [%rsi+16] + movdqa %xmm1, [%rsi+%rdx] + movdqa %xmm5, [%rsi+%rdx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + movdqa %xmm9, %xmm7 + pshufd %xmm11, %xmm7, 0xe4 + + pandn %xmm3, [%rdi+16*0] + pand %xmm0, %xmm7 + por %xmm0, %xmm3 + movdqa [%rdi+16*0], %xmm0 + + pandn %xmm5, [%rdi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movdqa [%rdi+16*1], %xmm2 + + pandn %xmm9, [%rdi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm9 + movdqa [%rdi+16*2], %xmm4 + + pandn %xmm11, [%rdi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm11 + movdqa [%rdi+16*3], %xmm6 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock32_sse2_3 + + ret + +// +// SwizzleBlock16_sse2 +// + +.globl SwizzleBlock16_sse2 + .type SwizzleBlock16_sse2, @function +SwizzleBlock16_sse2: + + mov %eax, 4 + + .align 16 +SwizzleBlock16_sse2_1: + movdqa %xmm0, [%rsi] + movdqa %xmm1, [%rsi+16] + movdqa %xmm2, [%rsi+%rdx] + movdqa %xmm3, [%rsi+%rdx+16] + + punpck(wd, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm1 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm5 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock16_sse2_1 + + ret + +// +// SwizzleBlock8 +// + +.globl SwizzleBlock8_sse2 + .type SwizzleBlock8_sse2, @function +SwizzleBlock8_sse2: + + mov %ecx, 2 + + .align 16 +SwizzleBlock8_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%rsi] + movdqa %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshufd %xmm1, [%rsi], 0xb1 + pshufd %xmm3, [%rsi+%rdx], 0xb1 + lea %rsi, [%rsi+%rdx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm4 + movdqa [%rdi+16*2], %xmm1 + movdqa [%rdi+16*3], %xmm5 + + // col 1, 3 + + pshufd %xmm0, [%rsi], 0xb1 + pshufd %xmm2, [%rsi+%rdx], 0xb1 + lea %rsi, [%rsi+%rdx*2] + + movdqa %xmm1, [%rsi] + movdqa %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movdqa [%rdi+16*4], %xmm0 + movdqa [%rdi+16*5], %xmm4 + movdqa [%rdi+16*6], %xmm1 + movdqa [%rdi+16*7], %xmm5 + + add %rdi, 128 + + dec %ecx + jnz SwizzleBlock8_sse2_1 + + ret + +// +// SwizzleBlock4 +// + +.globl SwizzleBlock4_sse2 + .type SwizzleBlock4_sse2, @function +SwizzleBlock4_sse2: + + mov %ecx, 2 + + mov %eax, 0x0f0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock4_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%rsi] + movdqa %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + movdqa %xmm1, [%rsi] + movdqa %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + punpcknbl + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm1 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm3 + + // col 1, 3 + + movdqa %xmm0, [%rsi] + movdqa %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + movdqa %xmm1, [%rsi] + movdqa %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknbl + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movdqa [%rdi+16*4], %xmm0 + movdqa [%rdi+16*5], %xmm1 + movdqa [%rdi+16*6], %xmm4 + movdqa [%rdi+16*7], %xmm3 + + add %rdi, 128 + + dec %ecx + jnz SwizzleBlock4_sse2_1 + + ret + +// +// swizzling with unaligned reads +// + +// +// SwizzleBlock32u_sse2 +// + +.globl SwizzleBlock32u_sse2 + .type SwizzleBlock32u_sse2, @function +SwizzleBlock32u_sse2: + + mov %eax, 4 + + cmp %ecx, 0xffffffff + jne SwizzleBlock32u_sse2_2 + + .align 16 +SwizzleBlock32u_sse2_1: + movdqu %xmm0, [%rsi] + movdqu %xmm4, [%rsi+16] + movdqu %xmm1, [%rsi+%rdx] + movdqu %xmm5, [%rsi+%rdx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm2 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm6 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock32u_sse2_1 + + ret + +SwizzleBlock32u_sse2_2: + + movd %xmm7, %rcx + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32u_sse2_3: + movdqu %xmm0, [%rsi] + movdqu %xmm4, [%rsi+16] + movdqu %xmm1, [%rsi+%rdx] + movdqu %xmm5, [%rsi+%rdx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + movdqa %xmm9, %xmm7 + pshufd %xmm11, %xmm7, 0xe4 + + pandn %xmm3, [%rdi+16*0] + pand %xmm0, %xmm7 + por %xmm0, %xmm3 + movdqa [%rdi+16*0], %xmm0 + + pandn %xmm5, [%rdi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movdqa [%rdi+16*1], %xmm2 + + pandn %xmm9, [%rdi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm9 + movdqa [%rdi+16*2], %xmm4 + + pandn %xmm11, [%rdi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm11 + movdqa [%rdi+16*3], %xmm6 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock32u_sse2_3 + + ret + +// +// SwizzleBlock16u_sse2 +// + +.globl SwizzleBlock16u_sse2 + .type SwizzleBlock16u_sse2, @function +SwizzleBlock16u_sse2: + mov %eax, 4 + + .align 16 +SwizzleBlock16u_sse2_1: + movdqu %xmm0, [%rsi] + movdqu %xmm1, [%rsi+16] + movdqu %xmm2, [%rsi+%rdx] + movdqu %xmm3, [%rsi+%rdx+16] + + punpck(wd, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm1 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm5 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock16u_sse2_1 + + ret + +// +// SwizzleBlock8u +// + +.globl SwizzleBlock8u_sse2 + .type SwizzleBlock8u_sse2, @function +SwizzleBlock8u_sse2: + mov %ecx, 2 + + .align 16 +SwizzleBlock8u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%rsi] + movdqu %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshufd %xmm1, %xmm0, 0xb1 + pshufd %xmm3, %xmm2, 0xb1 + lea %rsi, [%rsi+%rdx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm4 + movdqa [%rdi+16*2], %xmm1 + movdqa [%rdi+16*3], %xmm5 + + // col 1, 3 + + movdqu %xmm0, [%rsi] + movdqu %xmm2, [%rsi+%rdx] + pshufd %xmm0, %xmm0, 0xb1 + pshufd %xmm2, %xmm2, 0xb1 + lea %rsi, [%rsi+%rdx*2] + + movdqu %xmm1, [%rsi] + movdqu %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movdqa [%rdi+16*4], %xmm0 + movdqa [%rdi+16*5], %xmm4 + movdqa [%rdi+16*6], %xmm1 + movdqa [%rdi+16*7], %xmm5 + + add %rdi, 128 + + dec %ecx + jnz SwizzleBlock8u_sse2_1 + + ret + +// +// SwizzleBlock4u +// + +.globl SwizzleBlock4u_sse2 + .type SwizzleBlock4u_sse2, @function +SwizzleBlock4u_sse2: + + mov %ecx, 2 + + mov %eax, 0xf0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock4u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%rsi] + movdqu %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + movdqu %xmm1, [%rsi] + movdqu %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + punpcknbl + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm1 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm3 + + // col 1, 3 + + movdqu %xmm0, [%rsi] + movdqu %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + movdqu %xmm1, [%rsi] + movdqu %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknbl + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movdqa [%rdi+16*4], %xmm0 + movdqa [%rdi+16*5], %xmm1 + movdqa [%rdi+16*6], %xmm4 + movdqa [%rdi+16*7], %xmm3 + + add %rdi, 128 + + dec %ecx + jnz SwizzleBlock4u_sse2_1 + + ret + + + .align 16 +s_clut16mask: + .long 0xffff0000 + .long 0xffff0000 + .long 0xffff0000 + .long 0xffff0000 + + .align 16 +s_clut16mask2: + + .long 0x0000ffff + .long 0x0000ffff + .long 0x0000ffff + .long 0x0000ffff + +.globl WriteCLUT_T16_I4_CSM1_sse2 + .type WriteCLUT_T16_I4_CSM1_sse2, @function +WriteCLUT_T16_I4_CSM1_sse2: + movdqa %xmm0, xmmword ptr [%rdi] + movdqa %xmm1, xmmword ptr [%rdi+16] + movdqa %xmm2, xmmword ptr [%rdi+32] + movdqa %xmm3, xmmword ptr [%rdi+48] + + // rearrange + pshuflw %xmm0, %xmm0, 0x88 + pshufhw %xmm0, %xmm0, 0x88 + pshuflw %xmm1, %xmm1, 0x88 + pshufhw %xmm1, %xmm1, 0x88 + pshuflw %xmm2, %xmm2, 0x88 + pshufhw %xmm2, %xmm2, 0x88 + pshuflw %xmm3, %xmm3, 0x88 + pshufhw %xmm3, %xmm3, 0x88 + + shufps %xmm0, %xmm1, 0x88 + shufps %xmm2, %xmm3, 0x88 + + pshufd %xmm0, %xmm0, 0xd8 + pshufd %xmm2, %xmm2, 0xd8 + + pxor %xmm6, %xmm6 + + test %rsi, 15 + jnz WriteUnaligned + + movdqa %xmm7, [%rip+s_clut16mask] // saves upper 16 bits + + // have to save interlaced with the old data + movdqa %xmm4, [%rsi] + movdqa %xmm5, [%rsi+32] + movhlps %xmm1, %xmm0 + movlhps %xmm0, %xmm2 // lower 8 colors + + pand %xmm4, %xmm7 + pand %xmm5, %xmm7 + + shufps %xmm1, %xmm2, 0xe4 // upper 8 colors + movdqa %xmm2, %xmm0 + movdqa %xmm3, %xmm1 + + punpcklwd %xmm0, %xmm6 + punpcklwd %xmm1, %xmm6 + por %xmm0, %xmm4 + por %xmm1, %xmm5 + + punpckhwd %xmm2, %xmm6 + punpckhwd %xmm3, %xmm6 + + movdqa [%rsi], %xmm0 + movdqa [%rsi+32], %xmm1 + + movdqa %xmm5, %xmm7 + pand %xmm7, [%rsi+16] + pand %xmm5, [%rsi+48] + + por %xmm2, %xmm7 + por %xmm3, %xmm5 + + movdqa [%rsi+16], %xmm2 + movdqa [%rsi+48], %xmm3 + jmp WriteCLUT_T16_I4_CSM1_End + +WriteUnaligned: + // %rsi is offset by 2 + sub %rsi, 2 + + movdqa %xmm7, [%rip+s_clut16mask2] // saves lower 16 bits + + // have to save interlaced with the old data + movdqa %xmm4, [%rsi] + movdqa %xmm5, [%rsi+32] + movhlps %xmm1, %xmm0 + movlhps %xmm0, %xmm2 // lower 8 colors + + pand %xmm4, %xmm7 + pand %xmm5, %xmm7 + + shufps %xmm1, %xmm2, 0xe4 // upper 8 colors + movdqa %xmm2, %xmm0 + movdqa %xmm3, %xmm1 + + punpcklwd %xmm0, %xmm6 + punpcklwd %xmm1, %xmm6 + pslld %xmm0, 16 + pslld %xmm1, 16 + por %xmm0, %xmm4 + por %xmm1, %xmm5 + + punpckhwd %xmm2, %xmm6 + punpckhwd %xmm3, %xmm6 + pslld %xmm2, 16 + pslld %xmm3, 16 + + movdqa [%rsi], %xmm0 + movdqa [%rsi+32], %xmm1 + + movdqa %xmm5, %xmm7 + pand %xmm7, [%rsi+16] + pand %xmm5, [%rsi+48] + + por %xmm2, %xmm7 + por %xmm3, %xmm5 + + movdqa [%rsi+16], %xmm2 + movdqa [%rsi+48], %xmm3 +WriteCLUT_T16_I4_CSM1_End: + ret + +#endif diff --git a/plugins/zzogl-pg/opengl/x86-64.asm b/plugins/zzogl-pg/opengl/x86-64.asm new file mode 100644 index 0000000000..6d476dfc6d --- /dev/null +++ b/plugins/zzogl-pg/opengl/x86-64.asm @@ -0,0 +1,1091 @@ +; Copyright (C) 2003-2005 Gabest/zerofrog +; http:;;www.gabest.org +; +; 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, 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 GNU Make; see the file COPYING. If not, write to +; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +; http:;;www.gnu.org/copyleft/gpl.html +; +; + +extern s_clut16mask:ptr + + .code + +; mmx memcpy implementation, size has to be a multiple of 8 +; returns 0 is equal, nonzero value if not equal +; ~10 times faster than standard memcmp +; (zerofrog) +; u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +; rcx - src1 +; rdx - src2 +; r8d - cmpsize +memcmp_mmx proc public + cmp r8d, 32 + jl Done4 + + ; custom test first 8 to make sure things are ok + movq mm0, [rdx] + movq mm1, [rdx+8] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pand mm0, mm1 + movq mm2, [rdx+16] + pmovmskb eax, mm0 + movq mm3, [rdx+24] + + ; check if eq + cmp eax, 0ffh + je NextComp + mov eax, 1 + jmp Finish + +NextComp: + pcmpeqd mm2, [rcx+16] + pcmpeqd mm3, [rcx+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + sub r8d, 32 + add rdx, 32 + add rcx, 32 + + ; check if eq + cmp eax, 0ffh + je ContinueTest + mov eax, 1 + jmp Finish + + cmp r8d, 64 + jl Done8 + +Cmp8: + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + movq mm3, [rdx+24] + movq mm4, [rdx+32] + movq mm5, [rdx+40] + movq mm6, [rdx+48] + movq mm7, [rdx+56] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pcmpeqd mm2, [rcx+16] + pcmpeqd mm3, [rcx+24] + pand mm0, mm1 + pcmpeqd mm4, [rcx+32] + pand mm0, mm2 + pcmpeqd mm5, [rcx+40] + pand mm0, mm3 + pcmpeqd mm6, [rcx+48] + pand mm0, mm4 + pcmpeqd mm7, [rcx+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + ; check if eq + cmp eax, 0ffh + je Continue + mov eax, 1 + jmp Finish + +Continue: + sub r8d, 64 + add rdx, 64 + add rcx, 64 +ContinueTest: + cmp r8d, 64 + jge Cmp8 + +Done8: + test r8d, 020h + jz Done4 + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + movq mm3, [rdx+24] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pcmpeqd mm2, [rcx+16] + pcmpeqd mm3, [rcx+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub r8d, 32 + add rdx, 32 + add rcx, 32 + + ; check if eq + cmp eax, 0ffh + je Done4 + mov eax, 1 + jmp Finish + +Done4: + cmp r8d, 24 + jne Done2 + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pcmpeqd mm2, [rcx+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + ; check if eq + cmp eax, 0ffh + je Done + mov eax, 1 + jmp Finish + +Done2: + cmp r8d, 16 + jne Done1 + + movq mm0, [rdx] + movq mm1, [rdx+8] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + ; check if eq + cmp eax, 0ffh + je Done + mov eax, 1 + jmp Finish + +Done1: + cmp r8d, 8 + jne Done + + mov eax, [rdx] + mov rdx, [rdx+4] + cmp eax, [rcx] + je Next + mov eax, 1 + jmp Finish + +Next: + cmp rdx, [rcx+4] + je Done + mov eax, 1 + jmp Finish + +Done: + xor eax, eax + +Finish: + emms + ret + +memcmp_mmx endp + +; TestClutChangeMMX +; mov rdx, dst +; mov rcx, src +; mov r8d, entries +TestClutChangeMMX proc public + +Start: + movq mm0, [rdx] + movq mm1, [rdx+8] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+16] + + movq mm2, [rdx+16] + movq mm3, [rdx+24] + pcmpeqd mm2, [rcx+32] + pcmpeqd mm3, [rcx+48] + + pand mm0, mm1 + pand mm2, mm3 + movq mm4, [rdx+32] + movq mm5, [rdx+40] + pcmpeqd mm4, [rcx+8] + pcmpeqd mm5, [rcx+24] + + pand mm0, mm2 + pand mm4, mm5 + movq mm6, [rdx+48] + movq mm7, [rdx+56] + pcmpeqd mm6, [rcx+40] + pcmpeqd mm7, [rcx+56] + + pand mm0, mm4 + pand mm6, mm7 + pand mm0, mm6 + + pmovmskb eax, mm0 + cmp eax, 0ffh + je Continue + mov byte ptr [r9], 1 + jmp Return + +Continue: + cmp r8d, 16 + jle Return + + test r8d, 010h + jz AddRcx + sub rcx, 448 ; go back and down one column, +AddRcx: + add rcx, 256 ; go to the right block + + + jne Continue1 + add rcx, 256 ; skip whole block +Continue1: + add rdx, 64 + sub r8d, 16 + jmp Start + +Return: + emms + ret + +TestClutChangeMMX endp + +UnswizzleZ16Target proc public + pxor xmm7, xmm7 + +Z16Loop: + ;; unpack 64 bytes at a time + movdqa xmm0, [rdx] + movdqa xmm2, [rdx+16] + movdqa xmm4, [rdx+32] + movdqa xmm6, [rdx+48] + + movdqa xmm1, xmm0 + movdqa xmm3, xmm2 + movdqa xmm5, xmm4 + + punpcklwd xmm0, xmm7 + punpckhwd xmm1, xmm7 + punpcklwd xmm2, xmm7 + punpckhwd xmm3, xmm7 + + ;; start saving + movdqa [rcx], xmm0 + movdqa [rcx+16], xmm1 + + punpcklwd xmm4, xmm7 + punpckhwd xmm5, xmm7 + + movdqa [rcx+32], xmm2 + movdqa [rcx+48], xmm3 + + movdqa xmm0, xmm6 + punpcklwd xmm6, xmm7 + + movdqa [rcx+64], xmm4 + movdqa [rcx+80], xmm5 + + punpckhwd xmm0, xmm7 + + movdqa [rcx+96], xmm6 + movdqa [rcx+112], xmm0 + + add rdx, 64 + add rcx, 128 + sub r9d, 1 + jne Z16Loop + + ret +UnswizzleZ16Target endp + +; +; swizzling +; + +punpck macro op, sd0, sd2, s1, s3, d1, d3 + + movdqa @CatStr(xmm, %d1), @CatStr(xmm, %sd0) + pshufd @CatStr(xmm, %d3), @CatStr(xmm, %sd2), 0e4h + + @CatStr(punpckl, op) @CatStr(xmm, %sd0), @CatStr(xmm, %s1) + @CatStr(punpckh, op) @CatStr(xmm, %d1), @CatStr(xmm, %s1) + @CatStr(punpckl, op) @CatStr(xmm, %sd2), @CatStr(xmm, %s3) + @CatStr(punpckh, op) @CatStr(xmm, %d3), @CatStr(xmm, %s3) + + endm + +punpcknbl macro + + movdqa xmm4, xmm0 + pshufd xmm5, xmm1, 0e4h + + psllq xmm1, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm0, xmm7 + pandn xmm6, xmm1 + por xmm0, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm1, xmm4 + + movdqa xmm4, xmm2 + pshufd xmm5, xmm3, 0e4h + + psllq xmm3, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm2, xmm7 + pandn xmm6, xmm3 + por xmm2, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm3, xmm4 + + punpck bw, 0, 2, 1, 3, 4, 6 + + endm + +punpcknbh macro + + movdqa xmm12, xmm8 + pshufd xmm13, xmm9, 0e4h + + psllq xmm9, 4 + psrlq xmm12, 4 + + movdqa xmm14, xmm15 + pand xmm8, xmm15 + pandn xmm14, xmm9 + por xmm8, xmm14 + + movdqa xmm14, xmm15 + pand xmm12, xmm15 + pandn xmm14, xmm13 + por xmm12, xmm14 + + movdqa xmm9, xmm12 + + movdqa xmm12, xmm10 + pshufd xmm13, xmm11, 0e4h + + psllq xmm11, 4 + psrlq xmm12, 4 + + movdqa xmm14, xmm15 + pand xmm10, xmm15 + pandn xmm14, xmm11 + por xmm10, xmm14 + + movdqa xmm14, xmm15 + pand xmm12, xmm15 + pandn xmm14, xmm13 + por xmm12, xmm14 + + movdqa xmm11, xmm12 + + punpck bw, 8, 10, 9, 11, 12, 14 + + endm + +; +; SwizzleBlock32_sse2 +; + +SwizzleBlock32_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 4 + + cmp r9d, 0ffffffffh + jne SwizzleBlock32_sse2@WM + + align 16 +@@: + movdqa xmm0, [rsi] + movdqa xmm4, [rsi+16] + movdqa xmm1, [rsi+r8] + movdqa xmm5, [rsi+r8+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm2 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm6 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock32_sse2@WM: + + movd xmm7, r9d + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqa xmm0, [rsi] + movdqa xmm4, [rsi+16] + movdqa xmm1, [rsi+r8] + movdqa xmm5, [rsi+r8+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + movdqa xmm9, xmm7 + pshufd xmm11, xmm7, 0e4h + + pandn xmm3, [rdi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movdqa [rdi+16*0], xmm0 + + pandn xmm5, [rdi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movdqa [rdi+16*1], xmm2 + + pandn xmm9, [rdi+16*2] + pand xmm4, xmm7 + por xmm4, xmm9 + movdqa [rdi+16*2], xmm4 + + pandn xmm11, [rdi+16*3] + pand xmm6, xmm7 + por xmm6, xmm11 + movdqa [edi+16*3], xmm6 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock32_sse2 endp + +; +; SwizzleBlock16_sse2 +; + +SwizzleBlock16_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 4 + + align 16 +@@: + movdqa xmm0, [rsi] + movdqa xmm1, [rsi+16] + movdqa xmm2, [rsi+r8] + movdqa xmm3, [rsi+r8+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm1 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm5 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock16_sse2 endp + +; +; SwizzleBlock8 +; + +SwizzleBlock8_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov ecx, 2 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [rsi] + movdqa xmm2, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshufd xmm1, [rsi], 0b1h + pshufd xmm3, [rsi+r8], 0b1h + lea rsi, [rsi+r8*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm4 + movdqa [rdi+16*2], xmm1 + movdqa [rdi+16*3], xmm5 + + ; col 1, 3 + + pshufd xmm0, [rsi], 0b1h + pshufd xmm2, [rsi+r8], 0b1h + lea rsi, [rsi+r8*2] + + movdqa xmm1, [rsi] + movdqa xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movdqa [rdi+16*4], xmm0 + movdqa [rdi+16*5], xmm4 + movdqa [rdi+16*6], xmm1 + movdqa [rdi+16*7], xmm5 + + add edi, 128 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock8_sse2 endp + +; +; SwizzleBlock4 +; + +SwizzleBlock4_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 2 + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [rsi] + movdqa xmm2, [rsi+r8] + lea rsi, [rsi+r8*2] + + movdqa xmm1, [rsi] + movdqa xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknbl + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm1 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm3 + + ; col 1, 3 + + movdqa xmm0, [rsi] + movdqa xmm2, [rsi+r8] + lea esi, [rsi+r8*2] + + movdqa xmm1, [rsi] + movdqa xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknbl + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movdqa [rdi+16*4], xmm0 + movdqa [rdi+16*5], xmm1 + movdqa [rdi+16*6], xmm4 + movdqa [rdi+16*7], xmm3 + + add rdi, 128 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock4_sse2 endp + +; +; swizzling with unaligned reads +; + +; +; SwizzleBlock32u_sse2 +; + +SwizzleBlock32u_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 4 + + cmp r9d, 0ffffffffh + jne SwizzleBlock32u_sse2@WM + + align 16 +@@: + movdqu xmm0, [rsi] + movdqu xmm4, [rsi+16] + movdqu xmm1, [rsi+r8] + movdqu xmm5, [rsi+r8+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm2 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm6 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock32u_sse2@WM: + + movd xmm7, r9d + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqu xmm0, [rsi] + movdqu xmm4, [rsi+16] + movdqu xmm1, [rsi+r8] + movdqu xmm5, [rsi+r8+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + movdqa xmm9, xmm7 + pshufd xmm11, xmm7, 0e4h + + pandn xmm3, [rdi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movdqa [rdi+16*0], xmm0 + + pandn xmm5, [rdi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movdqa [rdi+16*1], xmm2 + + pandn xmm9, [rdi+16*2] + pand xmm4, xmm7 + por xmm4, xmm9 + movdqa [rdi+16*2], xmm4 + + pandn xmm11, [rdi+16*3] + pand xmm6, xmm7 + por xmm6, xmm11 + movdqa [edi+16*3], xmm6 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock32u_sse2 endp + +; +; SwizzleBlock16u_sse2 +; + +SwizzleBlock16u_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 4 + + align 16 +@@: + movdqu xmm0, [rsi] + movdqu xmm1, [rsi+16] + movdqu xmm2, [rsi+r8] + movdqu xmm3, [rsi+r8+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm1 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm5 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock16u_sse2 endp + +; +; SwizzleBlock8u +; + +SwizzleBlock8u_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov ecx, 2 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [rsi] + movdqu xmm2, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshufd xmm1, xmm0, 0b1h + pshufd xmm3, xmm2, 0b1h + lea rsi, [rsi+r8*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm4 + movdqa [rdi+16*2], xmm1 + movdqa [rdi+16*3], xmm5 + + ; col 1, 3 + + movdqu xmm0, [rsi] + movdqu xmm2, [rsi+r8] + pshufd xmm0, xmm0, 0b1h + pshufd xmm2, xmm2, 0b1h + lea rsi, [rsi+r8*2] + + movdqu xmm1, [rsi] + movdqu xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movdqa [rdi+16*4], xmm0 + movdqa [rdi+16*5], xmm4 + movdqa [rdi+16*6], xmm1 + movdqa [rdi+16*7], xmm5 + + add edi, 128 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock8u_sse2 endp + +; +; SwizzleBlock4u +; + +SwizzleBlock4u_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 2 + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [rsi] + movdqu xmm2, [rsi+r8] + lea rsi, [rsi+r8*2] + + movdqu xmm1, [rsi] + movdqu xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknbl + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm1 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm3 + + ; col 1, 3 + + movdqu xmm0, [rsi] + movdqu xmm2, [rsi+r8] + lea esi, [rsi+r8*2] + + movdqu xmm1, [rsi] + movdqu xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknbl + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movdqa [rdi+16*4], xmm0 + movdqa [rdi+16*5], xmm1 + movdqa [rdi+16*6], xmm4 + movdqa [rdi+16*7], xmm3 + + add rdi, 128 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock4u_sse2 endp + +WriteCLUT_T16_I4_CSM1_sse2 proc public + movdqa xmm0, XMMWORD PTR [rcx] + movdqa xmm1, XMMWORD PTR [rcx+16] + movdqa xmm2, XMMWORD PTR [rcx+32] + movdqa xmm3, XMMWORD PTR [rcx+48] + + ;; rearrange + pshuflw xmm0, xmm0, 088h + pshufhw xmm0, xmm0, 088h + pshuflw xmm1, xmm1, 088h + pshufhw xmm1, xmm1, 088h + pshuflw xmm2, xmm2, 088h + pshufhw xmm2, xmm2, 088h + pshuflw xmm3, xmm3, 088h + pshufhw xmm3, xmm3, 088h + + shufps xmm0, xmm1, 088h + shufps xmm2, xmm3, 088h + + pshufd xmm0, xmm0, 0d8h + pshufd xmm2, xmm2, 0d8h + + pxor xmm6, xmm6 + mov rax, offset s_clut16mask + + test rdx, 15 + jnz WriteUnaligned + + movdqa xmm7, XMMWORD PTR [rax] ;; saves upper 16 bits + + ;; have to save interlaced with the old data + movdqa xmm4, [rdx] + movdqa xmm5, [rdx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 ;; lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0e4h ;; upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + + movdqa [rdx], xmm0 + movdqa [rdx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [rdx+16] + pand xmm5, [rdx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [rdx+16], xmm2 + movdqa [rdx+48], xmm3 + jmp WriteCLUT_T16_I4_CSM1_End + +WriteUnaligned: + ;; rdx is offset by 2 + sub rdx, 2 + + movdqa xmm7, XMMWORD PTR [rax+16] ;; saves lower 16 bits + + ;; have to save interlaced with the old data + movdqa xmm4, [rdx] + movdqa xmm5, [rdx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 ;; lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0e4h ;; upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + pslld xmm0, 16 + pslld xmm1, 16 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + pslld xmm2, 16 + pslld xmm3, 16 + + movdqa [rdx], xmm0 + movdqa [rdx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [rdx+16] + pand xmm5, [rdx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [rdx+16], xmm2 + movdqa [rdx+48], xmm3 +WriteCLUT_T16_I4_CSM1_End: + ret + +WriteCLUT_T16_I4_CSM1_sse2 endp + +end \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/x86.cpp b/plugins/zzogl-pg/opengl/x86.cpp new file mode 100644 index 0000000000..17ecda32f1 --- /dev/null +++ b/plugins/zzogl-pg/opengl/x86.cpp @@ -0,0 +1,719 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 Gabest/zerofrog@gmail.com + * http://www.gabest.org + * + * 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, 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GS.h" +#include "Mem.h" +#include "x86.h" + +#if defined(ZEROGS_SSE2) && (defined(_WIN32)||defined(__x86_64__)) +#include +#include +#endif + +// swizzling + +void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + + if(WriteMask == 0xffffffff) + { + for(int j = 0; j < 8; j++, d += 8, src += srcpitch) + for(int i = 0; i < 8; i++) + ((u32*)dst)[d[i]] = ((u32*)src)[i]; + } + else + { + for(int j = 0; j < 8; j++, d += 8, src += srcpitch) + for(int i = 0; i < 8; i++) + ((u32*)dst)[d[i]] = (((u32*)dst)[d[i]] & ~WriteMask) | (((u32*)src)[i] & WriteMask); + } +} + + +void __fastcall SwizzleBlock24_c(u8* dst, u8* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + + if(WriteMask == 0x00ffffff) + { + for(int j = 0; j < 8; j++, d += 8, src += srcpitch) + for(int i = 0; i < 8; i++) + ((u32*)dst)[d[i]] = ((u32*)src)[i]; + } + else + { + for(int j = 0; j < 8; j++, d += 8, src += srcpitch) + for(int i = 0; i < 8; i++) + ((u32*)dst)[d[i]] = (((u32*)dst)[d[i]] & ~WriteMask) | (((u32*)src)[i] & WriteMask); + } +} + +void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch) +{ + u32* d = &g_columnTable16[0][0]; + + for(int j = 0; j < 8; j++, d += 16, src += srcpitch) + for(int i = 0; i < 16; i++) + ((u16*)dst)[d[i]] = ((u16*)src)[i]; +} + +void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch) +{ + u32* d = &g_columnTable8[0][0]; + + for(int j = 0; j < 16; j++, d += 16, src += srcpitch) + for(int i = 0; i < 16; i++) + dst[d[i]] = src[i]; +} + +void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch) +{ + u32* d = &g_columnTable4[0][0]; + + for(int j = 0; j < 16; j++, d += 32, src += srcpitch) + { + for(int i = 0; i < 32; i++) + { + u32 addr = d[i]; + u8 c = (src[i>>1] >> ((i&1) << 2)) & 0x0f; + u32 shift = (addr&1) << 2; + dst[addr >> 1] = (dst[addr >> 1] & (0xf0 >> shift)) | (c << shift); + } + } +} + +#define _FrameSwizzleBlock(type, transfer, transfer16, incsrc) \ +/* FrameSwizzleBlock32 */ \ +void __fastcall FrameSwizzleBlock32##type##c(u32* dst, u32* src, int srcpitch, u32 WriteMask) \ +{ \ + u32* d = &g_columnTable32[0][0]; \ + \ + if( WriteMask == 0xffffffff ) { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + dst[d[j]] = (transfer); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + dst[d[j]] = ((transfer)&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ +} \ +\ +void __fastcall FrameSwizzleBlock24##type##c(u32* dst, u32* src, int srcpitch, u32 WriteMask) \ +{ \ + u32* d = &g_columnTable32[0][0]; \ + \ + if( WriteMask == 0xffffffff ) { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + dst[d[j]] = (transfer); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + dst[d[j]] = ((transfer)&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ +} \ +\ +/* FrameSwizzleBlock16 */ \ +void __fastcall FrameSwizzleBlock16##type##c(u16* dst, u32* src, int srcpitch, u32 WriteMask) \ +{ \ + u32* d = &g_columnTable16[0][0]; \ + \ + if( WriteMask == 0xffff ) { \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + u32 temp = (transfer); \ + dst[d[j]] = RGBA32to16(temp); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + u32 temp = (transfer); \ + u32 dsrc = RGBA32to16(temp); \ + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ +} \ +\ +/* Frame16SwizzleBlock32 */ \ +void __fastcall Frame16SwizzleBlock32##type##c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask) \ +{ \ + u32* d = &g_columnTable32[0][0]; \ +\ + if( WriteMask == 0xffffffff ) { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + dst[d[j]] = Float16ToARGB(dsrc16); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + u32 dsrc = Float16ToARGB(dsrc16); \ + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + } \ +\ +/* Frame16SwizzleBlock32Z */ \ +void __fastcall Frame16SwizzleBlock32Z##type##c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask) \ +{ \ + u32* d = &g_columnTable32[0][0]; \ + if( WriteMask == 0xffffffff ) { /* breaks KH text if not checked */ \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + dst[d[j]] = Float16ToARGB_Z(dsrc16); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + u32 dsrc = Float16ToARGB_Z(dsrc16); \ + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + } \ + \ + /* Frame16SwizzleBlock16 */ \ +void __fastcall Frame16SwizzleBlock16##type##c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask) \ +{ \ + u32* d = &g_columnTable16[0][0]; \ + \ + if( (WriteMask&0xfff8f8f8) == 0xfff8f8f8) { \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + dst[d[j]] = Float16ToARGB16(dsrc16); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + u32 dsrc = Float16ToARGB16(dsrc16); \ + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + } \ + \ + /* Frame16SwizzleBlock16Z */ \ +void __fastcall Frame16SwizzleBlock16Z##type##c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask) \ +{ \ + u32* d = &g_columnTable16[0][0]; \ + \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + dst[d[j]] = Float16ToARGB16_Z(dsrc16); \ + } \ + src += srcpitch << incsrc; \ + } \ +} \ + +_FrameSwizzleBlock(_, src[j], src[j], 0); +_FrameSwizzleBlock(A2_, (src[2*j]+src[2*j+1])>>1, src[2*j], 0); +_FrameSwizzleBlock(A4_, (src[2*j]+src[2*j+1]+src[2*j+srcpitch]+src[2*j+srcpitch+1])>>2, src[2*j], 1); + +#ifdef ZEROGS_SSE2 + +//void __fastcall WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32* clut) +//{ +// __asm { +// mov eax, vm +// mov ecx, clut +// mov edx, 8 +// } +// +//Extract32x2: +// __asm { +// movdqa xmm0, qword ptr [eax] +// movdqa xmm1, qword ptr [eax+16] +// movdqa xmm2, qword ptr [eax+32] +// movdqa xmm3, qword ptr [eax+48] +// +// // rearrange +// pshuflw xmm0, xmm0, 0xd8 +// pshufhw xmm0, xmm0, 0xd8 +// pshuflw xmm1, xmm1, 0xd8 +// pshufhw xmm1, xmm1, 0xd8 +// pshuflw xmm2, xmm2, 0xd8 +// pshufhw xmm2, xmm2, 0xd8 +// pshuflw xmm3, xmm3, 0xd8 +// pshufhw xmm3, xmm3, 0xd8 +// +// movdqa xmm4, xmm0 +// movdqa xmm6, xmm2 +// +// shufps xmm0, xmm1, 0x88 +// shufps xmm2, xmm3, 0x88 +// +// shufps xmm4, xmm1, 0xdd +// shufps xmm6, xmm3, 0xdd +// +// pshufd xmm0, xmm0, 0xd8 +// pshufd xmm2, xmm2, 0xd8 +// pshufd xmm4, xmm4, 0xd8 +// pshufd xmm6, xmm6, 0xd8 +// +// // left column +// movhlps xmm1, xmm0 +// movlhps xmm0, xmm2 +// //movdqa xmm7, [ecx] +// +// movdqa [ecx], xmm0 +// shufps xmm1, xmm2, 0xe4 +// movdqa [ecx+16], xmm1 +// +// // right column +// movhlps xmm3, xmm4 +// movlhps xmm4, xmm6 +// movdqa [ecx+32], xmm4 +// shufps xmm3, xmm6, 0xe4 +// movdqa [ecx+48], xmm3 +// +// add eax, 16*4 +// add ecx, 16*8 +// sub edx, 1 +// cmp edx, 0 +// jne Extract32x2 +// } +//} + +#if (defined(_WIN32)||defined(__x86_64__)) + +extern "C" void __fastcall WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut) +{ + __m128i* src = (__m128i*)vm; + __m128i* dst = (__m128i*)clut; + + for(int j = 0; j < 64; j += 32, src += 32, dst += 32) + { + for(int i = 0; i < 16; i += 4) + { + __m128i r0 = _mm_load_si128(&src[i+0]); + __m128i r1 = _mm_load_si128(&src[i+1]); + __m128i r2 = _mm_load_si128(&src[i+2]); + __m128i r3 = _mm_load_si128(&src[i+3]); + + _mm_store_si128(&dst[i*2+0], _mm_unpacklo_epi64(r0, r1)); + _mm_store_si128(&dst[i*2+1], _mm_unpacklo_epi64(r2, r3)); + _mm_store_si128(&dst[i*2+2], _mm_unpackhi_epi64(r0, r1)); + _mm_store_si128(&dst[i*2+3], _mm_unpackhi_epi64(r2, r3)); + + __m128i r4 = _mm_load_si128(&src[i+0+16]); + __m128i r5 = _mm_load_si128(&src[i+1+16]); + __m128i r6 = _mm_load_si128(&src[i+2+16]); + __m128i r7 = _mm_load_si128(&src[i+3+16]); + + _mm_store_si128(&dst[i*2+4], _mm_unpacklo_epi64(r4, r5)); + _mm_store_si128(&dst[i*2+5], _mm_unpacklo_epi64(r6, r7)); + _mm_store_si128(&dst[i*2+6], _mm_unpackhi_epi64(r4, r5)); + _mm_store_si128(&dst[i*2+7], _mm_unpackhi_epi64(r6, r7)); + } + } +} + +extern "C" void __fastcall WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut) +{ + __m128i* src = (__m128i*)vm; + __m128i* dst = (__m128i*)clut; + + __m128i r0 = _mm_load_si128(&src[0]); + __m128i r1 = _mm_load_si128(&src[1]); + __m128i r2 = _mm_load_si128(&src[2]); + __m128i r3 = _mm_load_si128(&src[3]); + + _mm_store_si128(&dst[0], _mm_unpacklo_epi64(r0, r1)); + _mm_store_si128(&dst[1], _mm_unpacklo_epi64(r2, r3)); + _mm_store_si128(&dst[2], _mm_unpackhi_epi64(r0, r1)); + _mm_store_si128(&dst[3], _mm_unpackhi_epi64(r2, r3)); +} +#endif + +#if defined(_MSC_VER) + +extern "C" { +PCSX2_ALIGNED16(int s_clut16mask2[4]) = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; +PCSX2_ALIGNED16(int s_clut16mask[8]) = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, + 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}; +} + +#if !defined(__x86_64__) + +extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut) +{ + __asm { + mov eax, vm + mov ecx, clut + movdqa xmm0, qword ptr [eax] + movdqa xmm1, qword ptr [eax+16] + movdqa xmm2, qword ptr [eax+32] + movdqa xmm3, qword ptr [eax+48] + + // rearrange + pshuflw xmm0, xmm0, 0x88 + pshufhw xmm0, xmm0, 0x88 + pshuflw xmm1, xmm1, 0x88 + pshufhw xmm1, xmm1, 0x88 + pshuflw xmm2, xmm2, 0x88 + pshufhw xmm2, xmm2, 0x88 + pshuflw xmm3, xmm3, 0x88 + pshufhw xmm3, xmm3, 0x88 + + shufps xmm0, xmm1, 0x88 + shufps xmm2, xmm3, 0x88 + + pshufd xmm0, xmm0, 0xd8 + pshufd xmm2, xmm2, 0xd8 + + pxor xmm6, xmm6 + + test ecx, 15 + jnz WriteUnaligned + + movdqa xmm7, s_clut16mask // saves upper 16 bits + + // have to save interlaced with the old data + movdqa xmm4, [ecx] + movdqa xmm5, [ecx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 // lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0xe4 // upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + + movdqa [ecx], xmm0 + movdqa [ecx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [ecx+16] + pand xmm5, [ecx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [ecx+16], xmm2 + movdqa [ecx+48], xmm3 + jmp End + +WriteUnaligned: + // ecx is offset by 2 + sub ecx, 2 + + movdqa xmm7, s_clut16mask2 // saves lower 16 bits + + // have to save interlaced with the old data + movdqa xmm4, [ecx] + movdqa xmm5, [ecx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 // lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0xe4 // upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + pslld xmm0, 16 + pslld xmm1, 16 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + pslld xmm2, 16 + pslld xmm3, 16 + + movdqa [ecx], xmm0 + movdqa [ecx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [ecx+16] + pand xmm5, [ecx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [ecx+16], xmm2 + movdqa [ecx+48], xmm3 +End: + } +} +#endif // __x86_64__ +#endif // _MSC_VER + +#endif // ZEROGS_SSE2 + +void __fastcall WriteCLUT_T16_I8_CSM1_c(u32* _vm, u32* _clut) +{ + const static u32 map[] = + { + 0, 2, 8, 10, 16, 18, 24, 26, + 4, 6, 12, 14, 20, 22, 28, 30, + 1, 3, 9, 11, 17, 19, 25, 27, + 5, 7, 13, 15, 21, 23, 29, 31 + }; + + u16* vm = (u16*)_vm; + u16* clut = (u16*)_clut; + + int left = ((u32)(uptr)clut&2) ? 512 : 512-(((u32)(uptr)clut)&0x3ff)/2; + + for(int j = 0; j < 8; j++, vm += 32, clut += 64, left -= 32) + { + if(left == 32) { + assert( left == 32 ); + for(int i = 0; i < 16; i++) + clut[2*i] = vm[map[i]]; + + clut = (u16*)((uptr)clut & ~0x3ff) + 1; + + for(int i = 16; i < 32; i++) + clut[2*i] = vm[map[i]]; + } + else { + if( left == 0 ) { + clut = (u16*)((uptr)clut & ~0x3ff) + 1; + left = -1; + } + + for(int i = 0; i < 32; i++) + clut[2*i] = vm[map[i]]; + } + } +} + +void __fastcall WriteCLUT_T32_I8_CSM1_c(u32* vm, u32* clut) +{ + u64* src = (u64*)vm; + u64* dst = (u64*)clut; + + for(int j = 0; j < 2; j++, src += 32) { + for(int i = 0; i < 4; i++, dst+=16, src+=8) + { + dst[0] = src[0]; + dst[1] = src[2]; + dst[2] = src[4]; + dst[3] = src[6]; + dst[4] = src[1]; + dst[5] = src[3]; + dst[6] = src[5]; + dst[7] = src[7]; + + dst[8] = src[32]; + dst[9] = src[32+2]; + dst[10] = src[32+4]; + dst[11] = src[32+6]; + dst[12] = src[32+1]; + dst[13] = src[32+3]; + dst[14] = src[32+5]; + dst[15] = src[32+7]; + } + } +} + +void __fastcall WriteCLUT_T16_I4_CSM1_c(u32* _vm, u32* _clut) +{ + u16* dst = (u16*)_clut; + u16* src = (u16*)_vm; + + dst[0] = src[0]; dst[2] = src[2]; + dst[4] = src[8]; dst[6] = src[10]; + dst[8] = src[16]; dst[10] = src[18]; + dst[12] = src[24]; dst[14] = src[26]; + dst[16] = src[4]; dst[18] = src[6]; + dst[20] = src[12]; dst[22] = src[14]; + dst[24] = src[20]; dst[26] = src[22]; + dst[28] = src[28]; dst[30] = src[30]; +} + +void __fastcall WriteCLUT_T32_I4_CSM1_c(u32* vm, u32* clut) +{ + u64* src = (u64*)vm; + u64* dst = (u64*)clut; + + dst[0] = src[0]; + dst[1] = src[2]; + dst[2] = src[4]; + dst[3] = src[6]; + dst[4] = src[1]; + dst[5] = src[3]; + dst[6] = src[5]; + dst[7] = src[7]; +} + +void SSE2_UnswizzleZ16Target( u16* dst, u16* src, int iters ) { + +#if defined(_MSC_VER) +# if defined(__x86_64__) + UnswizzleZ16Target(dst, src, iters); +# else + __asm { + mov edx, iters + pxor xmm7, xmm7 + mov eax, dst + mov ecx, src + +Z16Loop: + // unpack 64 bytes at a time + movdqa xmm0, [ecx] + movdqa xmm2, [ecx+16] + movdqa xmm4, [ecx+32] + movdqa xmm6, [ecx+48] + + movdqa xmm1, xmm0 + movdqa xmm3, xmm2 + movdqa xmm5, xmm4 + + punpcklwd xmm0, xmm7 + punpckhwd xmm1, xmm7 + punpcklwd xmm2, xmm7 + punpckhwd xmm3, xmm7 + + // start saving + movdqa [eax], xmm0 + movdqa [eax+16], xmm1 + + punpcklwd xmm4, xmm7 + punpckhwd xmm5, xmm7 + + movdqa [eax+32], xmm2 + movdqa [eax+48], xmm3 + + movdqa xmm0, xmm6 + punpcklwd xmm6, xmm7 + + movdqa [eax+64], xmm4 + movdqa [eax+80], xmm5 + + punpckhwd xmm0, xmm7 + + movdqa [eax+96], xmm6 + movdqa [eax+112], xmm0 + + add ecx, 64 + add eax, 128 + sub edx, 1 + jne Z16Loop + } +# endif // __x86_64__ +#else // _MSC_VER + + __asm__(".intel_syntax\n" + "pxor %%xmm7, %%xmm7\n" + + "Z16Loop:\n" + // unpack 64 bytes at a time + "movdqa %%xmm0, [%0]\n" + "movdqa %%xmm2, [%0+16]\n" + "movdqa %%xmm4, [%0+32]\n" + "movdqa %%xmm6, [%0+48]\n" + + "movdqa %%xmm1, %%xmm0\n" + "movdqa %%xmm3, %%xmm2\n" + "movdqa %%xmm5, %%xmm4\n" + + "punpcklwd %%xmm0, %%xmm7\n" + "punpckhwd %%xmm1, %%xmm7\n" + "punpcklwd %%xmm2, %%xmm7\n" + "punpckhwd %%xmm3, %%xmm7\n" + + // start saving + "movdqa [%1], %%xmm0\n" + "movdqa [%1+16], %%xmm1\n" + + "punpcklwd %%xmm4, %%xmm7\n" + "punpckhwd %%xmm5, %%xmm7\n" + + "movdqa [%1+32], %%xmm2\n" + "movdqa [%1+48], %%xmm3\n" + + "movdqa %%xmm0, %%xmm6\n" + "punpcklwd %%xmm6, %%xmm7\n" + + "movdqa [%1+64], %%xmm4\n" + "movdqa [%1+80], %%xmm5\n" + + "punpckhwd %%xmm0, %%xmm7\n" + + "movdqa [%1+96], %%xmm6\n" + "movdqa [%1+112], %%xmm0\n" + + "add %0, 64\n" + "add %1, 128\n" + "sub %2, 1\n" + "jne Z16Loop\n" + ".att_syntax\n" : "=r"(src), "=r"(dst), "=r"(iters) : "0"(src), "1"(dst), "2"(iters) + ); +#endif // _MSC_VER +} + diff --git a/plugins/zzogl-pg/opengl/x86.h b/plugins/zzogl-pg/opengl/x86.h new file mode 100644 index 0000000000..e78fa47996 --- /dev/null +++ b/plugins/zzogl-pg/opengl/x86.h @@ -0,0 +1,190 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 Gabest/zerofrog@gmail.com + * http://www.gabest.org + * + * 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, 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#ifndef ZEROGS_X86 +#define ZEROGS_X86 + +#include "GS.h" + +extern "C" void __fastcall SwizzleBlock32_sse2(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff); +extern "C" void __fastcall SwizzleBlock16_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock8_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock4_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock32u_sse2(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff); +extern "C" void __fastcall SwizzleBlock16u_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock8u_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock4u_sse2(u8* dst, u8* src, int srcpitch); + +// frame swizzling + +// no AA +extern "C" void __fastcall FrameSwizzleBlock32_sse2(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall FrameSwizzleBlock16_sse2(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32Z_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16Z_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +// AA 2x +extern "C" void __fastcall FrameSwizzleBlock32A2_sse2(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall FrameSwizzleBlock16A2_sse2(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32A2_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32ZA2_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16A2_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16ZA2_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +// AA 4x +extern "C" void __fastcall FrameSwizzleBlock32A4_sse2(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall FrameSwizzleBlock16A4_sse2(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32A4_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32ZA4_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16A4_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16ZA4_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +extern void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff); +extern void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch); +extern void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch); +extern void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch); + +// no AA +extern void __fastcall FrameSwizzleBlock32_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock24_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock16_c(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32Z_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16Z_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +// AA 2x +extern void __fastcall FrameSwizzleBlock32A2_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock24A2_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock16A2_c(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32A2_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32ZA2_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16A2_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16ZA2_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +// AA 4x +extern void __fastcall FrameSwizzleBlock32A4_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock24A4_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock16A4_c(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32A4_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32ZA4_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16A4_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16ZA4_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +extern void __fastcall SwizzleColumn32_c(int y, u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff); +extern void __fastcall SwizzleColumn16_c(int y, u8* dst, u8* src, int srcpitch); +extern void __fastcall SwizzleColumn8_c(int y, u8* dst, u8* src, int srcpitch); +extern void __fastcall SwizzleColumn4_c(int y, u8* dst, u8* src, int srcpitch); + +extern "C" void __fastcall WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32* clut); +extern "C" void __fastcall WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut); +extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut); +extern "C" void __fastcall WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut); +extern void __fastcall WriteCLUT_T16_I8_CSM1_c(u32* vm, u32* clut); +extern void __fastcall WriteCLUT_T32_I8_CSM1_c(u32* vm, u32* clut); + +extern void __fastcall WriteCLUT_T16_I4_CSM1_c(u32* vm, u32* clut); +extern void __fastcall WriteCLUT_T32_I4_CSM1_c(u32* vm, u32* clut); + +extern void SSE2_UnswizzleZ16Target( u16* dst, u16* src, int iters ); + +#ifdef ZEROGS_SSE2 + +#define SwizzleBlock32 SwizzleBlock32_sse2 +#define SwizzleBlock16 SwizzleBlock16_sse2 +#define SwizzleBlock8 SwizzleBlock8_sse2 +#define SwizzleBlock4 SwizzleBlock4_sse2 +#define SwizzleBlock32u SwizzleBlock32u_sse2 +#define SwizzleBlock16u SwizzleBlock16u_sse2 +#define SwizzleBlock8u SwizzleBlock8u_sse2 +#define SwizzleBlock4u SwizzleBlock4u_sse2 + +#define FrameSwizzleBlock32 FrameSwizzleBlock32_c +#define FrameSwizzleBlock24 FrameSwizzleBlock24_c +#define FrameSwizzleBlock16 FrameSwizzleBlock16_c +#define Frame16SwizzleBlock32 Frame16SwizzleBlock32_c +#define Frame16SwizzleBlock32Z Frame16SwizzleBlock32Z_c +#define Frame16SwizzleBlock16 Frame16SwizzleBlock16_c +#define Frame16SwizzleBlock16Z Frame16SwizzleBlock16Z_c + +#define FrameSwizzleBlock32A2 FrameSwizzleBlock32A2_c +#define FrameSwizzleBlock24A2 FrameSwizzleBlock24A2_c +#define FrameSwizzleBlock16A2 FrameSwizzleBlock16A2_c +#define Frame16SwizzleBlock32A2 Frame16SwizzleBlock32A2_c +#define Frame16SwizzleBlock32ZA2 Frame16SwizzleBlock32ZA2_c +#define Frame16SwizzleBlock16A2 Frame16SwizzleBlock16A2_c +#define Frame16SwizzleBlock16ZA2 Frame16SwizzleBlock16ZA2_c + +#define FrameSwizzleBlock32A4 FrameSwizzleBlock32A4_c +#define FrameSwizzleBlock24A4 FrameSwizzleBlock24A4_c +#define FrameSwizzleBlock16A4 FrameSwizzleBlock16A4_c +#define Frame16SwizzleBlock32A4 Frame16SwizzleBlock32A4_c +#define Frame16SwizzleBlock32ZA4 Frame16SwizzleBlock32ZA4_c +#define Frame16SwizzleBlock16A4 Frame16SwizzleBlock16A4_c +#define Frame16SwizzleBlock16ZA4 Frame16SwizzleBlock16ZA4_c + +#define WriteCLUT_T16_I8_CSM1 WriteCLUT_T16_I8_CSM1_sse2 +#define WriteCLUT_T32_I8_CSM1 WriteCLUT_T32_I8_CSM1_sse2 +#define WriteCLUT_T16_I4_CSM1 WriteCLUT_T16_I4_CSM1_sse2 +#define WriteCLUT_T32_I4_CSM1 WriteCLUT_T32_I4_CSM1_sse2 + +#else + +#define SwizzleBlock32 SwizzleBlock32_c +#define SwizzleBlock16 SwizzleBlock16_c +#define SwizzleBlock8 SwizzleBlock8_c +#define SwizzleBlock4 SwizzleBlock4_c +#define SwizzleBlock32u SwizzleBlock32_c +#define SwizzleBlock16u SwizzleBlock16_c +#define SwizzleBlock8u SwizzleBlock8_c +#define SwizzleBlock4u SwizzleBlock4_c + +#define FrameSwizzleBlock32 FrameSwizzleBlock32_c +#define FrameSwizzleBlock16 FrameSwizzleBlock16_c +#define Frame16SwizzleBlock32 Frame16SwizzleBlock32_c +#define Frame16SwizzleBlock32Z Frame16SwizzleBlock32Z_c +#define Frame16SwizzleBlock16 Frame16SwizzleBlock16_c +#define Frame16SwizzleBlock16Z Frame16SwizzleBlock16Z_c + +#define FrameSwizzleBlock32A2 FrameSwizzleBlock32A2_c +#define FrameSwizzleBlock16A2 FrameSwizzleBlock16A2_c +#define Frame16SwizzleBlock32A2 Frame16SwizzleBlock32A2_c +#define Frame16SwizzleBlock32ZA2 Frame16SwizzleBlock32ZA2_c +#define Frame16SwizzleBlock16A2 Frame16SwizzleBlock16A2_c +#define Frame16SwizzleBlock16ZA2 Frame16SwizzleBlock16ZA2_c + +#define FrameSwizzleBlock32A4 FrameSwizzleBlock32A4_c +#define FrameSwizzleBlock16A4 FrameSwizzleBlock16A4_c +#define Frame16SwizzleBlock32A4 Frame16SwizzleBlock32A4_c +#define Frame16SwizzleBlock32ZA4 Frame16SwizzleBlock32ZA4_c +#define Frame16SwizzleBlock16A4 Frame16SwizzleBlock16A4_c +#define Frame16SwizzleBlock16ZA4 Frame16SwizzleBlock16ZA4_c + +#define WriteCLUT_T16_I8_CSM1 WriteCLUT_T16_I8_CSM1_c +#define WriteCLUT_T32_I8_CSM1 WriteCLUT_T32_I8_CSM1_c +#define WriteCLUT_T16_I4_CSM1 WriteCLUT_T16_I4_CSM1_c +#define WriteCLUT_T32_I4_CSM1 WriteCLUT_T32_I4_CSM1_c + +#endif + +#endif diff --git a/plugins/zzogl-pg/opengl/zerogs.cpp b/plugins/zzogl-pg/opengl/zerogs.cpp new file mode 100644 index 0000000000..96d29c3771 --- /dev/null +++ b/plugins/zzogl-pg/opengl/zerogs.cpp @@ -0,0 +1,1178 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//-------------------------- Includes +#if defined(_WIN32) +# include +//# include +# include "resource.h" +#endif + +#include + +#include +#include +#include +#include + +#include "GS.h" +#include "Mem.h" +#include "x86.h" +#include "zerogs.h" +#include "zpipe.h" + +#include "ZeroGSShaders/zerogsshaders.h" +#include "targets.h" + +//----------------------- Defines + +//-------------------------- Typedefs +typedef void (APIENTRYP _PFNSWAPINTERVAL) (int); + +//-------------------------- Extern variables +using namespace ZeroGS; + +extern u32 g_nGenVars, g_nTexVars, g_nAlphaVars, g_nResolve; +extern char *libraryName; +extern int g_nFrame, g_nRealFrame; + +//-------------------------- Variables + +#ifdef _WIN32 +HDC hDC=NULL; // Private GDI Device Context +HGLRC hRC=NULL; // Permanent Rendering Context +#endif + +bool g_bIsLost = 0; // ZZ + +BOOL g_bMakeSnapshot = 0; +string strSnapshot; + +CGprogram g_vsprog = 0, g_psprog = 0; // 2 -- ZZ +// AVI Capture +int s_avicapturing = 0; + +inline u32 FtoDW(float f) { return (*((u32*)&f)); } + +int g_nDepthUpdateCount = 0; + +// Consts +const GLenum primtype[8] = { GL_POINTS, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, 0xffffffff }; +static const int PRIMMASK = 0x0e; // for now ignore 0x10 (AA) + +PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL; +PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL; +PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL; +PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL; +PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT = NULL; +PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL; +PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL; +PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL; +PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL; +PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; +PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; +PFNGLDRAWBUFFERSPROC glDrawBuffers = NULL; + +///////////////////// +// graphics resources +CGparameter g_vparamPosXY[2] = {0}, g_fparamFogColor = 0; + +map mapShaderResources; + +bool s_bTexFlush = FALSE; +int s_nLastResolveReset = 0; +int s_nWireframeCount = 0; +int s_nResolveCounts[30] = {0}; // resolve counts for last 30 frames + +//////////////////// +// State parameters +CGcontext g_cgcontext; +int nBackbufferWidth, nBackbufferHeight; + +u8* g_pbyGSMemory = NULL; // 4Mb GS system mem +u8* g_pbyGSClut = NULL; // ZZ + +namespace ZeroGS +{ + Vector g_vdepth, vlogz; + +// = Vector( 255.0 /256.0f, 255.0/65536.0f, 255.0f/(65535.0f*256.0f), 1.0f/(65536.0f*65536.0f)); +// Vector g_vdepth = Vector( 65536.0f*65536.0f, 256.0f*65536.0f, 65536.0f, 256.0f); + + extern CRangeManager s_RangeMngr; // manages overwritten memory + GLenum GetRenderTargetFormat() { return GetRenderFormat()==RFT_byte8?4:g_internalRGBAFloat16Fmt; } + + // returns the first and last addresses aligned to a page that cover + void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw); + +// bool LoadEffects(); +// bool LoadExtraEffects(); +// FRAGMENTSHADER* LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed); + + int s_nNewWidth = -1, s_nNewHeight = -1; + void ChangeDeviceSize(int nNewWidth, int nNewHeight); + + void ProcessMessages(); + void RenderCustom(float fAlpha); // intro anim + + struct MESSAGE + { + MESSAGE() {} + MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; } + char str[255]; + u32 dwTimeStamp; + }; + + static list listMsgs; + + /////////////////////// + // Method Prototypes // + /////////////////////// + + void KickPoint(); + void KickLine(); + void KickTriangle(); + void KickTriangleFan(); + void KickSprite(); + void KickDummy(); + + void ResolveInRange(int start, int end); + + void ExtWrite(); + + void ResetRenderTarget(int index) { + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+index, GL_TEXTURE_RECTANGLE_NV, 0, 0 ); + } + + DrawFn drawfn[8] = { KickDummy, KickDummy, KickDummy, KickDummy, + KickDummy, KickDummy, KickDummy, KickDummy }; + +}; // end namespace + +// does one time only initializing/destruction +class ZeroGSInit +{ +public: + ZeroGSInit() { + // clear + g_pbyGSMemory = (u8*)_aligned_malloc(0x00410000, 1024); // leave some room for out of range accesses (saves on the checks) + memset(g_pbyGSMemory, 0, 0x00410000); + + g_pbyGSClut = (u8*)_aligned_malloc(256*8, 1024); // need 512 alignment! + memset(g_pbyGSClut, 0, 256*8); + +#ifndef _WIN32 + memset(&GLWin, 0, sizeof(GLWin)); +#endif + } + ~ZeroGSInit() { + _aligned_free(g_pbyGSMemory); g_pbyGSMemory = NULL; + _aligned_free(g_pbyGSClut); g_pbyGSClut = NULL; + } +}; + +static ZeroGSInit s_ZeroGSInit; + +#ifndef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT +#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 +#endif + +void ZeroGS::HandleGLError() +{ + FUNCLOG + // check the error status of this framebuffer */ + GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + + // if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort + if( error != 0 ) { + int w, h; + GLint fmt; + glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt); + glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w); + glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &h); + + switch(error) + { + case GL_FRAMEBUFFER_COMPLETE_EXT: + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + ERROR_LOG("Error! missing a required image/buffer attachment!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + ERROR_LOG("Error! has no images/buffers attached!\n"); + break; +// case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: +// ERROR_LOG("Error! has an image/buffer attached in multiple locations!\n"); +// break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + ERROR_LOG("Error! has mismatched image/buffer dimensions!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: + ERROR_LOG("Error! colorbuffer attachments have different types!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: + ERROR_LOG("Error! trying to draw to non-attached color buffer!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: + ERROR_LOG("Error! trying to read from a non-attached color buffer!\n"); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ERROR_LOG("Error! format is not supported by current graphics card/driver!\n"); + break; + default: + ERROR_LOG("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT() for %s!\n"); + break; + } + } +} + + +void ZeroGS::GSStateReset() +{ + FUNCLOG + icurctx = -1; + + for(int i = 0; i < 2; ++i) { + vb[i].Destroy(); + memset(&vb[i], 0, sizeof(ZeroGS::VB)); + + vb[i].tex0.tw = 1; + vb[i].tex0.th = 1; + vb[i].scissor.x1 = 639; + vb[i].scissor.y1 = 479; + vb[i].tex0.tbw = 64; + vb[i].Init(VB_BUFFERSIZE); + } + + s_RangeMngr.Clear(); + g_MemTargs.Destroy(); + s_RTs.Destroy(); + s_DepthRTs.Destroy(); + s_BitwiseTextures.Destroy(); + + vb[0].ictx = 0; + vb[1].ictx = 1; +} + +void ZeroGS::AddMessage(const char* pstr, u32 ms) +{ + FUNCLOG + listMsgs.push_back(MESSAGE(pstr, timeGetTime()+ms)); +} + +void ZeroGS::DrawText(const char* pstr, int left, int top, u32 color) +{ + FUNCLOG + cgGLDisableProfile(cgvProf); + cgGLDisableProfile(cgfProf); + + glColor3f(((color>>16)&0xff)/255.0f, ((color>>8)&0xff)/255.0f, (color&0xff)/255.0f); + + font_p->printString(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight,0); + cgGLEnableProfile(cgvProf); + cgGLEnableProfile(cgfProf); +} + +void ZeroGS::ChangeWindowSize(int nNewWidth, int nNewHeight) +{ + FUNCLOG + nBackbufferWidth = nNewWidth > 16 ? nNewWidth : 16; + nBackbufferHeight = nNewHeight > 16 ? nNewHeight : 16; + + if( !(conf.options & GSOPTION_FULLSCREEN) ) { + conf.width = nNewWidth; + conf.height = nNewHeight; + //SaveConfig(); + } +} + +void ZeroGS::SetChangeDeviceSize(int nNewWidth, int nNewHeight) +{ + FUNCLOG + s_nNewWidth = nNewWidth; + s_nNewHeight = nNewHeight; + + if( !(conf.options & GSOPTION_FULLSCREEN) ) { + conf.width = nNewWidth; + conf.height = nNewHeight; + //SaveConfig(); + } +} + +void ZeroGS::Reset() +{ + FUNCLOG + s_RTs.ResolveAll(); + s_DepthRTs.ResolveAll(); + + vb[0].nCount = 0; + vb[1].nCount = 0; + + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + s_nLastResolveReset = 0; + + icurctx = -1; + g_vsprog = g_psprog = 0; + + GSStateReset(); + Destroy(0); + + drawfn[0] = KickDummy; + drawfn[1] = KickDummy; + drawfn[2] = KickDummy; + drawfn[3] = KickDummy; + drawfn[4] = KickDummy; + drawfn[5] = KickDummy; + drawfn[6] = KickDummy; + drawfn[7] = KickDummy; +} + +void ZeroGS::ChangeDeviceSize(int nNewWidth, int nNewHeight) +{ + FUNCLOG + int oldscreen = s_nFullscreen; + + int oldwidth = nBackbufferWidth, oldheight = nBackbufferHeight; + if( !Create(nNewWidth&~7, nNewHeight&~7) ) { + ERROR_LOG("Failed to recreate, changing to old\n"); + if( !Create(oldwidth, oldheight) ) { + SysMessage("failed to create dev, exiting...\n"); + exit(0); + } + } + + for(int i = 0; i < 2; ++i) { + vb[i].bNeedFrameCheck = vb[i].bNeedZCheck = 1; + vb[i].CheckFrame(0); + } + + assert( vb[0].pBufferData != NULL && vb[1].pBufferData != NULL ); +} + + +void ZeroGS::SetNegAA(int mode) { + FUNCLOG + // need to flush all targets + s_RTs.ResolveAll(); + s_RTs.Destroy(); + s_DepthRTs.ResolveAll(); + s_DepthRTs.Destroy(); + + s_AAz = s_AAw = 0; // This is code for x0, x2, x4, x8 and x16 anti-aliasing. + if (mode > 0) + { + s_AAz = (mode+1) / 2; // ( 1, 0 ) ; ( 1, 1 ) -- it's used as binary shift, so x << s_AAz, y << s_AAw + s_AAw = mode / 2; + } + + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + s_nLastResolveReset = 0; + + vb[0].prndr = NULL; vb[0].pdepth = NULL; vb[0].bNeedFrameCheck = 1; vb[0].bNeedZCheck = 1; + vb[1].prndr = NULL; vb[1].pdepth = NULL; vb[1].bNeedFrameCheck = 1; vb[1].bNeedZCheck = 1; +} + +void ZeroGS::SetAA(int mode) +{ + FUNCLOG + float f; + + // need to flush all targets + s_RTs.ResolveAll(); + s_RTs.Destroy(); + s_DepthRTs.ResolveAll(); + s_DepthRTs.Destroy(); + + s_AAx = s_AAy = 0; // This is code for x0, x2, x4, x8 and x16 anti-aliasing. + if (mode > 0) + { + s_AAx = (mode+1) / 2; // ( 1, 0 ) ; ( 1, 1 ) ; ( 2, 1 ) ; ( 2, 2 ) -- it's used as binary shift, so x >> s_AAx, y >> s_AAy + s_AAy = mode / 2; + } + + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + s_nLastResolveReset = 0; + + vb[0].prndr = NULL; vb[0].pdepth = NULL; vb[0].bNeedFrameCheck = 1; vb[0].bNeedZCheck = 1; + vb[1].prndr = NULL; vb[1].pdepth = NULL; vb[1].bNeedFrameCheck = 1; vb[1].bNeedZCheck = 1; + + f = mode > 0 ? 2.0f : 1.0f; + glPointSize(f); +} + +void ZeroGS::Prim(){ + FUNCLOG + if( g_bIsLost ) + return; + + VB& curvb = vb[prim->ctxt]; + + if( curvb.CheckPrim() ){ + Flush(prim->ctxt); + } + curvb.curprim._val = prim->_val; + + // flush the other pipe if sharing the same buffer +// if( vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp && vb[!prim->ctxt].nCount > 0 ) +// { +// assert( vb[prim->ctxt].nCount == 0 ); +// Flush(!prim->ctxt); +// } + + curvb.curprim.prim = prim->prim; +} + +void ZeroGS::ProcessMessages() +{ + FUNCLOG + if( listMsgs.size() > 0 ) { + int left = 25, top = 15; + list::iterator it = listMsgs.begin(); + + while( it != listMsgs.end() ) { + DrawText(it->str, left+1, top+1, 0xff000000); + DrawText(it->str, left, top, 0xffffff30); + top += 15; + + if( (int)(it->dwTimeStamp - timeGetTime()) < 0 ) + it = listMsgs.erase(it); + else ++it; + } + } +} + +void ZeroGS::RenderCustom(float fAlpha) +{ + FUNCLOG + GL_REPORT_ERROR(); + + fAlpha = 1; + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer + + DisableAllgl() ; + SetShaderCaller("RenderCustom"); + + glViewport(0, 0, nBackbufferWidth, nBackbufferHeight); + + // play custom animation + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + + // tex coords + Vector v = Vector(1/32767.0f, 1/32767.0f, 0, 0); + ZZcgSetParameter4fv(pvsBitBlt.sBitBltPos, v, "g_fBitBltPos"); + v.x = (float)nLogoWidth; + v.y = (float)nLogoHeight; + ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, v, "g_fBitBltTex"); + + v.x = v.y = v.z = v.w = fAlpha; + ZZcgSetParameter4fv(ppsBaseTexture.sOneColor, v, "g_fOneColor"); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + // inside vhDCb[0]'s target area, so render that region only + cgGLSetTextureParameter(ppsBaseTexture.sFinal, ptexLogo); + cgGLEnableTextureParameter(ppsBaseTexture.sFinal); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + SETVERTEXSHADER(pvsBitBlt.prog); + SETPIXELSHADER(ppsBaseTexture.prog); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + // restore + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + ProcessMessages(); + +#ifdef _WIN32 + SwapBuffers(hDC); +#else + glXSwapBuffers(GLWin.dpy, GLWin.win); +#endif + + glEnable(GL_SCISSOR_TEST); + glEnable(GL_STENCIL_TEST); + + vb[0].bSyncVars = 0; + vb[1].bSyncVars = 0; + + GL_REPORT_ERROR(); + GLint status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + assert( status == GL_FRAMEBUFFER_COMPLETE_EXT || status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT ); +} + +void ZeroGS::Restore() +{ + FUNCLOG + if( !g_bIsLost ) + return; + + //if( SUCCEEDED(pd3dDevice->Reset(&d3dpp)) ) { + g_bIsLost = 0; + // handle lost states + ZeroGS::ChangeDeviceSize(nBackbufferWidth, nBackbufferHeight); + //} +} + +////////////////////////// +// Internal Definitions // +////////////////////////// + + +__forceinline void MOVZ(VertexGPU *p, u32 gsz, const VB& curvb) +{ + p->z = curvb.zprimmask==0xffff?min((u32)0xffff, gsz):gsz; +} + +__forceinline void MOVFOG(VertexGPU *p, Vertex gsf) +{ + p->f = ((s16)(gsf).f<<7)|0x7f; +} + + +int Values[100]={0,}; +__forceinline void SET_VERTEX(VertexGPU *p, int Index, const VB& curvb) +{ + int index = Index; + + p->x = (((int)gs.gsvertex[index].x - curvb.offset.x)>>1)&0xffff; + p->y = (((int)gs.gsvertex[index].y - curvb.offset.y)>>1)&0xffff; + + /*x = ((int)gs.gsvertex[index].x - curvb.offset.x); + y = ((int)gs.gsvertex[index].y - curvb.offset.y); + p.x = (x&0x7fff) | (x < 0 ? 0x8000 : 0); + p.y = (y&0x7fff) | (y < 0 ? 0x8000 : 0);*/ + + p->f = ((s16)gs.gsvertex[index].f<<7)|0x7f; + MOVZ(p, gs.gsvertex[index].z, curvb); + p->rgba = prim->iip ? gs.gsvertex[index].rgba : gs.rgba; + +// This code is somehow icorrect +// if ((gs.texa.aem) && ((p->rgba & 0xffffff ) == 0)) +// p->rgba = 0; + + if (g_GameSettings & GAME_TEXAHACK) { + u32 B = (( p->rgba & 0xfe000000 ) >> 1) + + (0x01000000 * curvb.fba.fba) ; + p->rgba = ( p->rgba & 0xffffff ) + B; + } + + if (prim->tme ) + { + if( prim->fst ) + { + p->s = (float)gs.gsvertex[index].u * fiTexWidth[prim->ctxt]; + p->t = (float)gs.gsvertex[index].v * fiTexHeight[prim->ctxt]; + p->q = 1; + } + else + { + p->s = gs.gsvertex[index].s; + p->t = gs.gsvertex[index].t; + p->q = gs.gsvertex[index].q; + } + } +} + +#define OUTPUT_VERT(fn, vert, id) { \ + fn("%c%d(%d): xyzf=(%4d,%4d,0x%x,%3d), rgba=0x%8.8x, stq = (%2.5f,%2.5f,%2.5f)\n", id==0?'*':' ', id, prim->prim, vert.x/8, vert.y/8, vert.z, vert.f/128, \ + vert.rgba, Clamp(vert.s, -10, 10), Clamp(vert.t, -10, 10), Clamp(vert.q, -10, 10)); \ +} \ + +void ZeroGS::KickPoint() +{ + FUNCLOG + assert( gs.primC >= 1 ); + + VB& curvb = vb[prim->ctxt]; + if (curvb.bNeedTexCheck) curvb.FlushTexData(); + + if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp)) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(1); + + int last = (gs.primIndex+2)%ARRAY_SIZE(gs.gsvertex); + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + SET_VERTEX(&p[0], last, curvb); + curvb.nCount++; + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); +#endif +} + +void ZeroGS::KickLine() +{ + FUNCLOG + assert( gs.primC >= 2 ); + VB& curvb = vb[prim->ctxt]; + if( curvb.bNeedTexCheck ) + curvb.FlushTexData(); + + if( vb[!prim->ctxt].nCount > 0 && vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp ) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(2); + + int next = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + int last = (gs.primIndex+2)%ARRAY_SIZE(gs.gsvertex); + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + SET_VERTEX(&p[0], next, curvb); + SET_VERTEX(&p[1], last, curvb); + + curvb.nCount += 2; + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); + OUTPUT_VERT(PRIM_LOG, p[1], 1); +#endif +} + +void ZeroGS::KickTriangle() +{ + FUNCLOG + assert( gs.primC >= 3 ); + VB& curvb = vb[prim->ctxt]; + if (curvb.bNeedTexCheck) curvb.FlushTexData(); + + if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp)) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(3); + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + SET_VERTEX(&p[0], 0, curvb); + SET_VERTEX(&p[1], 1, curvb); + SET_VERTEX(&p[2], 2, curvb); + + curvb.nCount += 3; + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); + OUTPUT_VERT(PRIM_LOG, p[1], 1); + OUTPUT_VERT(PRIM_LOG, p[2], 2); +#endif +} + +void ZeroGS::KickTriangleFan() +{ + FUNCLOG + assert( gs.primC >= 3 ); + VB& curvb = vb[prim->ctxt]; + if (curvb.bNeedTexCheck) curvb.FlushTexData(); + + if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp)) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(3); + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + SET_VERTEX(&p[0], 0, curvb); + SET_VERTEX(&p[1], 1, curvb); + SET_VERTEX(&p[2], 2, curvb); + + curvb.nCount += 3; + + // add 1 to skip the first vertex + if (gs.primIndex == gs.nTriFanVert) + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); + OUTPUT_VERT(PRIM_LOG, p[1], 1); + OUTPUT_VERT(PRIM_LOG, p[2], 2); +#endif +} + +__forceinline void SetKickVertex(VertexGPU *p, Vertex v, int next, const VB& curvb) +{ + SET_VERTEX(p, next, curvb); + MOVZ(p, v.z, curvb); + MOVFOG(p, v); +} + +void ZeroGS::KickSprite() +{ + FUNCLOG + assert( gs.primC >= 2 ); + VB& curvb = vb[prim->ctxt]; + + if (curvb.bNeedTexCheck) curvb.FlushTexData(); + + if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp)) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(6); + + int next = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + int last = (gs.primIndex+2)%ARRAY_SIZE(gs.gsvertex); + + // sprite is too small and AA shows lines (tek4) + if ( s_AAx ) + { + gs.gsvertex[last].x += 4; + if( s_AAy ) gs.gsvertex[last].y += 4; + } + + // might be bad sprite (KH dialog text) + //if( gs.gsvertex[next].x == gs.gsvertex[last].x || gs.gsvertex[next].y == gs.gsvertex[last].y ) + //return; + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + + SetKickVertex(&p[0], gs.gsvertex[last], next, curvb); + SetKickVertex(&p[3], gs.gsvertex[last], next, curvb); + SetKickVertex(&p[1], gs.gsvertex[last], last, curvb); + SetKickVertex(&p[4], gs.gsvertex[last], last, curvb); + SetKickVertex(&p[2], gs.gsvertex[last], next, curvb); + + p[2].s = p[1].s; + p[2].x = p[1].x; + + SetKickVertex(&p[5], gs.gsvertex[last], last, curvb); + p[5].s = p[0].s; + p[5].x = p[0].x; + + curvb.nCount += 6; + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); + OUTPUT_VERT(PRIM_LOG, p[1], 1); +#endif +} + +void ZeroGS::KickDummy() +{ + FUNCLOG + //GREG_LOG("Kicking bad primitive: %.8x\n", *(u32*)prim); +} + +void ZeroGS::SetFogColor(u32 fog) +{ + FUNCLOG + if( 1||gs.fogcol != fog ) { + gs.fogcol = fog; + + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + if( !g_bIsLost ) { + SetShaderCaller("SetFogColor"); + Vector v; + + // set it immediately + v.x = (gs.fogcol&0xff)/255.0f; + v.y = ((gs.fogcol>>8)&0xff)/255.0f; + v.z = ((gs.fogcol>>16)&0xff)/255.0f; + ZZcgSetParameter4fv(g_fparamFogColor, v, "g_fParamFogColor"); + } + } +} + +void ZeroGS::ExtWrite() +{ + FUNCLOG + WARN_LOG("ExtWrite\n"); + + // use local DISPFB, EXTDATA, EXTBUF, and PMODE +// int bpp, start, end; +// tex0Info texframe; + +// bpp = 4; +// if( texframe.psm == PSMT16S ) bpp = 3; +// else if (PSMT_ISHALF(texframe.psm)) bpp = 2; +// +// // get the start and end addresses of the buffer +// GetRectMemAddress(start, end, texframe.psm, 0, 0, texframe.tw, texframe.th, texframe.tbp0, texframe.tbw); +} + +//////////// +// Caches // +//////////// +#ifdef __x86_64__ +extern "C" void TestClutChangeMMX(void* src, void* dst, int entries, void* pret); +#endif + +bool ZeroGS::CheckChangeInClut(u32 highdword, u32 psm) +{ + FUNCLOG + int cld = ZZOglGet_cld_TexBits(highdword); + int cbp = ZZOglGet_cbp_TexBits(highdword); + + // processing the CLUT after tex0/2 are written + switch(cld) { + case 0: return false; + case 1: break; // Seems to rarely not be 1. + // note sure about changing cbp[0,1] + case 4: return gs.cbp[0] != cbp; + case 5: return gs.cbp[1] != cbp; + + // default: load + default: break; + } + + int cpsm = ZZOglGet_cpsm_TexBits(highdword); + int csm = ZZOglGet_csm_TexBits(highdword); + + if( cpsm > 1 || csm ) + // don't support 16bit for now + return true; + + int csa = ZZOglGet_csa_TexBits(highdword); + + int entries = PSMT_IS8CLUT(psm) ? 256 : 16; + + u64* src = (u64*)(g_pbyGSMemory + cbp*256); + u64* dst = (u64*)(g_pbyGSClut+64*csa); + + bool bRet = false; + + // do a fast test with MMX +#ifdef _MSC_VER + +#ifdef __x86_64__ + TestClutChangeMMX(dst, src, entries, &bRet); +#else + int storeebx; + __asm { + mov storeebx, ebx + mov edx, dst + mov ecx, src + mov ebx, entries + +Start: + movq mm0, [edx] + movq mm1, [edx+8] + pcmpeqd mm0, [ecx] + pcmpeqd mm1, [ecx+16] + + movq mm2, [edx+16] + movq mm3, [edx+24] + pcmpeqd mm2, [ecx+32] + pcmpeqd mm3, [ecx+48] + + pand mm0, mm1 + pand mm2, mm3 + movq mm4, [edx+32] + movq mm5, [edx+40] + pcmpeqd mm4, [ecx+8] + pcmpeqd mm5, [ecx+24] + + pand mm0, mm2 + pand mm4, mm5 + movq mm6, [edx+48] + movq mm7, [edx+56] + pcmpeqd mm6, [ecx+40] + pcmpeqd mm7, [ecx+56] + + pand mm0, mm4 + pand mm6, mm7 + pand mm0, mm6 + + pmovmskb eax, mm0 + cmp eax, 0xff + je Continue + mov bRet, 1 + jmp Return + +Continue: + cmp ebx, 16 + jle Return + + test ebx, 0x10 + jz AddEcx + sub ecx, 448 // go back and down one column, +AddEcx: + add ecx, 256 // go to the right block + + + jne Continue1 + add ecx, 256 // skip whole block +Continue1: + add edx, 64 + sub ebx, 16 + jmp Start + +Return: + emms + mov ebx, storeebx + } +#endif // __x86_64__ + +#else // linux + +#ifdef __x86_64__ + __asm__( + ".intel_syntax\n" +"Start:\n" + "movq %%mm0, [%%rcx]\n" + "movq %%mm1, [%%rcx+8]\n" + "pcmpeqd %%mm0, [%%rdx]\n" + "pcmpeqd %%mm1, [%%rdx+16]\n" + "movq %%mm2, [%%rcx+16]\n" + "movq %%mm3, [%%rcx+24]\n" + "pcmpeqd %%mm2, [%%rdx+32]\n" + "pcmpeqd %%mm3, [%%rdx+48]\n" + "pand %%mm0, %%mm1\n" + "pand %%mm2, %%mm3\n" + "movq %%mm4, [%%rcx+32]\n" + "movq %%mm5, [%%rcx+40]\n" + "pcmpeqd %%mm4, [%%rdx+8]\n" + "pcmpeqd %%mm5, [%%rdx+24]\n" + "pand %%mm0, %%mm2\n" + "pand %%mm4, %%mm5\n" + "movq %%mm6, [%%rcx+48]\n" + "movq %%mm7, [%%rcx+56]\n" + "pcmpeqd %%mm6, [%%rdx+40]\n" + "pcmpeqd %%mm7, [%%rdx+56]\n" + "pand %%mm0, %%mm4\n" + "pand %%mm6, %%mm7\n" + "pand %%mm0, %%mm6\n" + "pmovmskb %%eax, %%mm0\n" + "cmp %%eax, 0xff\n" + "je Continue\n" + ".att_syntax\n" + "movb $1, %0\n" + ".intel_syntax\n" + "jmp Return\n" +"Continue:\n" + "cmp %%rbx, 16\n" + "jle Return\n" + "test %%rbx, 0x10\n" + "jz AddRcx\n" + "sub %%rdx, 448\n" // go back and down one column +"AddRcx:\n" + "add %%rdx, 256\n" // go to the right block + "cmp %%rbx, 0x90\n" + "jne Continue1\n" + "add %%rdx, 256\n" // skip whole block +"Continue1:\n" + "add %%rcx, 64\n" + "sub %%rbx, 16\n" + "jmp Start\n" +"Return:\n" + "emms\n" + ".att_syntax\n" : "=m"(bRet) : "c"(dst), "d"(src), "b"(entries) : "rax", "memory"); +#else + // do a fast test with MMX + __asm__( + ".intel_syntax\n" +"Start:\n" + "movq %%mm0, [%%ecx]\n" + "movq %%mm1, [%%ecx+8]\n" + "pcmpeqd %%mm0, [%%edx]\n" + "pcmpeqd %%mm1, [%%edx+16]\n" + "movq %%mm2, [%%ecx+16]\n" + "movq %%mm3, [%%ecx+24]\n" + "pcmpeqd %%mm2, [%%edx+32]\n" + "pcmpeqd %%mm3, [%%edx+48]\n" + "pand %%mm0, %%mm1\n" + "pand %%mm2, %%mm3\n" + "movq %%mm4, [%%ecx+32]\n" + "movq %%mm5, [%%ecx+40]\n" + "pcmpeqd %%mm4, [%%edx+8]\n" + "pcmpeqd %%mm5, [%%edx+24]\n" + "pand %%mm0, %%mm2\n" + "pand %%mm4, %%mm5\n" + "movq %%mm6, [%%ecx+48]\n" + "movq %%mm7, [%%ecx+56]\n" + "pcmpeqd %%mm6, [%%edx+40]\n" + "pcmpeqd %%mm7, [%%edx+56]\n" + "pand %%mm0, %%mm4\n" + "pand %%mm6, %%mm7\n" + "pand %%mm0, %%mm6\n" + "pmovmskb %%eax, %%mm0\n" + "cmp %%eax, 0xff\n" + "je Continue\n" + ".att_syntax\n" + "movb $1, %0\n" + ".intel_syntax\n" + "jmp Return\n" +"Continue:\n" + "cmp %%ebx, 16\n" + "jle Return\n" + "test %%ebx, 0x10\n" + "jz AddEcx\n" + "sub %%edx, 448\n" // go back and down one column +"AddEcx:\n" + "add %%edx, 256\n" // go to the right block + "cmp %%ebx, 0x90\n" + "jne Continue1\n" + "add %%edx, 256\n" // skip whole block +"Continue1:\n" + "add %%ecx, 64\n" + "sub %%ebx, 16\n" + "jmp Start\n" +"Return:\n" + "emms\n" + ".att_syntax\n" : "=m"(bRet) : "c"(dst), "d"(src), "b"(entries) : "eax", "memory"); +#endif // __x86_64__ + +#endif // _WIN32 + + return bRet; +} + +void ZeroGS::texClutWrite(int ctx) +{ + FUNCLOG + s_bTexFlush = 0; + if( g_bIsLost ) + return; + + tex0Info& tex0 = vb[ctx].tex0; + assert( PSMT_ISCLUT(tex0.psm) ); + // processing the CLUT after tex0/2 are written + switch(tex0.cld) { + case 0: return; + case 1: break; // tex0.cld is usually 1. + case 2: gs.cbp[0] = tex0.cbp; break; + case 3: gs.cbp[1] = tex0.cbp; break; + // not sure about changing cbp[0,1] + case 4: + if( gs.cbp[0] == tex0.cbp ) + return; + gs.cbp[0] = tex0.cbp; + break; + case 5: + if( gs.cbp[1] == tex0.cbp ) + return; + gs.cbp[1] = tex0.cbp; + break; + default: //DEBUG_LOG("cld isn't 0-5!"); + break; + } + + Flush(!ctx); + + int entries = PSMT_IS8CLUT(tex0.psm) ? 256 : 16; + + if (tex0.csm) + { + switch (tex0.cpsm) + { + // 16bit psm + // eggomania uses non16bit textures for csm2 + case PSMCT16: + { + u16* src = (u16*)g_pbyGSMemory + tex0.cbp*128; + u16 *dst = (u16*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0)); + + for (int i = 0; i < entries; ++i) + { + *dst = src[getPixelAddress16_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)]; + dst += 2; + + // check for wrapping + if (((u32)(uptr)dst & 0x3ff) == 0) dst = (u16*)(g_pbyGSClut+2); + } + break; + } + + case PSMCT16S: + { + u16* src = (u16*)g_pbyGSMemory + tex0.cbp*128; + u16 *dst = (u16*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0)); + + for (int i = 0; i < entries; ++i) + { + *dst = src[getPixelAddress16S_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)]; + dst += 2; + + // check for wrapping + if (((u32)(uptr)dst & 0x3ff) == 0) dst = (u16*)(g_pbyGSClut+2); + } + break; + } + + case PSMCT32: + case PSMCT24: + { + u32* src = (u32*)g_pbyGSMemory + tex0.cbp*64; + u32 *dst = (u32*)(g_pbyGSClut+64*tex0.csa); + + // check if address exceeds src + if( src+getPixelAddress32_0(gs.clut.cou+entries-1, gs.clut.cov, gs.clut.cbw) >= (u32*)g_pbyGSMemory + 0x00100000 ) + ERROR_LOG("texClutWrite out of bounds\n"); + else + for(int i = 0; i < entries; ++i) + { + *dst = src[getPixelAddress32_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)]; + dst++; + } + break; + } + + default: + { +#ifndef RELEASE_TO_PUBLIC + //DEBUG_LOG("unknown cpsm: %x (%x)\n", tex0.cpsm, tex0.psm); +#endif + break; + } + } + } + else + { + switch (tex0.cpsm) + { + case PSMCT24: + case PSMCT32: + if( entries == 16 ) + WriteCLUT_T32_I4_CSM1((u32*)(g_pbyGSMemory + tex0.cbp*256), (u32*)(g_pbyGSClut+64*tex0.csa)); + else + WriteCLUT_T32_I8_CSM1((u32*)(g_pbyGSMemory + tex0.cbp*256), (u32*)(g_pbyGSClut+64*tex0.csa)); + break; + + default: + if( entries == 16 ) + WriteCLUT_T16_I4_CSM1((u32*)(g_pbyGSMemory + 256 * tex0.cbp), (u32*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0))); + else // sse2 for 256 is more complicated, so use regular + WriteCLUT_T16_I8_CSM1_c((u32*)(g_pbyGSMemory + 256 * tex0.cbp), (u32*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0))); + break; + + } + } +} + + diff --git a/plugins/zzogl-pg/opengl/zerogs.h b/plugins/zzogl-pg/opengl/zerogs.h new file mode 100644 index 0000000000..2ff8a46a93 --- /dev/null +++ b/plugins/zzogl-pg/opengl/zerogs.h @@ -0,0 +1,846 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ZEROGS__H +#define __ZEROGS__H + +#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union + +// ----------------------------- Includes +#include "PS2Etypes.h" +#include "PS2Edefs.h" + +#ifndef _WIN32 +// adding glew support instead of glXGetProcAddress (thanks to scaught) +# include +#endif + +// Need this before gl.h +#ifdef _WIN32 +# include +#endif + +#include +#include + +#ifndef _WIN32 +# include + inline void* wglGetProcAddress(const char* x) { + return (void*)glXGetProcAddress((const GLubyte*)x); + } +#else +# include "glprocs.h" +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "GS.h" +#include "rasterfont.h" // simple font + +using namespace std; +#include "ZeroGSShaders/zerogsshaders.h" + +// ----------------------- Defines +#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils +# define GL_DEPTH_STENCIL_EXT 0x84F9 +# define GL_UNSIGNED_INT_24_8_EXT 0x84FA +# define GL_DEPTH24_STENCIL8_EXT 0x88F0 +# define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 +#endif + +#define GL_STENCILFUNC(func, ref, mask) { \ + s_stencilfunc = func; \ + s_stencilref = ref; \ + s_stencilmask = mask; \ + glStencilFunc(func, ref, mask); \ +} + +#define GL_STENCILFUNC_SET() glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask) + +#ifndef SAFE_DELETE +# define SAFE_DELETE(x) if( (x) != NULL ) { delete (x); (x) = NULL; } +#endif +#ifndef SAFE_DELETE_ARRAY +# define SAFE_DELETE_ARRAY(x) if( (x) != NULL ) { delete[] (x); (x) = NULL; } +#endif +#ifndef SAFE_RELEASE +# define SAFE_RELEASE(x) if( (x) != NULL ) { (x)->Release(); (x) = NULL; } +#endif + +#define SAFE_RELEASE_PROG(x) { if( (x) != NULL ) { cgDestroyProgram(x); x = NULL; } } +#define SAFE_RELEASE_TEX(x) { if( (x) != 0 ) { glDeleteTextures(1, &(x)); x = 0; } } + +#define FORIT(it, v) for(it = (v).begin(); it != (v).end(); ++(it)) + +// sends a message to output window if assert fails +#define BMSG(x, str) { if( !(x) ) { GS_LOG(str); GS_LOG(str); } } +#define BMSG_RETURN(x, str) { if( !(x) ) { GS_LOG(str); GS_LOG(str); return; } } +#define BMSG_RETURNX(x, str, rtype) { if( !(x) ) { GS_LOG(str); GS_LOG(str); return (##rtype); } } +#define B(x) { if( !(x) ) { GS_LOG(_#x"\n"); GS_LOG(#x"\n"); } } +#define B_RETURN(x) { if( !(x) ) { ERROR_LOG("%s:%d: %s\n", __FILE__, (u32)__LINE__, #x); return; } } +#define B_RETURNX(x, rtype) { if( !(x) ) { ERROR_LOG("%s:%d: %s\n", __FILE__, (u32)__LINE__, #x); return (##rtype); } } +#define B_G(x, action) { if( !(x) ) { ERROR_LOG("%s:%d: %s\n", __FILE__, (u32)__LINE__, #x); action; } } + +#define GL_REPORT_ERROR() \ +{ \ + GLenum err = glGetError(); \ + if( err != GL_NO_ERROR ) \ + { \ + ERROR_LOG("%s:%d: gl error %s\n", __FILE__, (int)__LINE__, error_name(err)); \ + ZeroGS::HandleGLError(); \ + } \ +} + +#ifdef _DEBUG +# define GL_REPORT_ERRORD() \ +{ \ + GLenum err = glGetError(); \ + if( err != GL_NO_ERROR ) \ + { \ + ERROR_LOG("%s:%d: gl error %s\n", __FILE__, (int)__LINE__, error_name(err)); \ + ZeroGS::HandleGLError(); \ + } \ +} +#else +# define GL_REPORT_ERRORD() +#endif + +// sets the data stream +#define SET_STREAM() { \ + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)8); \ + glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12); \ + glTexCoordPointer(3, GL_FLOAT, sizeof(VertexGPU), (void*)16); \ + glVertexPointer(4, GL_SHORT, sizeof(VertexGPU), (void*)0); \ +} + +extern const char* ShaderCallerName; +extern const char* ShaderHandleName; + +inline void SetShaderCaller(const char* Name) { + ShaderCallerName = Name; +} + +inline void SetHandleName(const char* Name) { + ShaderHandleName = Name; +} + +extern void HandleCgError(CGcontext ctx, CGerror err, void* appdata); +extern void ZZcgSetParameter4fv(CGparameter param, const float* v, const char* name); + +#define SETVERTEXSHADER(prog) { \ + if( (prog) != g_vsprog ) { \ + cgGLBindProgram(prog); \ + g_vsprog = prog; \ + } \ +} \ + +#define SETPIXELSHADER(prog) { \ + if( (prog) != g_psprog ) { \ + cgGLBindProgram(prog); \ + g_psprog = prog; \ + } \ +} \ + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +//------------------------ Constants ---------------------- +#define VB_BUFFERSIZE 0x400 + +// Used in logaripmic Z-test, as (1-o(1))/log(MAX_U32). +const float g_filog32 = 0.999f / (32.0f * logf(2.0f)); + +//------------------------ Inlines ------------------------- + +inline const char *error_name(int err) { + switch (err) { + case GL_NO_ERROR: + return "GL_NO_ERROR"; + case GL_INVALID_ENUM: + return "GL_INVALID_ENUM"; + case GL_INVALID_VALUE: + return "GL_INVALID_VALUE"; + case GL_INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + case GL_STACK_OVERFLOW: + return "GL_STACK_OVERFLOW"; + case GL_STACK_UNDERFLOW: + return "GL_STACK_UNDERFLOW"; + case GL_OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + case GL_TABLE_TOO_LARGE: + return "GL_TABLE_TOO_LARGE"; + default: { + char *str; + sprintf(str, "Unknown error(0x%x)", err); + return str; + } + } +} + +// inline for extemely ofthen used sequence +// This is turning off all gl functions. Safe to do updates. +inline void +DisableAllgl () { + glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glDisable(GL_STENCIL_TEST); + glColorMask(1,1,1,1); +} + +// Calculate maximun height for target +inline int +get_maxheight(int fbp, int fbw, int psm) { + if (fbw == 0) return 0; + return ( ( ( 0x00100000 - 64 * fbp ) / fbw ) & ~0x1f ) << (PSMT_ISHALF(psm)) ; +} + +// Does psm need Alpha test with alpha expansion +inline int +nNeedAlpha(u8 psm) { + return (psm == PSMCT24 || psm == PSMCT16 || psm == PSMCT16S); +} + +// Get color storage model psm, that is important on flush stage. +inline u8 +GetTexCPSM(const tex0Info& tex) { + if (PSMT_ISCLUT(tex.psm)) + return tex.cpsm; + else + return tex.psm; +} + +//--------------------- Dummies + +#ifdef _WIN32 + extern void (__stdcall *zgsBlendEquationSeparateEXT)(GLenum, GLenum); + extern void (__stdcall *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum); +#else + extern void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum); + extern void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum); +#endif + +// ------------------------ Types ------------------------- +struct FRAGMENTSHADER +{ + FRAGMENTSHADER() : prog(0), sMemory(0), sFinal(0), sBitwiseANDX(0), sBitwiseANDY(0), sInterlace(0), sCLUT(0), sOneColor(0), sBitBltZ(0), + fTexAlpha2(0), fTexOffset(0), fTexDims(0), fTexBlock(0), fClampExts(0), fTexWrapMode(0), + fRealTexDims(0), fTestBlack(0), fPageOffset(0), fTexAlpha(0) {} + + CGprogram prog; + CGparameter sMemory, sFinal, sBitwiseANDX, sBitwiseANDY, sInterlace, sCLUT; + CGparameter sOneColor, sBitBltZ, sInvTexDims; + CGparameter fTexAlpha2, fTexOffset, fTexDims, fTexBlock, fClampExts, fTexWrapMode, fRealTexDims, fTestBlack, fPageOffset, fTexAlpha; + +#ifdef _DEBUG + string filename; +#endif +}; + +struct VERTEXSHADER +{ + VERTEXSHADER() : prog(0), sBitBltPos(0), sBitBltTex(0) {} + CGprogram prog; + CGparameter sBitBltPos, sBitBltTex, fBitBltTrans; // vertex shader constants +}; +// ------------------------ Variables ------------------------- +// all textures have this width +//#define GPU_TEXWIDTH 512 +extern int GPU_TEXWIDTH; +extern float g_fiGPU_TEXWIDTH; +#define MASKDIVISOR 0 +#define GPU_TEXMASKWIDTH (1024 >> MASKDIVISOR) // bitwise mask width for region repeat mode + +#ifdef _WIN32 +extern HDC hDC; // Private GDI Device Context +extern HGLRC hRC; // Permanent Rendering Context +#endif +extern bool g_bIsLost; // Context is lost -- could not draw + +extern u32 ptexBlocks; // holds information on block tiling +extern u32 ptexConv16to32; +extern u32 ptexBilinearBlocks; +extern u32 ptexConv32to16; +extern int g_MaxTexWidth, g_MaxTexHeight; +extern float g_fBlockMult; +extern BOOL g_bDisplayMsg; +extern BOOL g_bDisplayFPS; + +extern int g_nDepthBias; +extern BOOL g_bSaveFlushedFrame; +extern u8* s_lpShaderResources; +extern u32 g_SaveFrameNum; +extern int s_nWriteDepthCount; +extern int s_nWireframeCount; +extern int s_nWriteDestAlphaTest; + +////////////////////////// +// State parameters +extern float fiRendWidth, fiRendHeight; +extern int g_PrevBitwiseTexX, g_PrevBitwiseTexY; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY +extern bool s_bDestAlphaTest; +extern int s_ClutResolve; +extern int s_nLastResolveReset; +extern int g_nDepthUpdateCount; +extern int s_nResolveCounts[30]; // resolve counts for last 30 frames +extern int g_nDepthUsed; // ffx2 pal movies + +///////////////////// +// graphics resources +extern map mapGLExtensions; +extern map mapShaderResources; + +#ifdef DEVBUILD +extern char* EFFECT_NAME; +extern char* EFFECT_DIR; +extern u32 g_nGenVars, g_nTexVars, g_nAlphaVars, g_nResolve; +extern bool g_bSaveTrans, g_bUpdateEffect, g_bSaveTex, g_bSaveResolved; + +#endif + +extern RasterFont* font_p; +extern u32 s_uFramebuffer; +extern CGprofile cgvProf, cgfProf; +extern int g_nPixelShaderVer; +extern CGprogram pvs[16]; +extern FRAGMENTSHADER ppsRegular[4], ppsTexture[NUM_SHADERS]; +extern FRAGMENTSHADER ppsCRTC[2], ppsCRTC24[2], ppsCRTCTarg[2]; +extern GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT +extern u32 s_stencilfunc, s_stencilref, s_stencilmask; +extern GLenum s_drawbuffers[]; +extern bool s_bTexFlush; +extern bool s_bWriteDepth; + +extern int maxmin; +extern const GLenum primtype[8]; +extern u32 ptexLogo; +extern int nLogoWidth, nLogoHeight; +extern u32 s_ptexInterlace; // holds interlace fields +extern int s_nFullscreen; + +extern vector s_vecTempTextures; // temporary textures, released at the end of every frame +// global alpha blending settings +extern GLenum g_internalFloatFmt; +extern GLenum g_internalRGBAFloatFmt; +extern GLenum g_internalRGBAFloat16Fmt; + +extern CGprogram g_vsprog, g_psprog; +extern BOOL g_bMakeSnapshot; +extern string strSnapshot; +extern BOOL g_bCRTCBilinear; + +// AVI Capture +extern int s_aviinit; +extern int s_avicapturing; + +// don't change these values! +#define GAME_TEXTURETARGS 0x01 +#define GAME_AUTORESET 0x02 +#define GAME_INTERLACE2X 0x04 +#define GAME_TEXAHACK 0x08 // apply texa to non textured polys +#define GAME_NOTARGETRESOLVE 0x10 +#define GAME_EXACTCOLOR 0x20 +#define GAME_NOCOLORCLAMP 0x40 +#define GAME_FFXHACK 0x80 +#define GAME_NOALPHAFAIL 0x0100 +#define GAME_NODEPTHUPDATE 0x0200 +#define GAME_QUICKRESOLVE1 0x0400 +#define GAME_NOQUICKRESOLVE 0x0800 +#define GAME_NOTARGETCLUT 0x1000 // full 16 bit resolution +#define GAME_NOSTENCIL 0x2000 +#define GAME_VSSHACKOFF 0x4000 // vertical stripe syndrome +#define GAME_NODEPTHRESOLVE 0x8000 +#define GAME_FULL16BITRES 0x00010000 +#define GAME_RESOLVEPROMOTED 0x00020000 +#define GAME_FASTUPDATE 0x00040000 +#define GAME_NOALPHATEST 0x00080000 +#define GAME_DISABLEMRTDEPTH 0x00100000 +#define GAME_32BITTARGS 0x00200000 +#define GAME_PATH3HACK 0x00400000 +#define GAME_DOPARALLELCTX 0x00800000 // tries to parallelize both contexts so that render calls are reduced (xenosaga) + // makes the game faster, but can be buggy +#define GAME_XENOSPECHACK 0x01000000 // xenosaga specularity hack (ignore any zmask=1 draws) +#define GAME_PARTIALPOINTERS 0x02000000 // whenver the texture or render target are small, tries to look for bigger ones to read from +#define GAME_PARTIALDEPTH 0x04000000 // tries to save depth targets as much as possible across height changes +#define GAME_REGETHACK 0x08000000 // some sort of weirdness in ReGet() code +#define GAME_GUSTHACK 0x10000000 // Needed for Gustgames fast update. +#define GAME_NOLOGZ 0x20000000 // Intended for linux -- not logaripmic Z. + +#define USEALPHATESTING (!(g_GameSettings&GAME_NOALPHATEST)) + +extern int nBackbufferWidth, nBackbufferHeight; +extern u8* g_pbyGSMemory; +extern u8* g_pbyGSClut; // the temporary clut buffer +extern CGparameter g_vparamPosXY[2], g_fparamFogColor; + +namespace ZeroGS { + + typedef void (*DrawFn)(); + + enum RenderFormatType + { + RFT_byte8 = 0, // A8R8G8B8 + RFT_float16 = 1, // A32R32B32G32 + }; + + // managers render-to-texture targets + class CRenderTarget + { + public: + CRenderTarget(); + virtual ~CRenderTarget(); + + virtual bool Create(const frameInfo& frame); + virtual void Destroy(); + + // set the GPU_POSXY variable, scissor rect, and current render target + void SetTarget(int fbplocal, const Rect2& scissor, int context); + void SetViewport(); + + // copies/creates the feedback contents + inline void CreateFeedback() { + if( ptexFeedback == 0 || !(status&TS_FeedbackReady) ) + _CreateFeedback(); + } + + virtual void Resolve(); + virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range + virtual void Update(int context, CRenderTarget* pdepth); + virtual void ConvertTo32(); // converts a psm==2 target, to a psm==0 + virtual void ConvertTo16(); // converts a psm==0 target, to a psm==2 + + virtual bool IsDepth() { return false; } + void SetRenderTarget(int targ); + + void* psys; // system data used for comparison + u32 ptex; + + int fbp, fbw, fbh, fbhCalc; // if fbp is negative, virtual target (not mapped to any real addr) + int start, end; // in bytes + u32 lastused; // time stamp since last used + Vector vposxy; + + u32 fbm; + u16 status; + u8 psm; + u8 resv0; + Rect scissorrect; + + u8 created; // Check for object destruction/creating for r201. + + //int startresolve, endresolve; + u32 nUpdateTarg; // use this target to update the texture if non 0 (one time only) + + // this is optionally used when feedback effects are used (render target is used as a texture when rendering to itself) + u32 ptexFeedback; + + enum TargetStatus { + TS_Resolved = 1, + TS_NeedUpdate = 2, + TS_Virtual = 4, // currently not mapped to memory + TS_FeedbackReady = 8, // feedback effect is ready and doesn't need to be updated + TS_NeedConvert32 = 16, + TS_NeedConvert16 = 32, + }; + inline Vector DefaultBitBltPos() ; + inline Vector DefaultBitBltTex() ; + private: + void _CreateFeedback(); + inline bool InitialiseDefaultTexture ( u32 *p_ptr, int fbw, int fbh ) ; + }; + + // manages zbuffers + class CDepthTarget : public CRenderTarget + { + public: + CDepthTarget(); + virtual ~CDepthTarget(); + + virtual bool Create(const frameInfo& frame); + virtual void Destroy(); + + virtual void Resolve(); + virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range + virtual void Update(int context, CRenderTarget* prndr); + + virtual bool IsDepth() { return true; } + + void SetDepthStencilSurface(); + + u32 pdepth; // 24 bit, will contain the stencil buffer if possible + u32 pstencil; // if not 0, contains the stencil buffer + int icount; // internal counter + }; + + // manages contiguous chunks of memory (width is always 1024) + class CMemoryTarget + { + public: + struct TEXTURE + { + inline TEXTURE() : tex(0), memptr(NULL), ref(0) {} + inline ~TEXTURE() { glDeleteTextures(1, &tex); _aligned_free(memptr); } + u32 tex; + u8* memptr; // GPU memory used for comparison + int ref; + }; + + inline CMemoryTarget() : ptex(NULL), starty(0), height(0), realy(0), realheight(0), usedstamp(0), psm(0), cpsm(0), channels(0), clearminy(0), clearmaxy(0), validatecount(0) {} + + inline CMemoryTarget(const CMemoryTarget& r) { + ptex = r.ptex; + if( ptex != NULL ) ptex->ref++; + starty = r.starty; + height = r.height; + realy = r.realy; + realheight = r.realheight; + usedstamp = r.usedstamp; + psm = r.psm; + cpsm = r.cpsm; + clut = r.clut; + clearminy = r.clearminy; + clearmaxy = r.clearmaxy; + widthmult = r.widthmult; + channels = r.channels; + validatecount = r.validatecount; + fmt = r.fmt; + } + + ~CMemoryTarget() { Destroy(); } + + inline void Destroy() { + if( ptex != NULL && ptex->ref > 0 ) { + if( --ptex->ref <= 0 ) + delete ptex; + } + + ptex = NULL; + } + + // returns true if clut data is synced + bool ValidateClut(const tex0Info& tex0); + // returns true if tex data is synced + bool ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex); + + // realy is offset in pixels from start of valid region + // so texture in memory is [realy,starty+height] + // valid texture is [starty,starty+height] + // offset in mem [starty-realy, height] + TEXTURE* ptex; // can be 16bit + + int starty, height; // assert(starty >= realy) + int realy, realheight; // this is never touched once allocated + u32 usedstamp; + u8 psm, cpsm; // texture and clut format. For psm, only 16bit/32bit differentiation matters + + u32 fmt; + + int widthmult; + int channels; + int clearminy, clearmaxy; // when maxy > 0, need to check for clearing + + int validatecount; // count how many times has been validated, if too many, destroy + + vector clut; // if nonzero, texture uses CLUT + }; + + + struct VB + { + VB(); + ~VB(); + + void Destroy(); + + inline bool CheckPrim() { + static const int PRIMMASK = 0x0e; // for now ignore 0x10 (AA) + if( (PRIMMASK & prim->_val) != (PRIMMASK & curprim._val) || primtype[prim->prim] != primtype[curprim.prim] ) + return nCount > 0; + return false; + } + + void CheckFrame(int tbp); + + // context specific state + Point offset; + Rect2 scissor; + tex0Info tex0; + tex1Info tex1; + miptbpInfo miptbp0; + miptbpInfo miptbp1; + alphaInfo alpha; + fbaInfo fba; + clampInfo clamp; + pixTest test; + u32 ptexClamp[2]; // textures for x and y dir region clamping + + public: + void FlushTexData(); + inline int CheckFrameAddConstraints(int tbp); + inline void CheckScissors (int maxpos); + inline void CheckFrame32bitRes(int maxpos); + inline int FindMinimalMemoryConstrain(int tbp, int maxpos); + inline int FindZbufferMemoryConstrain(int tbp, int maxpos); + inline int FindMinimalHeightConstrain(int maxpos); + + inline int CheckFrameResolveRender(int tbp); + inline void CheckFrame16vs32Convesion(); + inline int CheckFrameResolveDepth(int tbp); + + inline void FlushTexUnchangedClutDontUpdate() ; + inline void FlushTexClutDontUpdate() ; + inline void FlushTexClutting() ; + inline void FlushTexSetNewVars(u32 psm) ; + + // notify VB that nVerts need to be written to pbuf + inline void NotifyWrite(int nVerts) { + assert( pBufferData != NULL && nCount <= nNumVertices && nVerts > 0 ); + + if( nCount + nVerts > nNumVertices ) { + // recreate except with a bigger count + VertexGPU* ptemp = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU)*nNumVertices*2, 256); + memcpy_amd(ptemp, pBufferData, sizeof(VertexGPU) * nCount); + nNumVertices *= 2; + assert( nCount + nVerts <= nNumVertices ); + _aligned_free(pBufferData); + pBufferData = ptemp; + } + } + + void Init(int nVerts) { + if( pBufferData == NULL && nVerts > 0 ) { + pBufferData = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU)*nVerts, 256); + nNumVertices = nVerts; + } + + nCount = 0; + } + + u8 bNeedFrameCheck; + u8 bNeedZCheck; + u8 bNeedTexCheck; + u8 dummy0; + + union { + struct { + u8 bTexConstsSync; // only pixel shader constants that context owns + u8 bVarsTexSync; // texture info + u8 bVarsSetTarg; + u8 dummy1; + }; + u32 bSyncVars; + }; + + int ictx; + VertexGPU* pBufferData; // current allocated data + + int nNumVertices; // size of pBufferData in terms of VertexGPU objects + int nCount; + primInfo curprim; // the previous prim the current buffers are set to + + zbufInfo zbuf; + frameInfo gsfb; // the real info set by FRAME cmd + frameInfo frame; + int zprimmask; // zmask for incoming points + + u32 uCurTex0Data[2]; // current tex0 data + u32 uNextTex0Data[2]; // tex0 data that has to be applied if bNeedTexCheck is 1 + + //int nFrameHeights[8]; // frame heights for the past frame changes + int nNextFrameHeight; + + CMemoryTarget* pmemtarg; // the current mem target set + CRenderTarget* prndr; + CDepthTarget* pdepth; + }; + + // Return, if tcc, aem or psm mode told us, than Alpha test should be used + // if tcc == 0 than no alpha used, aem used for alpha expanding and I am not sure + // that it's correct, psm -- color mode, + inline bool + IsAlphaTestExpansion(VB& curvb){ + return (curvb.tex0.tcc && gs.texa.aem && nNeedAlpha(GetTexCPSM(curvb.tex0))); + } + + // visible members + extern DrawFn drawfn[8]; + + // VB variables + extern VB vb[2]; + extern float fiTexWidth[2], fiTexHeight[2]; // current tex width and height + extern vector g_vboBuffers; // VBOs for all drawing commands + extern GLuint vboRect; + extern int g_nCurVBOIndex; + + // Shaders variables + extern Vector g_vdepth; + extern Vector vlogz; + extern VERTEXSHADER pvsBitBlt; + extern FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne; + extern FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16; + bool LoadEffects(); + bool LoadExtraEffects(); + FRAGMENTSHADER* LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed); + + extern RenderFormatType g_RenderFormatType; + + void AddMessage(const char* pstr, u32 ms = 5000); + void DrawText(const char* pstr, int left, int top, u32 color); + void ChangeWindowSize(int nNewWidth, int nNewHeight); + void SetChangeDeviceSize(int nNewWidth, int nNewHeight); + void ChangeDeviceSize(int nNewWidth, int nNewHeight); + void SetAA(int mode); + void SetNegAA(int mode); + void SetCRC(int crc); + + void ReloadEffects(); + + // Methods // + bool IsGLExt( const char* szTargetExtension ); ///< returns true if the the opengl extension is supported + inline bool Create_Window(int _width, int _height); + bool Create(int width, int height); + void Destroy(BOOL bD3D); + + void Restore(); // call to restore device + void Reset(); // call to destroy video resources + + void GSStateReset(); + void HandleGLError(); + + // called on a primitive switch + void Prim(); + + void SetTexFlush(); + // flush current vertices, call before setting new registers (the main render method) + void Flush(int context); + + void ExtWrite(); + + void SetWriteDepth(); + bool IsWriteDepth(); + + void SetDestAlphaTest(); + bool IsWriteDestAlphaTest(); + + void SetFogColor(u32 fog); + void SaveTex(tex0Info* ptex, int usevid); + char* NamedSaveTex(tex0Info* ptex, int usevid); + + // called when trxdir is accessed. If host is involved, transfers memory to temp buffer byTransferBuf. + // Otherwise performs the transfer. TODO: Perhaps divide the transfers into chunks? + void InitTransferHostLocal(); + void TransferHostLocal(const void* pbyMem, u32 nQWordSize); + + void InitTransferLocalHost(); + void TransferLocalHost(void* pbyMem, u32 nQWordSize); + inline void TerminateLocalHost() {} + + void TransferLocalLocal(); + + // switches the render target to the real target, flushes the current render targets and renders the real image + void RenderCRTC(int interlace); + void ResetRenderTarget(int index); + + bool CheckChangeInClut(u32 highdword, u32 psm); // returns true if clut will change after this tex0 op + + // call to load CLUT data (depending on CLD) + void texClutWrite(int ctx); + RenderFormatType GetRenderFormat(); + GLenum GetRenderTargetFormat(); + + int Save(s8* pbydata); + bool Load(s8* pbydata); + + void SaveSnapshot(const char* filename); + bool SaveRenderTarget(const char* filename, int width, int height, int jpeg); + bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height); + bool SaveJPEG(const char* filename, int width, int height, const void* pdata, int quality); + bool SaveTGA(const char* filename, int width, int height, void* pdata); + void Stop_Avi(); + + // private methods + void FlushSysMem(const RECT* prc); + void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm, bool mode); + + // returns the first and last addresses aligned to a page that cover + void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw); + + // inits the smallest rectangle in ptexMem that covers this region in ptexMem + // returns the offset that needs to be added to the locked rect to get the beginning of the buffer + //void GetMemRect(RECT& rc, int psm, int x, int y, int w, int h, int bp, int bw); + + void SetContextTarget(int context) ; + + void NeedFactor(int w); + // only sets a limited amount of state (for Update) + void SetTexClamping(int context, FRAGMENTSHADER* pfragment); + void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, ZeroGS::CMemoryTarget* pmemtarg, FRAGMENTSHADER* pfragment, int force); + + void ResetAlphaVariables(); + + void StartCapture(); + void StopCapture(); + void CaptureFrame(); + + // Perform clutting for flushed texture. Better check if it need prior call + inline void + CluttingForFlushedTex(tex0Info* tex0, u32 Data, int ictx) { + tex0->cbp = ZZOglGet_cbp_TexBits(Data); + tex0->cpsm = ZZOglGet_cpsm_TexBits(Data); + tex0->csm = ZZOglGet_csm_TexBits(Data); + tex0->csa = ZZOglGet_csa_TexBits(Data); + tex0->cld = ZZOglGet_cld_TexBits(Data); + + ZeroGS::texClutWrite(ictx); + } +}; + +// GL prototypes +extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; +extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; +extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; +extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; +extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; +extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; +extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; +extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; +extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; +extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; +extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; +extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; +extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; +extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; +extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; +extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; +extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; +extern PFNGLDRAWBUFFERSPROC glDrawBuffers; + +#endif diff --git a/plugins/zzogl-pg/opengl/zerogsmath.h b/plugins/zzogl-pg/opengl/zerogsmath.h new file mode 100644 index 0000000000..83481ffb5b --- /dev/null +++ b/plugins/zzogl-pg/opengl/zerogsmath.h @@ -0,0 +1,903 @@ +#ifndef ZEROGS_MATH_H +#define ZEROGS_MATH_H + +#ifndef _WIN32 +#include +#endif + +#include +#include + +#ifndef PI +#define PI ((dReal)3.141592654) +#endif + +#define rswap(x, y) *(int*)&(x) ^= *(int*)&(y) ^= *(int*)&(x) ^= *(int*)&(y); + +template inline T RAD_2_DEG(T radians) { return (radians * (T)57.29577951); } + +class Transform; +class TransformMatrix; + +typedef float dReal; +typedef dReal dMatrix3[3*4]; + +inline dReal* normalize3(dReal* pfout, const dReal* pf); +inline dReal* normalize4(dReal* pfout, const dReal* pf); +inline dReal* cross3(dReal* pfout, const dReal* pf1, const dReal* pf2); + +// multiplies 3x3 matrices +inline dReal* mult3(dReal* pfres, const dReal* pf1, const dReal* pf2); +inline double* mult3(double* pfres, const double* pf1, const double* pf2); + +inline dReal* inv3(const dReal* pf, dReal* pfres, int stride); +inline dReal* inv4(const dReal* pf, dReal* pfres); + +// class used for 3 and 4 dim vectors and quaternions +// It is better to use this for a 3 dim vector because it is 16byte aligned and SIMD instructions can be used +class Vector +{ +public: + dReal x, y, z, w; + + Vector() : x(0), y(0), z(0), w(0) {} + Vector(dReal x, dReal y, dReal z) : x(x), y(y), z(z), w(0) {} + Vector(dReal x, dReal y, dReal z, dReal w) : x(x), y(y), z(z), w(w) {} + Vector(const Vector &vec) : x(vec.x), y(vec.y), z(vec.z), w(vec.w) {} + Vector(const dReal* pf) { assert(pf != NULL); x = pf[0]; y = pf[1]; z = pf[2]; w = 0; } + + dReal operator[](int i) const { return (&x)[i]; } + dReal& operator[](int i) { return (&x)[i]; } + + // casting operators + operator dReal* () { return &x; } + operator const dReal* () const { return (const dReal*)&x; } + + // SCALAR FUNCTIONS + inline dReal dot(const Vector &v) const { return x*v.x + y*v.y + z*v.z + w*v.w; } + inline void normalize() { normalize4(&x, &x); } + + inline void Set3(const float* pvals) { x = pvals[0]; y = pvals[1]; z = pvals[2]; } + inline void Set4(const float* pvals) { x = pvals[0]; y = pvals[1]; z = pvals[2]; w = pvals[3]; } + + // 3 dim cross product, w is not touched + /// this = this x v + inline void Cross(const Vector &v) { cross3(&x, &x, v); } + + /// this = u x v + inline void Cross(const Vector &u, const Vector &v) { cross3(&x, u, v); } + + inline Vector operator-() const { Vector v; v.x = -x; v.y = -y; v.z = -z; v.w = -w; return v; } + inline Vector operator+(const Vector &r) const { Vector v; v.x = x+r.x; v.y = y+r.y; v.z = z+r.z; v.w = w+r.w; return v; } + inline Vector operator-(const Vector &r) const { Vector v; v.x = x-r.x; v.y = y-r.y; v.z = z-r.z; v.w = w-r.w; return v; } + inline Vector operator*(const Vector &r) const { Vector v; v.x = r.x*x; v.y = r.y*y; v.z = r.z*z; v.w = r.w*w; return v; } + inline Vector operator*(dReal k) const { Vector v; v.x = k*x; v.y = k*y; v.z = k*z; v.w = k*w; return v; } + + inline Vector& operator += (const Vector& r) { x += r.x; y += r.y; z += r.z; w += r.w; return *this; } + inline Vector& operator -= (const Vector& r) { x -= r.x; y -= r.y; z -= r.z; w -= r.w; return *this; } + inline Vector& operator *= (const Vector& r) { x *= r.x; y *= r.y; z *= r.z; w *= r.w; return *this; } + + inline Vector& operator *= (const dReal k) { x *= k; y *= k; z *= k; w *= k; return *this; } + inline Vector& operator /= (const dReal _k) { dReal k=1/_k; x *= k; y *= k; z *= k; w *= k; return *this; } + + friend Vector operator* (float f, const Vector& v); + //friend ostream& operator<<(ostream& O, const Vector& v); + //friend istream& operator>>(istream& I, Vector& v); +}; + +inline Vector operator* (float f, const Vector& left) +{ + Vector v; + v.x = f * left.x; + v.y = f * left.y; + v.z = f * left.z; + return v; +} + +struct AABB +{ + Vector pos, extents; +}; + +struct OBB +{ + Vector right, up, dir, pos, extents; +}; + +struct TRIANGLE +{ + TRIANGLE() {} + TRIANGLE(const Vector& v1, const Vector& v2, const Vector& v3) : v1(v1), v2(v2), v3(v3) {} + ~TRIANGLE() {} + + Vector v1, v2, v3; //!< the vertices of the triangle + + const Vector& operator[](int i) const { return (&v1)[i]; } + Vector& operator[](int i) { return (&v1)[i]; } + + /// assumes CCW ordering of vertices + inline Vector ComputeNormal() { + Vector normal; + cross3(normal, v2-v1, v3-v1); + return normal; + } +}; + +// Routines made for 3D graphics that deal with 3 or 4 dim algebra structures +// Functions with postfix 3 are for 3x3 operations, etc + +// all fns return pfout on success or NULL on failure +// results and arguments can share pointers + + +// multiplies 4x4 matrices +inline dReal* mult4(dReal* pfres, const dReal* pf1, const dReal* pf2); +inline double* mult4(double* pfres, const double* pf1, const double* pf2); + +// pf1^T * pf2 +inline dReal* multtrans3(dReal* pfres, const dReal* pf1, const dReal* pf2); +inline double* multtrans3(double* pfres, const double* pf1, const double* pf2); +inline dReal* multtrans4(dReal* pfres, const dReal* pf1, const dReal* pf2); +inline double* multtrans4(double* pfres, const double* pf1, const double* pf2); + +inline dReal* transpose3(const dReal* pf, dReal* pfres); +inline double* transpose3(const double* pf, double* pfres); +inline dReal* transpose4(const dReal* pf, dReal* pfres); +inline double* transpose4(const double* pf, double* pfres); + +inline dReal dot2(const dReal* pf1, const dReal* pf2); +inline dReal dot3(const dReal* pf1, const dReal* pf2); +inline dReal dot4(const dReal* pf1, const dReal* pf2); + +inline dReal lengthsqr2(const dReal* pf); +inline dReal lengthsqr3(const dReal* pf); +inline dReal lengthsqr4(const dReal* pf); + +inline dReal* normalize2(dReal* pfout, const dReal* pf); +inline dReal* normalize3(dReal* pfout, const dReal* pf); +inline dReal* normalize4(dReal* pfout, const dReal* pf); + +//// +// More complex ops that deal with arbitrary matrices // +//// + +// extract eigen values and vectors from a 2x2 matrix and returns true if all values are real +// returned eigen vectors are normalized +inline bool eig2(const dReal* pfmat, dReal* peigs, dReal& fv1x, dReal& fv1y, dReal& fv2x, dReal& fv2y); + +// Simple routines for linear algebra algorithms // +int CubicRoots (double c0, double c1, double c2, double *r0, double *r1, double *r2); +bool QLAlgorithm3 (dReal* m_aafEntry, dReal* afDiag, dReal* afSubDiag); + +void EigenSymmetric3(dReal* fCovariance, dReal* eval, dReal* fAxes); + +void GetCovarBasisVectors(dReal fCovariance[3][3], Vector* vRight, Vector* vUp, Vector* vDir); + +// first root returned is always >= second, roots are defined if the quadratic doesn't have real solutions +void QuadraticSolver(dReal* pfQuadratic, dReal* pfRoots); + +int insideQuadrilateral(const Vector* p0,const Vector* p1, const Vector* p2,const Vector* p3); +int insideTriangle(const Vector* p0, const Vector* p1, const Vector* p2); + +// multiplies a matrix by a scalar +template inline void mult(T* pf, T fa, int r); + +// multiplies a r1xc1 by c1xc2 matrix into pfres, if badd is true adds the result to pfres +// does not handle cases where pfres is equal to pf1 or pf2, use multtox for those cases +template +inline T* mult(T* pf1, R* pf2, int r1, int c1, int c2, S* pfres, bool badd = false); + +// pf1 is transposed before mult +// rows of pf2 must equal rows of pf1 +// pfres will be c1xc2 matrix +template +inline T* multtrans(T* pf1, R* pf2, int r1, int c1, int c2, S* pfres, bool badd = false); + +// pf2 is transposed before mult +// the columns of both matrices must be the same and equal to c1 +// r2 is the number of rows in pf2 +// pfres must be an r1xr2 matrix +template +inline T* multtrans_to2(T* pf1, R* pf2, int r1, int c1, int r2, S* pfres, bool badd = false); + +// multiplies rxc matrix pf1 and cxc matrix pf2 and stores the result in pf1, +// the function needs a temporary buffer the size of c doubles, if pftemp == NULL, +// the function will allocate the necessary memory, otherwise pftemp should be big +// enough to store all the entries +template inline T* multto1(T* pf1, T* pf2, int r1, int c1, T* pftemp = NULL); + +// same as multto1 except stores the result in pf2, pf1 has to be an r2xr2 matrix +// pftemp must be of size r2 if not NULL +template inline T* multto2(T* pf1, S* pf2, int r2, int c2, S* pftemp = NULL); + +// add pf1 + pf2 and store in pf1 +template inline void sub(T* pf1, T* pf2, int r); +template inline T normsqr(T* pf1, int r); +template inline T lengthsqr(T* pf1, T* pf2, int length); +template inline T dot(T* pf1, T* pf2, int length); + +template inline T sum(T* pf, int length); + +// takes the inverse of the 3x3 matrix pf and stores it into pfres, returns true if matrix is invertible +template inline bool inv2(T* pf, T* pfres); + +/////////////////////// +// Function Definitions +/////////////////////// +bool eig2(const dReal* pfmat, dReal* peigs, dReal& fv1x, dReal& fv1y, dReal& fv2x, dReal& fv2y) +{ + // x^2 + bx + c + dReal a, b, c, d; + b = -(pfmat[0] + pfmat[3]); + c = pfmat[0] * pfmat[3] - pfmat[1] * pfmat[2]; + d = b * b - 4.0f * c + 1e-16f; + + if( d < 0 ) return false; + if( d < 1e-16f ) { + a = -0.5f * b; + peigs[0] = a; peigs[1] = a; + fv1x = pfmat[1]; fv1y = a - pfmat[0]; + c = 1 / sqrtf(fv1x*fv1x + fv1y*fv1y); + fv1x *= c; fv1y *= c; + fv2x = -fv1y; fv2y = fv1x; + return true; + } + + // two roots + d = sqrtf(d); + a = -0.5f * (b + d); + peigs[0] = a; + fv1x = pfmat[1]; fv1y = a-pfmat[0]; + c = 1 / sqrtf(fv1x*fv1x + fv1y*fv1y); + fv1x *= c; fv1y *= c; + + a += d; + peigs[1] = a; + fv2x = pfmat[1]; fv2y = a-pfmat[0]; + c = 1 / sqrtf(fv2x*fv2x + fv2y*fv2y); + fv2x *= c; fv2y *= c; + return true; +} + +//#ifndef TI_USING_IPP + +// Functions that are replacable by ipp library funcs +template inline T* _mult3(T* pfres, const T* pf1, const T* pf2) +{ + assert( pf1 != NULL && pf2 != NULL && pfres != NULL ); + + T* pfres2; + if( pfres == pf1 || pfres == pf2 ) pfres2 = (T*)alloca(9 * sizeof(T)); + else pfres2 = pfres; + + pfres2[0*4+0] = pf1[0*4+0]*pf2[0*4+0]+pf1[0*4+1]*pf2[1*4+0]+pf1[0*4+2]*pf2[2*4+0]; + pfres2[0*4+1] = pf1[0*4+0]*pf2[0*4+1]+pf1[0*4+1]*pf2[1*4+1]+pf1[0*4+2]*pf2[2*4+1]; + pfres2[0*4+2] = pf1[0*4+0]*pf2[0*4+2]+pf1[0*4+1]*pf2[1*4+2]+pf1[0*4+2]*pf2[2*4+2]; + + pfres2[1*4+0] = pf1[1*4+0]*pf2[0*4+0]+pf1[1*4+1]*pf2[1*4+0]+pf1[1*4+2]*pf2[2*4+0]; + pfres2[1*4+1] = pf1[1*4+0]*pf2[0*4+1]+pf1[1*4+1]*pf2[1*4+1]+pf1[1*4+2]*pf2[2*4+1]; + pfres2[1*4+2] = pf1[1*4+0]*pf2[0*4+2]+pf1[1*4+1]*pf2[1*4+2]+pf1[1*4+2]*pf2[2*4+2]; + + pfres2[2*4+0] = pf1[2*4+0]*pf2[0*4+0]+pf1[2*4+1]*pf2[1*4+0]+pf1[2*4+2]*pf2[2*4+0]; + pfres2[2*4+1] = pf1[2*4+0]*pf2[0*4+1]+pf1[2*4+1]*pf2[1*4+1]+pf1[2*4+2]*pf2[2*4+1]; + pfres2[2*4+2] = pf1[2*4+0]*pf2[0*4+2]+pf1[2*4+1]*pf2[1*4+2]+pf1[2*4+2]*pf2[2*4+2]; + + if( pfres2 != pfres ) memcpy(pfres, pfres2, 9*sizeof(T)); + + return pfres; +} + +inline dReal* mult3(dReal* pfres, const dReal* pf1, const dReal* pf2) { return _mult3(pfres, pf1, pf2); } +inline double* mult3(double* pfres, const double* pf1, const double* pf2) { return _mult3(pfres, pf1, pf2); } + +template +inline T* _mult4(T* pfres, const T* p1, const T* p2) +{ + assert( pfres != NULL && p1 != NULL && p2 != NULL ); + + T* pfres2; + if( pfres == p1 || pfres == p2 ) pfres2 = (T*)alloca(16 * sizeof(T)); + else pfres2 = pfres; + + pfres2[0*4+0] = p1[0*4+0]*p2[0*4+0] + p1[0*4+1]*p2[1*4+0] + p1[0*4+2]*p2[2*4+0] + p1[0*4+3]*p2[3*4+0]; + pfres2[0*4+1] = p1[0*4+0]*p2[0*4+1] + p1[0*4+1]*p2[1*4+1] + p1[0*4+2]*p2[2*4+1] + p1[0*4+3]*p2[3*4+1]; + pfres2[0*4+2] = p1[0*4+0]*p2[0*4+2] + p1[0*4+1]*p2[1*4+2] + p1[0*4+2]*p2[2*4+2] + p1[0*4+3]*p2[3*4+2]; + pfres2[0*4+3] = p1[0*4+0]*p2[0*4+3] + p1[0*4+1]*p2[1*4+3] + p1[0*4+2]*p2[2*4+3] + p1[0*4+3]*p2[3*4+3]; + + pfres2[1*4+0] = p1[1*4+0]*p2[0*4+0] + p1[1*4+1]*p2[1*4+0] + p1[1*4+2]*p2[2*4+0] + p1[1*4+3]*p2[3*4+0]; + pfres2[1*4+1] = p1[1*4+0]*p2[0*4+1] + p1[1*4+1]*p2[1*4+1] + p1[1*4+2]*p2[2*4+1] + p1[1*4+3]*p2[3*4+1]; + pfres2[1*4+2] = p1[1*4+0]*p2[0*4+2] + p1[1*4+1]*p2[1*4+2] + p1[1*4+2]*p2[2*4+2] + p1[1*4+3]*p2[3*4+2]; + pfres2[1*4+3] = p1[1*4+0]*p2[0*4+3] + p1[1*4+1]*p2[1*4+3] + p1[1*4+2]*p2[2*4+3] + p1[1*4+3]*p2[3*4+3]; + + pfres2[2*4+0] = p1[2*4+0]*p2[0*4+0] + p1[2*4+1]*p2[1*4+0] + p1[2*4+2]*p2[2*4+0] + p1[2*4+3]*p2[3*4+0]; + pfres2[2*4+1] = p1[2*4+0]*p2[0*4+1] + p1[2*4+1]*p2[1*4+1] + p1[2*4+2]*p2[2*4+1] + p1[2*4+3]*p2[3*4+1]; + pfres2[2*4+2] = p1[2*4+0]*p2[0*4+2] + p1[2*4+1]*p2[1*4+2] + p1[2*4+2]*p2[2*4+2] + p1[2*4+3]*p2[3*4+2]; + pfres2[2*4+3] = p1[2*4+0]*p2[0*4+3] + p1[2*4+1]*p2[1*4+3] + p1[2*4+2]*p2[2*4+3] + p1[2*4+3]*p2[3*4+3]; + + pfres2[3*4+0] = p1[3*4+0]*p2[0*4+0] + p1[3*4+1]*p2[1*4+0] + p1[3*4+2]*p2[2*4+0] + p1[3*4+3]*p2[3*4+0]; + pfres2[3*4+1] = p1[3*4+0]*p2[0*4+1] + p1[3*4+1]*p2[1*4+1] + p1[3*4+2]*p2[2*4+1] + p1[3*4+3]*p2[3*4+1]; + pfres2[3*4+2] = p1[3*4+0]*p2[0*4+2] + p1[3*4+1]*p2[1*4+2] + p1[3*4+2]*p2[2*4+2] + p1[3*4+3]*p2[3*4+2]; + pfres2[3*4+3] = p1[3*4+0]*p2[0*4+3] + p1[3*4+1]*p2[1*4+3] + p1[3*4+2]*p2[2*4+3] + p1[3*4+3]*p2[3*4+3]; + + if( pfres != pfres2 ) memcpy(pfres, pfres2, sizeof(T)*16); + return pfres; +} + +inline dReal* mult4(dReal* pfres, const dReal* pf1, const dReal* pf2) { return _mult4(pfres, pf1, pf2); } +inline double* mult4(double* pfres, const double* pf1, const double* pf2) { return _mult4(pfres, pf1, pf2); } + +template +inline T* _multtrans3(T* pfres, const T* pf1, const T* pf2) +{ + T* pfres2; + if( pfres == pf1 ) pfres2 = (T*)alloca(9 * sizeof(T)); + else pfres2 = pfres; + + pfres2[0] = pf1[0]*pf2[0]+pf1[3]*pf2[3]+pf1[6]*pf2[6]; + pfres2[1] = pf1[0]*pf2[1]+pf1[3]*pf2[4]+pf1[6]*pf2[7]; + pfres2[2] = pf1[0]*pf2[2]+pf1[3]*pf2[5]+pf1[6]*pf2[8]; + + pfres2[3] = pf1[1]*pf2[0]+pf1[4]*pf2[3]+pf1[7]*pf2[6]; + pfres2[4] = pf1[1]*pf2[1]+pf1[4]*pf2[4]+pf1[7]*pf2[7]; + pfres2[5] = pf1[1]*pf2[2]+pf1[4]*pf2[5]+pf1[7]*pf2[8]; + + pfres2[6] = pf1[2]*pf2[0]+pf1[5]*pf2[3]+pf1[8]*pf2[6]; + pfres2[7] = pf1[2]*pf2[1]+pf1[5]*pf2[4]+pf1[8]*pf2[7]; + pfres2[8] = pf1[2]*pf2[2]+pf1[5]*pf2[5]+pf1[8]*pf2[8]; + + if( pfres2 != pfres ) memcpy(pfres, pfres2, 9*sizeof(T)); + + return pfres; +} + +template +inline T* _multtrans4(T* pfres, const T* pf1, const T* pf2) +{ + T* pfres2; + if( pfres == pf1 ) pfres2 = (T*)alloca(16 * sizeof(T)); + else pfres2 = pfres; + + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + pfres[4*i+j] = pf1[i] * pf2[j] + pf1[i+4] * pf2[j+4] + pf1[i+8] * pf2[j+8] + pf1[i+12] * pf2[j+12]; + } + } + + return pfres; +} + +inline dReal* multtrans3(dReal* pfres, const dReal* pf1, const dReal* pf2) { return _multtrans3(pfres, pf1, pf2); } +inline double* multtrans3(double* pfres, const double* pf1, const double* pf2) { return _multtrans3(pfres, pf1, pf2); } +inline dReal* multtrans4(dReal* pfres, const dReal* pf1, const dReal* pf2) { return _multtrans4(pfres, pf1, pf2); } +inline double* multtrans4(double* pfres, const double* pf1, const double* pf2) { return _multtrans4(pfres, pf1, pf2); } + +// stride is in T +template inline T* _inv3(const T* pf, T* pfres, int stride) +{ + T* pfres2; + if( pfres == pf ) pfres2 = (T*)alloca(3 * stride * sizeof(T)); + else pfres2 = pfres; + + // inverse = C^t / det(pf) where C is the matrix of coefficients + + // calc C^t + pfres2[0*stride + 0] = pf[1*stride + 1] * pf[2*stride + 2] - pf[1*stride + 2] * pf[2*stride + 1]; + pfres2[0*stride + 1] = pf[0*stride + 2] * pf[2*stride + 1] - pf[0*stride + 1] * pf[2*stride + 2]; + pfres2[0*stride + 2] = pf[0*stride + 1] * pf[1*stride + 2] - pf[0*stride + 2] * pf[1*stride + 1]; + pfres2[1*stride + 0] = pf[1*stride + 2] * pf[2*stride + 0] - pf[1*stride + 0] * pf[2*stride + 2]; + pfres2[1*stride + 1] = pf[0*stride + 0] * pf[2*stride + 2] - pf[0*stride + 2] * pf[2*stride + 0]; + pfres2[1*stride + 2] = pf[0*stride + 2] * pf[1*stride + 0] - pf[0*stride + 0] * pf[1*stride + 2]; + pfres2[2*stride + 0] = pf[1*stride + 0] * pf[2*stride + 1] - pf[1*stride + 1] * pf[2*stride + 0]; + pfres2[2*stride + 1] = pf[0*stride + 1] * pf[2*stride + 0] - pf[0*stride + 0] * pf[2*stride + 1]; + pfres2[2*stride + 2] = pf[0*stride + 0] * pf[1*stride + 1] - pf[0*stride + 1] * pf[1*stride + 0]; + + T fdet = pf[0*stride + 2] * pfres2[2*stride + 0] + pf[1*stride + 2] * pfres2[2*stride + 1] + + pf[2*stride + 2] * pfres2[2*stride + 2]; + + if( fabs(fdet) < 1e-6 ) return NULL; + + fdet = 1 / fdet; + //if( pfdet != NULL ) *pfdet = fdet; + + if( pfres != pf ) { + pfres[0*stride+0] *= fdet; pfres[0*stride+1] *= fdet; pfres[0*stride+2] *= fdet; + pfres[1*stride+0] *= fdet; pfres[1*stride+1] *= fdet; pfres[1*stride+2] *= fdet; + pfres[2*stride+0] *= fdet; pfres[2*stride+1] *= fdet; pfres[2*stride+2] *= fdet; + return pfres; + } + + pfres[0*stride+0] = pfres2[0*stride+0] * fdet; + pfres[0*stride+1] = pfres2[0*stride+1] * fdet; + pfres[0*stride+2] = pfres2[0*stride+2] * fdet; + pfres[1*stride+0] = pfres2[1*stride+0] * fdet; + pfres[1*stride+1] = pfres2[1*stride+1] * fdet; + pfres[1*stride+2] = pfres2[1*stride+2] * fdet; + pfres[2*stride+0] = pfres2[2*stride+0] * fdet; + pfres[2*stride+1] = pfres2[2*stride+1] * fdet; + pfres[2*stride+2] = pfres2[2*stride+2] * fdet; + return pfres; +} + +inline dReal* inv3(const dReal* pf, dReal* pfres, int stride) { return _inv3(pf, pfres, stride); } + +// inverse if 92 mults and 39 adds +template inline T* _inv4(const T* pf, T* pfres) +{ + T* pfres2; + if( pfres == pf ) pfres2 = (T*)alloca(16 * sizeof(T)); + else pfres2 = pfres; + + // inverse = C^t / det(pf) where C is the matrix of coefficients + + // calc C^t + + // determinants of all possibel 2x2 submatrices formed by last two rows + T fd0, fd1, fd2; + T f1, f2, f3; + fd0 = pf[2*4 + 0] * pf[3*4 + 1] - pf[2*4 + 1] * pf[3*4 + 0]; + fd1 = pf[2*4 + 1] * pf[3*4 + 2] - pf[2*4 + 2] * pf[3*4 + 1]; + fd2 = pf[2*4 + 2] * pf[3*4 + 3] - pf[2*4 + 3] * pf[3*4 + 2]; + + f1 = pf[2*4 + 1] * pf[3*4 + 3] - pf[2*4 + 3] * pf[3*4 + 1]; + f2 = pf[2*4 + 0] * pf[3*4 + 3] - pf[2*4 + 3] * pf[3*4 + 0]; + f3 = pf[2*4 + 0] * pf[3*4 + 2] - pf[2*4 + 2] * pf[3*4 + 0]; + + pfres2[0*4 + 0] = pf[1*4 + 1] * fd2 - pf[1*4 + 2] * f1 + pf[1*4 + 3] * fd1; + pfres2[0*4 + 1] = -(pf[0*4 + 1] * fd2 - pf[0*4 + 2] * f1 + pf[0*4 + 3] * fd1); + + pfres2[1*4 + 0] = -(pf[1*4 + 0] * fd2 - pf[1*4 + 2] * f2 + pf[1*4 + 3] * f3); + pfres2[1*4 + 1] = pf[0*4 + 0] * fd2 - pf[0*4 + 2] * f2 + pf[0*4 + 3] * f3; + + pfres2[2*4 + 0] = pf[1*4 + 0] * f1 - pf[1*4 + 1] * f2 + pf[1*4 + 3] * fd0; + pfres2[2*4 + 1] = -(pf[0*4 + 0] * f1 - pf[0*4 + 1] * f2 + pf[0*4 + 3] * fd0); + + pfres2[3*4 + 0] = -(pf[1*4 + 0] * fd1 - pf[1*4 + 1] * f3 + pf[1*4 + 2] * fd0); + pfres2[3*4 + 1] = pf[0*4 + 0] * fd1 - pf[0*4 + 1] * f3 + pf[0*4 + 2] * fd0; + + // determinants of first 2 rows of 4x4 matrix + fd0 = pf[0*4 + 0] * pf[1*4 + 1] - pf[0*4 + 1] * pf[1*4 + 0]; + fd1 = pf[0*4 + 1] * pf[1*4 + 2] - pf[0*4 + 2] * pf[1*4 + 1]; + fd2 = pf[0*4 + 2] * pf[1*4 + 3] - pf[0*4 + 3] * pf[1*4 + 2]; + + f1 = pf[0*4 + 1] * pf[1*4 + 3] - pf[0*4 + 3] * pf[1*4 + 1]; + f2 = pf[0*4 + 0] * pf[1*4 + 3] - pf[0*4 + 3] * pf[1*4 + 0]; + f3 = pf[0*4 + 0] * pf[1*4 + 2] - pf[0*4 + 2] * pf[1*4 + 0]; + + pfres2[0*4 + 2] = pf[3*4 + 1] * fd2 - pf[3*4 + 2] * f1 + pf[3*4 + 3] * fd1; + pfres2[0*4 + 3] = -(pf[2*4 + 1] * fd2 - pf[2*4 + 2] * f1 + pf[2*4 + 3] * fd1); + + pfres2[1*4 + 2] = -(pf[3*4 + 0] * fd2 - pf[3*4 + 2] * f2 + pf[3*4 + 3] * f3); + pfres2[1*4 + 3] = pf[2*4 + 0] * fd2 - pf[2*4 + 2] * f2 + pf[2*4 + 3] * f3; + + pfres2[2*4 + 2] = pf[3*4 + 0] * f1 - pf[3*4 + 1] * f2 + pf[3*4 + 3] * fd0; + pfres2[2*4 + 3] = -(pf[2*4 + 0] * f1 - pf[2*4 + 1] * f2 + pf[2*4 + 3] * fd0); + + pfres2[3*4 + 2] = -(pf[3*4 + 0] * fd1 - pf[3*4 + 1] * f3 + pf[3*4 + 2] * fd0); + pfres2[3*4 + 3] = pf[2*4 + 0] * fd1 - pf[2*4 + 1] * f3 + pf[2*4 + 2] * fd0; + + T fdet = pf[0*4 + 3] * pfres2[3*4 + 0] + pf[1*4 + 3] * pfres2[3*4 + 1] + + pf[2*4 + 3] * pfres2[3*4 + 2] + pf[3*4 + 3] * pfres2[3*4 + 3]; + + if( fabs(fdet) < 1e-6) return NULL; + + fdet = 1 / fdet; + //if( pfdet != NULL ) *pfdet = fdet; + + if( pfres2 == pfres ) { + mult(pfres, fdet, 16); + return pfres; + } + + int i = 0; + while(i < 16) { + pfres[i] = pfres2[i] * fdet; + ++i; + } + + return pfres; +} + +inline dReal* inv4(const dReal* pf, dReal* pfres) { return _inv4(pf, pfres); } + +template inline T* _transpose3(const T* pf, T* pfres) +{ + assert( pf != NULL && pfres != NULL ); + + if( pf == pfres ) { + rswap(pfres[1], pfres[3]); + rswap(pfres[2], pfres[6]); + rswap(pfres[5], pfres[7]); + return pfres; + } + + pfres[0] = pf[0]; pfres[1] = pf[3]; pfres[2] = pf[6]; + pfres[3] = pf[1]; pfres[4] = pf[4]; pfres[5] = pf[7]; + pfres[6] = pf[2]; pfres[7] = pf[5]; pfres[8] = pf[8]; + + return pfres; +} + +inline dReal* transpose3(const dReal* pf, dReal* pfres) { return _transpose3(pf, pfres); } +inline double* transpose3(const double* pf, double* pfres) { return _transpose3(pf, pfres); } + +template inline T* _transpose4(const T* pf, T* pfres) +{ + assert( pf != NULL && pfres != NULL ); + + if( pf == pfres ) { + rswap(pfres[1], pfres[4]); + rswap(pfres[2], pfres[8]); + rswap(pfres[3], pfres[12]); + rswap(pfres[6], pfres[9]); + rswap(pfres[7], pfres[13]); + rswap(pfres[11], pfres[15]); + return pfres; + } + + pfres[0] = pf[0]; pfres[1] = pf[4]; pfres[2] = pf[8]; pfres[3] = pf[12]; + pfres[4] = pf[1]; pfres[5] = pf[5]; pfres[6] = pf[9]; pfres[7] = pf[13]; + pfres[8] = pf[2]; pfres[9] = pf[6]; pfres[10] = pf[10]; pfres[11] = pf[14]; + pfres[12] = pf[3]; pfres[13] = pf[7]; pfres[14] = pf[11]; pfres[15] = pf[15]; + return pfres; +} + +inline dReal* transpose4(const dReal* pf, dReal* pfres) { return _transpose4(pf, pfres); } +inline double* transpose4(const double* pf, double* pfres) { return _transpose4(pf, pfres); } + +inline dReal dot2(const dReal* pf1, const dReal* pf2) +{ + assert( pf1 != NULL && pf2 != NULL ); + return pf1[0]*pf2[0] + pf1[1]*pf2[1]; +} + +inline dReal dot3(const dReal* pf1, const dReal* pf2) +{ + assert( pf1 != NULL && pf2 != NULL ); + return pf1[0]*pf2[0] + pf1[1]*pf2[1] + pf1[2]*pf2[2]; +} + +inline dReal dot4(const dReal* pf1, const dReal* pf2) +{ + assert( pf1 != NULL && pf2 != NULL ); + return pf1[0]*pf2[0] + pf1[1]*pf2[1] + pf1[2]*pf2[2] + pf1[3] * pf2[3]; +} + +inline dReal lengthsqr2(const dReal* pf) +{ + assert( pf != NULL ); + return pf[0] * pf[0] + pf[1] * pf[1]; +} + +inline dReal lengthsqr3(const dReal* pf) +{ + assert( pf != NULL ); + return pf[0] * pf[0] + pf[1] * pf[1] + pf[2] * pf[2]; +} + +inline dReal lengthsqr4(const dReal* pf) +{ + assert( pf != NULL ); + return pf[0] * pf[0] + pf[1] * pf[1] + pf[2] * pf[2] + pf[3] * pf[3]; +} + +inline dReal* normalize2(dReal* pfout, const dReal* pf) +{ + assert(pf != NULL); + + dReal f = pf[0]*pf[0] + pf[1]*pf[1]; + f = 1.0f / sqrtf(f); + pfout[0] = pf[0] * f; + pfout[1] = pf[1] * f; + + return pfout; +} + +inline dReal* normalize3(dReal* pfout, const dReal* pf) +{ + assert(pf != NULL); + + dReal f = pf[0]*pf[0] + pf[1]*pf[1] + pf[2]*pf[2]; + + f = 1.0f / sqrtf(f); + pfout[0] = pf[0] * f; + pfout[1] = pf[1] * f; + pfout[2] = pf[2] * f; + + return pfout; +} + +inline dReal* normalize4(dReal* pfout, const dReal* pf) +{ + assert(pf != NULL); + + dReal f = pf[0]*pf[0] + pf[1]*pf[1] + pf[2]*pf[2] + pf[3]*pf[3]; + + f = 1.0f / sqrtf(f); + pfout[0] = pf[0] * f; + pfout[1] = pf[1] * f; + pfout[2] = pf[2] * f; + pfout[3] = pf[3] * f; + + return pfout; +} + +inline dReal* cross3(dReal* pfout, const dReal* pf1, const dReal* pf2) +{ + assert( pfout != NULL && pf1 != NULL && pf2 != NULL ); + + dReal temp[3]; + temp[0] = pf1[1] * pf2[2] - pf1[2] * pf2[1]; + temp[1] = pf1[2] * pf2[0] - pf1[0] * pf2[2]; + temp[2] = pf1[0] * pf2[1] - pf1[1] * pf2[0]; + + pfout[0] = temp[0]; pfout[1] = temp[1]; pfout[2] = temp[2]; + return pfout; +} + +template inline void mult(T* pf, T fa, int r) +{ + assert( pf != NULL ); + + while(r > 0) { + --r; + pf[r] *= fa; + } +} + +template +inline T* mult(T* pf1, R* pf2, int r1, int c1, int c2, S* pfres, bool badd) +{ + assert( pf1 != NULL && pf2 != NULL && pfres != NULL); + int j, k; + + if( !badd ) memset(pfres, 0, sizeof(S) * r1 * c2); + + while(r1 > 0) { + --r1; + + j = 0; + while(j < c2) { + k = 0; + while(k < c1) { + pfres[j] += pf1[k] * pf2[k*c2 + j]; + ++k; + } + ++j; + } + + pf1 += c1; + pfres += c2; + } + + return pfres; +} + +template +inline T* multtrans(T* pf1, R* pf2, int r1, int c1, int c2, S* pfres, bool badd) +{ + assert( pf1 != NULL && pf2 != NULL && pfres != NULL); + int i, j, k; + + if( !badd ) memset(pfres, 0, sizeof(S) * c1 * c2); + + i = 0; + while(i < c1) { + + j = 0; + while(j < c2) { + + k = 0; + while(k < r1) { + pfres[j] += pf1[k*c1] * pf2[k*c2 + j]; + ++k; + } + ++j; + } + + pfres += c2; + ++pf1; + + ++i; + } + + return pfres; +} + +template +inline T* multtrans_to2(T* pf1, R* pf2, int r1, int c1, int r2, S* pfres, bool badd) +{ + assert( pf1 != NULL && pf2 != NULL && pfres != NULL); + int j, k; + + if( !badd ) memset(pfres, 0, sizeof(S) * r1 * r2); + + while(r1 > 0) { + --r1; + + j = 0; + while(j < r2) { + k = 0; + while(k < c1) { + pfres[j] += pf1[k] * pf2[j*c1 + k]; + ++k; + } + ++j; + } + + pf1 += c1; + pfres += r2; + } + + return pfres; +} + +template inline T* multto1(T* pf1, T* pf2, int r, int c, T* pftemp) +{ + assert( pf1 != NULL && pf2 != NULL ); + + int j, k; + bool bdel = false; + + if( pftemp == NULL ) { + pftemp = new T[c]; + bdel = true; + } + + while(r > 0) { + --r; + + j = 0; + while(j < c) { + + pftemp[j] = 0.0; + + k = 0; + while(k < c) { + pftemp[j] += pf1[k] * pf2[k*c + j]; + ++k; + } + ++j; + } + + memcpy(pf1, pftemp, c * sizeof(T)); + pf1 += c; + } + + if( bdel ) delete[] pftemp; + + return pf1; +} + +template inline T* multto2(T* pf1, S* pf2, int r2, int c2, S* pftemp) +{ + assert( pf1 != NULL && pf2 != NULL ); + + int i, j, k; + bool bdel = false; + + if( pftemp == NULL ) { + pftemp = new S[r2]; + bdel = true; + } + + // do columns first + j = 0; + while(j < c2) { + i = 0; + while(i < r2) { + + pftemp[i] = 0.0; + + k = 0; + while(k < r2) { + pftemp[i] += pf1[i*r2 + k] * pf2[k*c2 + j]; + ++k; + } + ++i; + } + + i = 0; + while(i < r2) { + *(pf2+i*c2+j) = pftemp[i]; + ++i; + } + + ++j; + } + + if( bdel ) delete[] pftemp; + + return pf1; +} + +template inline void add(T* pf1, T* pf2, int r) +{ + assert( pf1 != NULL && pf2 != NULL); + + while(r > 0) { + --r; + pf1[r] += pf2[r]; + } +} + +template inline void sub(T* pf1, T* pf2, int r) +{ + assert( pf1 != NULL && pf2 != NULL); + + while(r > 0) { + --r; + pf1[r] -= pf2[r]; + } +} + +template inline T normsqr(T* pf1, int r) +{ + assert( pf1 != NULL ); + + T d = 0.0; + while(r > 0) { + --r; + d += pf1[r] * pf1[r]; + } + + return d; +} + +template inline T lengthsqr(T* pf1, T* pf2, int length) +{ + T d = 0; + while(length > 0) { + --length; + d += sqr(pf1[length] - pf2[length]); + } + + return d; +} + +template inline T dot(T* pf1, T* pf2, int length) +{ + T d = 0; + while(length > 0) { + --length; + d += pf1[length] * pf2[length]; + } + + return d; +} + +template inline T sum(T* pf, int length) +{ + T d = 0; + while(length > 0) { + --length; + d += pf[length]; + } + + return d; +} + +template inline bool inv2(T* pf, T* pfres) +{ + T fdet = pf[0] * pf[3] - pf[1] * pf[2]; + + if( fabs(fdet) < 1e-16 ) return false; + + fdet = 1 / fdet; + //if( pfdet != NULL ) *pfdet = fdet; + + if( pfres != pf ) { + pfres[0] = fdet * pf[3]; pfres[1] = -fdet * pf[1]; + pfres[2] = -fdet * pf[2]; pfres[3] = fdet * pf[0]; + return true; + } + + dReal ftemp = pf[0]; + pfres[0] = pf[3] * fdet; + pfres[1] *= -fdet; + pfres[2] *= -fdet; + pfres[3] = ftemp * pf[0]; + + return true; +} + +#endif diff --git a/plugins/zzogl-pg/opengl/zpipe.cpp b/plugins/zzogl-pg/opengl/zpipe.cpp new file mode 100644 index 0000000000..3dc4b17d6c --- /dev/null +++ b/plugins/zzogl-pg/opengl/zpipe.cpp @@ -0,0 +1,115 @@ +// zpipe.cpp : Defines the entry point for the console application. +// + +#include + +#include +#include +#include + +//#define ZLIB_WINAPI +#include "zlib.h" + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress) ; + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) +{ + z_stream strm; + + int ret;//, flush; + unsigned have; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION) ; + if (ret != Z_OK) + return ret; + + /* compress */ + strm.avail_in = bytes_to_compress ; + strm.avail_out = bytes_to_compress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + + ret = deflate(&strm, Z_FINISH) ; + have = bytes_to_compress - strm.avail_out ; + *bytes_after_compressed = have ; + + assert(ret == Z_STREAM_END); /* stream will be complete */ + + /* clean up and return */ + (void)deflateEnd(&strm); + return Z_OK; +} + +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes) +{ + z_stream strm; + + int ret; + //unsigned have; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + if (ret != Z_OK) + return ret; + + /* decompress */ + strm.avail_in = bytes_to_decompress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + strm.avail_out = maximum_after_decompress ; + + ret = inflate(&strm, Z_NO_FLUSH) ; + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return ret; + } + + assert(strm.avail_in == 0); /* all input will be used */ + + if( outbytes != NULL ) + *outbytes = strm.total_out; + + /* clean up and return */ + (void)inflateEnd(&strm); + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + +/* report a zlib or i/o error */ +void zerr(int ret) +{ + fputs("zpipe: ", stderr); + switch (ret) { + case Z_ERRNO: + if (ferror(stdin)) + fputs("error reading stdin\n", stderr); + if (ferror(stdout)) + fputs("error writing stdout\n", stderr); + break; + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + } +} diff --git a/plugins/zzogl-pg/opengl/zpipe.h b/plugins/zzogl-pg/opengl/zpipe.h new file mode 100644 index 0000000000..2b3f8b3262 --- /dev/null +++ b/plugins/zzogl-pg/opengl/zpipe.h @@ -0,0 +1,7 @@ +#ifndef zpipe_h +#define zpipe_h + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes); + +#endif