From 2b987923af2b5c5f18d2f05afe9129016afc2311 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Thu, 13 Nov 2014 20:52:55 +0600 Subject: [PATCH] Add GLideNHQ module. --- GLideNHQ/CMakeLists.txt | 87 + GLideNHQ/Ext_TxFilter.cpp | 172 + GLideNHQ/Ext_TxFilter.h | 211 ++ GLideNHQ/GlideHQ.rc | 79 + GLideNHQ/Makefile.gcc | 126 + GLideNHQ/Makefile.vc8 | 144 + GLideNHQ/README.txt | 94 + GLideNHQ/TextureFilters.cpp | 715 +++++ GLideNHQ/TextureFilters.h | 81 + GLideNHQ/TextureFilters_2xsai.cpp | 155 + GLideNHQ/TextureFilters_2xsai.h | 145 + GLideNHQ/TextureFilters_hq2x.cpp | 1510 +++++++++ GLideNHQ/TextureFilters_hq2x.h | 1847 +++++++++++ GLideNHQ/TextureFilters_hq4x.cpp | 892 +++++ GLideNHQ/TextureFilters_hq4x.h | 4999 +++++++++++++++++++++++++++++ GLideNHQ/TextureFilters_lq2x.h | 1307 ++++++++ GLideNHQ/TxCache.cpp | 449 +++ GLideNHQ/TxCache.h | 69 + GLideNHQ/TxDbg.cpp | 75 + GLideNHQ/TxDbg.h | 61 + GLideNHQ/TxFilter.cpp | 683 ++++ GLideNHQ/TxFilter.h | 81 + GLideNHQ/TxFilterExport.cpp | 106 + GLideNHQ/TxHiResCache.cpp | 1080 +++++++ GLideNHQ/TxHiResCache.h | 60 + GLideNHQ/TxImage.cpp | 799 +++++ GLideNHQ/TxImage.h | 116 + GLideNHQ/TxInternal.h | 100 + GLideNHQ/TxQuantize.cpp | 2394 ++++++++++++++ GLideNHQ/TxQuantize.h | 99 + GLideNHQ/TxReSample.cpp | 417 +++ GLideNHQ/TxReSample.h | 45 + GLideNHQ/TxTexCache.cpp | 79 + GLideNHQ/TxTexCache.h | 39 + GLideNHQ/TxUtil.cpp | 1006 ++++++ GLideNHQ/TxUtil.h | 121 + GLideNHQ/bldno.cpp | 27 + GLideNHQ/bldno.h | 2 + GLideNHQ/gpl-2.0.txt | 339 ++ GLideNHQ/inc/png.h | 2686 ++++++++++++++++ GLideNHQ/inc/pngconf.h | 1510 +++++++++ GLideNHQ/inc/zconf.h | 332 ++ GLideNHQ/inc/zlib.h | 1357 ++++++++ GLideNHQ/lib/dxtn.lib | Bin 0 -> 126254 bytes GLideNHQ/lib/dxtnd.lib | Bin 0 -> 67224 bytes GLideNHQ/lib/libpng.lib | Bin 0 -> 322288 bytes GLideNHQ/lib/libpngd.lib | Bin 0 -> 923454 bytes GLideNHQ/lib/zlib.lib | Bin 0 -> 113904 bytes GLideNHQ/lib/zlibd.lib | Bin 0 -> 252172 bytes GLideNHQ/tc-1.1+/Makefile.gcc | 94 + GLideNHQ/tc-1.1+/Makefile.vc8 | 143 + GLideNHQ/tc-1.1+/dxtn.c | 884 +++++ GLideNHQ/tc-1.1+/dxtn.h | 62 + GLideNHQ/tc-1.1+/fxt1.c | 1459 +++++++++ GLideNHQ/tc-1.1+/fxt1.h | 38 + GLideNHQ/tc-1.1+/fxt1license.txt | 244 ++ GLideNHQ/tc-1.1+/internal.h | 137 + GLideNHQ/tc-1.1+/texstore.c | 93 + GLideNHQ/tc-1.1+/types.h | 11 + GLideNHQ/tc-1.1+/wrapper.c | 110 + GLideNHQ/test/Makefile.gcc | 70 + GLideNHQ/test/Makefile.vc8 | 68 + GLideNHQ/test/test.cpp | 120 + 63 files changed, 30229 insertions(+) create mode 100644 GLideNHQ/CMakeLists.txt create mode 100644 GLideNHQ/Ext_TxFilter.cpp create mode 100644 GLideNHQ/Ext_TxFilter.h create mode 100644 GLideNHQ/GlideHQ.rc create mode 100644 GLideNHQ/Makefile.gcc create mode 100644 GLideNHQ/Makefile.vc8 create mode 100644 GLideNHQ/README.txt create mode 100644 GLideNHQ/TextureFilters.cpp create mode 100644 GLideNHQ/TextureFilters.h create mode 100644 GLideNHQ/TextureFilters_2xsai.cpp create mode 100644 GLideNHQ/TextureFilters_2xsai.h create mode 100644 GLideNHQ/TextureFilters_hq2x.cpp create mode 100644 GLideNHQ/TextureFilters_hq2x.h create mode 100644 GLideNHQ/TextureFilters_hq4x.cpp create mode 100644 GLideNHQ/TextureFilters_hq4x.h create mode 100644 GLideNHQ/TextureFilters_lq2x.h create mode 100644 GLideNHQ/TxCache.cpp create mode 100644 GLideNHQ/TxCache.h create mode 100644 GLideNHQ/TxDbg.cpp create mode 100644 GLideNHQ/TxDbg.h create mode 100644 GLideNHQ/TxFilter.cpp create mode 100644 GLideNHQ/TxFilter.h create mode 100644 GLideNHQ/TxFilterExport.cpp create mode 100644 GLideNHQ/TxHiResCache.cpp create mode 100644 GLideNHQ/TxHiResCache.h create mode 100644 GLideNHQ/TxImage.cpp create mode 100644 GLideNHQ/TxImage.h create mode 100644 GLideNHQ/TxInternal.h create mode 100644 GLideNHQ/TxQuantize.cpp create mode 100644 GLideNHQ/TxQuantize.h create mode 100644 GLideNHQ/TxReSample.cpp create mode 100644 GLideNHQ/TxReSample.h create mode 100644 GLideNHQ/TxTexCache.cpp create mode 100644 GLideNHQ/TxTexCache.h create mode 100644 GLideNHQ/TxUtil.cpp create mode 100644 GLideNHQ/TxUtil.h create mode 100644 GLideNHQ/bldno.cpp create mode 100644 GLideNHQ/bldno.h create mode 100644 GLideNHQ/gpl-2.0.txt create mode 100644 GLideNHQ/inc/png.h create mode 100644 GLideNHQ/inc/pngconf.h create mode 100644 GLideNHQ/inc/zconf.h create mode 100644 GLideNHQ/inc/zlib.h create mode 100644 GLideNHQ/lib/dxtn.lib create mode 100644 GLideNHQ/lib/dxtnd.lib create mode 100644 GLideNHQ/lib/libpng.lib create mode 100644 GLideNHQ/lib/libpngd.lib create mode 100644 GLideNHQ/lib/zlib.lib create mode 100644 GLideNHQ/lib/zlibd.lib create mode 100644 GLideNHQ/tc-1.1+/Makefile.gcc create mode 100644 GLideNHQ/tc-1.1+/Makefile.vc8 create mode 100644 GLideNHQ/tc-1.1+/dxtn.c create mode 100644 GLideNHQ/tc-1.1+/dxtn.h create mode 100644 GLideNHQ/tc-1.1+/fxt1.c create mode 100644 GLideNHQ/tc-1.1+/fxt1.h create mode 100644 GLideNHQ/tc-1.1+/fxt1license.txt create mode 100644 GLideNHQ/tc-1.1+/internal.h create mode 100644 GLideNHQ/tc-1.1+/texstore.c create mode 100644 GLideNHQ/tc-1.1+/types.h create mode 100644 GLideNHQ/tc-1.1+/wrapper.c create mode 100644 GLideNHQ/test/Makefile.gcc create mode 100644 GLideNHQ/test/Makefile.vc8 create mode 100644 GLideNHQ/test/test.cpp diff --git a/GLideNHQ/CMakeLists.txt b/GLideNHQ/CMakeLists.txt new file mode 100644 index 00000000..f51f5b9c --- /dev/null +++ b/GLideNHQ/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 2.6) + +project( GLideNHQ ) + +set(GLideNHQ_SOURCES + Ext_TxFilter.cpp + TextureFilters.cpp + TextureFilters_2xsai.cpp + TextureFilters_hq2x.cpp + TextureFilters_hq4x.cpp + TxCache.cpp + TxDbg.cpp + TxFilter.cpp + TxFilterExport.cpp + TxHiResCache.cpp + TxImage.cpp + TxQuantize.cpp + TxReSample.cpp + TxTexCache.cpp + TxUtil.cpp +) + +include_directories( inc ) + +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_MULTITHREADED ON) +find_package(Boost COMPONENTS thread filesystem system REQUIRED) +include_directories(${Boost_INCLUDE_DIRS}) + +if(WIN32) + LINK_DIRECTORIES( lib ) + add_definitions( + -DWIN32 + -D_CRT_SECURE_NO_WARNINGS + ) +endif(WIN32) + + +if (WIN32 AND __COMPILER_GNU) + # mingw-gcc fails to link boost::thread + add_definitions(-DBOOST_THREAD_USE_LIB) +endif (WIN32 AND __COMPILER_GNU) + +# Build type + +if( NOT CMAKE_BUILD_TYPE) + set( CMAKE_BUILD_TYPE Release) +endif( NOT CMAKE_BUILD_TYPE) + +if( CMAKE_BUILD_TYPE STREQUAL "Debug") + set( CMAKE_BUILD_TYPE Debug) + set( DEBUG_BUILD TRUE) + add_definitions( + -DDEBUG + ) +endif( CMAKE_BUILD_TYPE STREQUAL "Debug") + +find_package(OpenGL REQUIRED) +include_directories(${OpenGL_INCLUDE_DIRS}) +link_directories(${OpenGL_LIBRARY_DIRS}) +add_definitions(${OpenGL_DEFINITIONS}) +if(NOT OPENGL_FOUND) + message(ERROR " OPENGL not found!") +endif(NOT OPENGL_FOUND) + +SET(GCC_CPP11_COMPILE_FLAGS "-std=c++0x -static-libgcc -static-libstdc++") +SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_CPP11_COMPILE_FLAGS}" ) +SET(GCC_STATIC_LINK_FLAGS "-static-libgcc -static-libstdc++") +SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_STATIC_LINK_FLAGS}" ) + +add_library( GLideNHQ STATIC ${GLideNHQ_SOURCES}) + +SET_TARGET_PROPERTIES( + GLideNHQ + PROPERTIES + LINKER_LANGUAGE CXX # Or else we get an error message, because cmake can't figure out from the ".o"-suffix that it is a C-linker we need. + PREFIX "" + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/plugin + ) + +if( CMAKE_BUILD_TYPE STREQUAL "Debug") +target_link_libraries(GLideNHQ ${OPENGL_LIBRARIES} ${Boost_LIBRARIES} libpng zlib ) +endif( CMAKE_BUILD_TYPE STREQUAL "Debug") + +if( CMAKE_BUILD_TYPE STREQUAL "Release") +target_link_libraries(GLideNHQ ${OPENGL_LIBRARIES} ${Boost_LIBRARIES} libpngd zlibd ) +endif( CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/GLideNHQ/Ext_TxFilter.cpp b/GLideNHQ/Ext_TxFilter.cpp new file mode 100644 index 00000000..171e03b8 --- /dev/null +++ b/GLideNHQ/Ext_TxFilter.cpp @@ -0,0 +1,172 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include "Ext_TxFilter.h" + +typedef boolean (*txfilter_init)(int maxwidth, int maxheight, int maxbpp, + int options, int cachesize, + wchar_t *path, wchar_t *ident, + dispInfoFuncExt callback); + +typedef void (*txfilter_shutdown)(void); + +typedef boolean (*txfilter_filter)(unsigned char *src, int srcwidth, int srcheight, unsigned short srcformat, + uint64 g64crc, GHQTexInfo *info); + +typedef boolean (*txfilter_hirestex)(uint64 g64crc, uint64 r_crc64, unsigned short *palette, GHQTexInfo *info); + +typedef uint64 (*txfilter_checksum)(unsigned char *src, int width, int height, int size, int rowStride, unsigned char *palette); + +typedef boolean (*txfilter_dmptx)(unsigned char *src, int width, int height, int rowStridePixel, unsigned short gfmt, unsigned short n64fmt, uint64 r_crc64); + +typedef boolean (*txfilter_reloadhirestex)(); + +static struct { + TXHMODULE lib; + txfilter_init init; + txfilter_shutdown shutdown; + txfilter_filter filter; + txfilter_hirestex hirestex; + txfilter_checksum checksum; + txfilter_dmptx dmptx; + txfilter_reloadhirestex reloadhirestex; +} txfilter; + +void ext_ghq_shutdown(void) +{ + if (txfilter.shutdown) + (*txfilter.shutdown)(); + + if (txfilter.lib) { + DLCLOSE(txfilter.lib); + memset(&txfilter, 0, sizeof(txfilter)); + } +} + +boolean ext_ghq_init(int maxwidth, int maxheight, int maxbpp, int options, int cachesize, + wchar_t *path, wchar_t *ident, + dispInfoFuncExt callback) +{ + boolean bRet = 0; + + if (!txfilter.lib) { + wchar_t curpath[MAX_PATH]; + wcscpy(curpath, path); +#ifdef WIN32 +#ifdef GHQCHK + wcscat(curpath, L"\\ghqchk.dll"); +#else + wcscat(curpath, L"\\GlideHQ.dll"); +#endif + txfilter.lib = DLOPEN(curpath); +#else + char cbuf[MAX_PATH]; +#ifdef GHQCHK + wcscat(curpath, L"/ghqchk.so"); +#else + wcscat(curpath, L"/GlideHQ.so"); +#endif + wcstombs(cbuf, curpath, MAX_PATH); + txfilter.lib = DLOPEN(cbuf); +#endif + } + + if (txfilter.lib) { + if (!txfilter.init) + txfilter.init = (txfilter_init)DLSYM(txfilter.lib, "txfilter_init"); + if (!txfilter.shutdown) + txfilter.shutdown = (txfilter_shutdown)DLSYM(txfilter.lib, "txfilter_shutdown"); + if (!txfilter.filter) + txfilter.filter = (txfilter_filter)DLSYM(txfilter.lib, "txfilter"); + if (!txfilter.hirestex) + txfilter.hirestex = (txfilter_hirestex)DLSYM(txfilter.lib, "txfilter_hirestex"); + if (!txfilter.checksum) + txfilter.checksum = (txfilter_checksum)DLSYM(txfilter.lib, "txfilter_checksum"); + if (!txfilter.dmptx) + txfilter.dmptx = (txfilter_dmptx)DLSYM(txfilter.lib, "txfilter_dmptx"); + if (!txfilter.reloadhirestex) + txfilter.reloadhirestex = (txfilter_reloadhirestex)DLSYM(txfilter.lib, "txfilter_reloadhirestex"); + } + + if (txfilter.init && txfilter.shutdown && txfilter.filter && + txfilter.hirestex && txfilter.checksum /*&& txfilter.dmptx && txfilter.reloadhirestex */) + bRet = (*txfilter.init)(maxwidth, maxheight, maxbpp, options, cachesize, path, ident, callback); + else + ext_ghq_shutdown(); + + return bRet; +} + +boolean ext_ghq_txfilter(unsigned char *src, int srcwidth, int srcheight, unsigned short srcformat, + uint64 g64crc, GHQTexInfo *info) +{ + boolean ret = 0; + + if (txfilter.filter) + ret = (*txfilter.filter)(src, srcwidth, srcheight, srcformat, + g64crc, info); + + return ret; +} + +boolean ext_ghq_hirestex(uint64 g64crc, uint64 r_crc64, unsigned short *palette, GHQTexInfo *info) +{ + boolean ret = 0; + + if (txfilter.hirestex) + ret = (*txfilter.hirestex)(g64crc, r_crc64, palette, info); + + return ret; +} + +uint64 ext_ghq_checksum(unsigned char *src, int width, int height, int size, int rowStride, unsigned char *palette) +{ + uint64 ret = 0; + + if (txfilter.checksum) + ret = (*txfilter.checksum)(src, width, height, size, rowStride, palette); + + return ret; +} + +boolean ext_ghq_dmptx(unsigned char *src, int width, int height, int rowStridePixel, unsigned short gfmt, unsigned short n64fmt, uint64 r_crc64) +{ + boolean ret = 0; + + if (txfilter.dmptx) + ret = (*txfilter.dmptx)(src, width, height, rowStridePixel, gfmt, n64fmt, r_crc64); + + return ret; +} + +boolean ext_ghq_reloadhirestex() +{ + boolean ret = 0; + + if (txfilter.reloadhirestex) + ret = (*txfilter.reloadhirestex)(); + + return ret; +} diff --git a/GLideNHQ/Ext_TxFilter.h b/GLideNHQ/Ext_TxFilter.h new file mode 100644 index 00000000..2ea585a8 --- /dev/null +++ b/GLideNHQ/Ext_TxFilter.h @@ -0,0 +1,211 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __EXT_TXFILTER_H__ +#define __EXT_TXFILTER_H__ + +#ifdef WIN32 +#include +#define TXHMODULE HMODULE +#define DLOPEN(a) LoadLibraryW(a) +#define DLCLOSE(a) FreeLibrary(a) +#define DLSYM(a, b) GetProcAddress(a, b) +#define GETCWD(a, b) GetCurrentDirectoryW(a, b) +#define CHDIR(a) SetCurrentDirectoryW(a) +#else +#include +#include +#define MAX_PATH 4095 +#define TXHMODULE void* +#define DLOPEN(a) dlopen(a, RTLD_LAZY|RTLD_GLOBAL) +#define DLCLOSE(a) dlclose(a) +#define DLSYM(a, b) dlsym(a, b) +#define GETCWD(a, b) getcwd(b, a) +#define CHDIR(a) chdir(a) +#endif + +#ifdef __MSC__ +typedef __int64 int64; +typedef unsigned __int64 uint64; +#else +typedef long long int64; +typedef unsigned long long uint64; +typedef unsigned char boolean; +#endif + +#define NO_OPTIONS 0x00000000 + +#define FILTER_MASK 0x000000ff +#define NO_FILTER 0x00000000 +#define SMOOTH_FILTER_MASK 0x0000000f +#define NO_SMOOTH_FILTER 0x00000000 +#define SMOOTH_FILTER_1 0x00000001 +#define SMOOTH_FILTER_2 0x00000002 +#define SMOOTH_FILTER_3 0x00000003 +#define SMOOTH_FILTER_4 0x00000004 +#define SHARP_FILTER_MASK 0x000000f0 +#define NO_SHARP_FILTER 0x00000000 +#define SHARP_FILTER_1 0x00000010 +#define SHARP_FILTER_2 0x00000020 + +#define ENHANCEMENT_MASK 0x00000f00 +#define NO_ENHANCEMENT 0x00000000 +#define X2_ENHANCEMENT 0x00000100 +#define X2SAI_ENHANCEMENT 0x00000200 +#define HQ2X_ENHANCEMENT 0x00000300 +#define LQ2X_ENHANCEMENT 0x00000400 +#define HQ4X_ENHANCEMENT 0x00000500 +#define HQ2XS_ENHANCEMENT 0x00000600 +#define LQ2XS_ENHANCEMENT 0x00000700 + +#define COMPRESSION_MASK 0x0000f000 +#define NO_COMPRESSION 0x00000000 +#define FXT1_COMPRESSION 0x00001000 +#define NCC_COMPRESSION 0x00002000 +#define S3TC_COMPRESSION 0x00003000 + +#define HIRESTEXTURES_MASK 0x000f0000 +#define NO_HIRESTEXTURES 0x00000000 +#define GHQ_HIRESTEXTURES 0x00010000 +#define RICE_HIRESTEXTURES 0x00020000 +#define JABO_HIRESTEXTURES 0x00030000 + +#define COMPRESS_TEX 0x00100000 +#define COMPRESS_HIRESTEX 0x00200000 +#define GZ_TEXCACHE 0x00400000 +#define GZ_HIRESTEXCACHE 0x00800000 +#define DUMP_TEXCACHE 0x01000000 +#define DUMP_HIRESTEXCACHE 0x02000000 +#define TILE_HIRESTEX 0x04000000 +#define UNDEFINED_0 0x08000000 +#define FORCE16BPP_HIRESTEX 0x10000000 +#define FORCE16BPP_TEX 0x20000000 +#define LET_TEXARTISTS_FLY 0x40000000 /* a little freedom for texture artists */ +#define DUMP_TEX 0x80000000 + +#ifndef __GLIDE_H__ /* GLIDE3 */ +/* from 3Dfx Interactive Inc. glide.h */ +#define GR_TEXFMT_ALPHA_8 0x2 +#define GR_TEXFMT_INTENSITY_8 0x3 + +#define GR_TEXFMT_ALPHA_INTENSITY_44 0x4 +#define GR_TEXFMT_P_8 0x5 + +#define GR_TEXFMT_RGB_565 0xa +#define GR_TEXFMT_ARGB_1555 0xb +#define GR_TEXFMT_ARGB_4444 0xc +#define GR_TEXFMT_ALPHA_INTENSITY_88 0xd + +/* from 3Dfx Interactive Inc. g3ext.h */ +#define GR_TEXFMT_ARGB_CMP_FXT1 0x11 + +#define GR_TEXFMT_ARGB_8888 0x12 + +#define GR_TEXFMT_ARGB_CMP_DXT1 0x16 +#define GR_TEXFMT_ARGB_CMP_DXT3 0x18 +#define GR_TEXFMT_ARGB_CMP_DXT5 0x1A +#endif /* GLIDE3 */ + +struct GHQTexInfo { + unsigned char *data; + int width; + int height; + unsigned short format; + + int smallLodLog2; + int largeLodLog2; + int aspectRatioLog2; + + int tiles; + int untiled_width; + int untiled_height; + + unsigned char is_hires_tex; +}; + +/* Callback to display hires texture info. + * Gonetz + * + * void DispInfo(const char *format, ...) + * { + * va_list args; + * char buf[INFO_BUF]; + * + * va_start(args, format); + * vsprintf(buf, format, args); + * va_end(args); + * + * printf(buf); + * } + */ +#define INFO_BUF 4095 +typedef void (*dispInfoFuncExt)(const wchar_t *format, ...); + +#ifndef TXFILTER_DLL +boolean ext_ghq_init(int maxwidth, /* maximum texture width supported by hardware */ + int maxheight,/* maximum texture height supported by hardware */ + int maxbpp, /* maximum texture bpp supported by hardware */ + int options, /* options */ + int cachesize,/* cache textures to system memory */ + wchar_t *path, /* plugin directory. must be smaller than MAX_PATH */ + wchar_t *ident, /* name of ROM. must be no longer than 64 in character. */ + dispInfoFuncExt callback /* callback function to display info */ + ); + +void ext_ghq_shutdown(void); + +boolean ext_ghq_txfilter(unsigned char *src, /* input texture */ + int srcwidth, /* width of input texture */ + int srcheight, /* height of input texture */ + unsigned short srcformat, /* format of input texture */ + uint64 g64crc, /* glide64 crc */ + GHQTexInfo *info /* output */ + ); + +boolean ext_ghq_hirestex(uint64 g64crc, /* glide64 crc */ + uint64 r_crc64, /* checksum hi:palette low:texture */ + unsigned short *palette, /* palette for CI textures */ + GHQTexInfo *info /* output */ + ); + +uint64 ext_ghq_checksum(unsigned char *src, /* input texture */ + int width, /* width of texture */ + int height, /* height of texture */ + int size, /* type of texture pixel */ + int rowStride, /* row stride in bytes */ + unsigned char *palette /* palette */ + ); + +boolean ext_ghq_dmptx(unsigned char *src, /* input texture (must be in 3Dfx Glide format) */ + int width, /* width of texture */ + int height, /* height of texture */ + int rowStridePixel, /* row stride of input texture in pixels */ + unsigned short gfmt, /* glide format of input texture */ + unsigned short n64fmt,/* N64 format hi:format low:size */ + uint64 r_crc64 /* checksum hi:palette low:texture */ + ); + +boolean ext_ghq_reloadhirestex(); +#endif /* TXFILTER_DLL */ + +#endif /* __EXT_TXFILTER_H__ */ diff --git a/GLideNHQ/GlideHQ.rc b/GLideNHQ/GlideHQ.rc new file mode 100644 index 00000000..9346c06e --- /dev/null +++ b/GLideNHQ/GlideHQ.rc @@ -0,0 +1,79 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "bldno.h" + +#define ID(id) id + +#define VS_FILE_INFO ID(16) /* Version stamp res type */ +#define VS_VERSION_INFO ID(1) /* Version stamp res ID */ +#define VS_USER_DEFINED ID(100) /* User-defined res IDs */ + +#define VOS_DOS_WINDOWS32 0x00010004L +#define VFT_DLL 0x00000002L +#define VER_PRERELEASE 0 +#define VER_PRIVATEBUILD 0 +#define VER_DEBUG 0 + +#define VERSIONNAME "GlideHQ.dll\0" +#define PRODNAME "GlideHQ\0" +#define DESCRIPT "Texture filtering DLL\0" +#define COPYRIGHTSTR "Copyright (C) 2007 Hiroshi Morii\0" +#define CONTACTSTR "Hiroshi Morii http://www.3dfxzone.it/koolsmoky\0" + +#define MANVERSION 1 +#define MANREVISION 02 +#define MINVERSION 00 + +#define VERSIONSTR "1.02.00." BUILD_NUMBER_STR + +VS_VERSION_INFO VERSIONINFO + FILEVERSION MANVERSION, MANREVISION, 0, BUILD_NUMBER + PRODUCTVERSION MANVERSION, MANREVISION, 0, BUILD_NUMBER + FILEFLAGSMASK 0x0030003FL + FILEFLAGS (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG) + + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "FileDescription", DESCRIPT + VALUE "FileVersion", VERSIONSTR + VALUE "InternalName", VERSIONNAME + VALUE "LegalCopyright", COPYRIGHTSTR + VALUE "OriginalFilename", VERSIONNAME + VALUE "ProductName", PRODNAME + VALUE "ProductVersion", VERSIONSTR + VALUE "Contact", CONTACTSTR + END + END + BLOCK "VarFileInfo" + BEGIN + /* the following line should be extended for localized versions */ + VALUE "Translation", 0x409, 1252 + END +END diff --git a/GLideNHQ/Makefile.gcc b/GLideNHQ/Makefile.gcc new file mode 100644 index 00000000..e4fa1aef --- /dev/null +++ b/GLideNHQ/Makefile.gcc @@ -0,0 +1,126 @@ +# This MUST be processed by GNU make +# +# Texture Filtering Linux Makefile +# Version: 1.0 +# +# Copyright (C) 2007 Hiroshi Morii All Rights Reserved. +# Email koolsmoky(at)users.sourceforge.net +# Web http://www.3dfxzone.it/koolsmoky +# +# this is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# this is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Make; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# Available options: +# +# Environment variables: +# DEBUG=1 enable debugging checks and messages +# default = no +# +# Environment variables: +# +# Targets: +# all: build dynamic module +# clean: remove object files +# realclean: remove all generated files +# +# +# Requirements: +# +# Compiler: +# GCC 4.2 +# +# Libraries: +# boost 1.41.0 (http://www.boost.org) bjam --toolset=gcc link=static runtime-link=static variant=release,debug stage +# libpng 1.4.1 (http://www.libpng.org) static library +# zlib 1.2.3 (http://www.zlib.org) static library +# tc 1.1+ patched for ARGB input and ATI Radeon workaround +# + +# +# GCC does not have SEH (structured exception handling) +# + +.PHONY: all clean realclean + +DLLNAME = GlideHQ.so + +# libpng and zlib headers & libraries +EXT_INC = ./inc +EXT_LIB = ./lib + +# boost library & headers +BOOST_INC = ../boost_1_41_0 +BOOST_LIB = ../boost_1_41_0/stage/lib + +CC = g++ +CFLAGS = -Wall -W -pedantic -ansi -Wno-long-long +CFLAGS += -O3 -ffast-math -funroll-loops +#CFLAGS += -fexpensive-optimizations -march=k6 +CFLAGS += -I. -I$(EXT_INC) -I$(BOOST_INC) +CFLAGS += -fPIC -DPIC +#CFLAGS += -DTXFILTER_DLL + +ifdef DEBUG +CFLAGS += -DDEBUG +endif + +LD = g++ +LDFLAGS = -shared -lstdc++ -lpthread +LDLIBS = $(EXT_LIB)/libdxtn.a $(EXT_LIB)/libpng.a $(EXT_LIB)/libz.a $(BOOST_LIB)/libboost_filesystem-gcc42-mt-s.a $(BOOST_LIB)/libboost_system-gcc42-mt-s.a $(BOOST_LIB)/libboost_thread-gcc42-mt-s.a + +RM = rm + +SOURCES = \ + TxFilterExport.cpp \ + TxFilter.cpp \ + TxCache.cpp \ + TxTexCache.cpp \ + TxHiResCache.cpp \ + TxQuantize.cpp \ + TxUtil.cpp \ + TextureFilters.cpp \ + TextureFilters_2xsai.cpp \ + TextureFilters_hq2x.cpp \ + TextureFilters_hq4x.cpp \ + TxImage.cpp \ + TxReSample.cpp \ + TxDbg.cpp + +OBJECTS = $(SOURCES:.cpp=.o) + +.cpp.o: + $(CC) -o $@ $(CFLAGS) -c $< + +all: $(DLLNAME) + +$(DLLNAME): $(OBJECTS) + $(LD) -o $@ $(LDFLAGS) $^ $(LDLIBS) + +$(OBJECTS): $(SOURCES) bldno.h + +bldno.h: bldno.exe + ./$< > $@ + +bldno.exe: bldno.cpp + $(CC) -o $@ $(CFLAGS) $< + +clean: + -$(RM) *.o + +realclean: clean + -$(RM) $(DLLNAME) bldno.exe bldno.h + +-include depend diff --git a/GLideNHQ/Makefile.vc8 b/GLideNHQ/Makefile.vc8 new file mode 100644 index 00000000..5fe03263 --- /dev/null +++ b/GLideNHQ/Makefile.vc8 @@ -0,0 +1,144 @@ +# This MUST be processed by GNU make +# +# Texture Filtering MSVC Makefile +# Version: 1.0 +# +# Copyright (C) 2007 Hiroshi Morii All Rights Reserved. +# Email koolsmoky(at)users.sourceforge.net +# Web http://www.3dfxzone.it/koolsmoky +# +# this is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# this is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Make; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# Available options: +# +# Environment variables: +# DEBUG=1 enable debugging checks and messages +# default = no +# +# Targets: +# all: build everything +# clean: remove object files +# realclean: remove all generated files +# +# +# Requirements: +# +# Compiler: +# Microsoft VisualC++ 8.0 (VS2005) +# +# Libraries: +# boost 1.41.0 (http://www.boost.org) bjam --toolset=msvc-8.0 link=static runtime-link=static variant=release,debug stage +# libpng 1.4.1 (http://www.libpng.org) built with /MT or /MTd switch +# zlib 1.2.3 (http://www.zlib.org) built with /MT or /MTd switch +# tc 1.1+ patched for ARGB input and ATI Radeon workaround +# +# All libraries must be built with /MT or /MTd switch and statically linked. +# If you need any help feel free to drop me a line. +# + +.PHONY: all clean realclean +.SUFFIXES: .cpp .obj .rc .res + +# RESNAME = txfilter.res +# DLLNAME = txfilter.dll +# LIBNAME = txfilter.lib +# EXPNAME = txfilter.exp +RESNAME = GlideHQ.res +DLLNAME = GlideHQ.dll +LIBNAME = GlideHQ.lib +EXPNAME = GlideHQ.exp + +# libpng and zlib headers & libraries +EXT_INC = ./inc +EXT_LIB = ./lib + +# boost library & headers +BOOST_INC = ../boost_1_41_0 +BOOST_LIB = ../boost_1_41_0/stage/lib + +CC = cl +AS = nasm +LD = _link # change this to suite your build environment +RC = rc + +UNLINK = $(RM) $(1) + +LDFLAGS = -nologo -dll -opt:WIN98 -machine:X86 -nodefaultlib + +ASFLAGS = -O6 -fwin32 -D__WIN32__ --prefix _ +ASFLAGS += $(CDEFS) + +CFLAGS = -nologo -W3 -WX -D__MSC__ -DWIN32 -D_WINDOWS -D_WINDLL -EHa -D_CRT_SECURE_NO_DEPRECATE -DTXFILTER_DLL + +LDLIBS = user32.lib kernel32.lib +ifdef DEBUG +CFLAGS += -Zi -DDEBUG -MTd +LDLIBS += $(EXT_LIB)/dxtnd.lib $(EXT_LIB)/libpngd.lib $(EXT_LIB)/zlibd.lib LIBCMTD.LIB LIBCPMTD.LIB $(BOOST_LIB)/libboost_filesystem-vc80-mt-sgd.lib $(BOOST_LIB)/libboost_system-vc80-mt-sgd.lib $(BOOST_LIB)/libboost_thread-vc80-mt-sgd.lib +OPTFLAGS ?= -Od +else +CFLAGS += -DNDEBUG -GL -MT +LDFLAGS += -ltcg:STATUS +LDLIBS += $(EXT_LIB)/dxtn.lib $(EXT_LIB)/libpng.lib $(EXT_LIB)/zlib.lib LIBCMT.LIB LIBCPMT.LIB $(BOOST_LIB)/libboost_filesystem-vc80-mt-s.lib $(BOOST_LIB)/libboost_system-vc80-mt-s.lib $(BOOST_LIB)/libboost_thread-vc80-mt-s.lib +OPTFLAGS ?= -O2 +endif + +CFLAGS += -I. -I$(EXT_INC) -I$(BOOST_INC) +CFLAGS += $(CDEFS) $(OPTFLAGS) + +SOURCES = \ + TxFilterExport.cpp \ + TxFilter.cpp \ + TxCache.cpp \ + TxTexCache.cpp \ + TxHiResCache.cpp \ + TxQuantize.cpp \ + TxUtil.cpp \ + TextureFilters.cpp \ + TextureFilters_2xsai.cpp \ + TextureFilters_hq2x.cpp \ + TextureFilters_hq4x.cpp \ + TxImage.cpp \ + TxReSample.cpp \ + TxDbg.cpp + + +OBJECTS = $(SOURCES:.cpp=.obj) + +.cpp.obj: + $(CC) -Fo$@ $(CFLAGS) -c $< + +.rc.res: + $(RC) -Fo$@ $(CDEFS) $< + +all: $(DLLNAME) + +$(DLLNAME): $(OBJECTS) $(RESNAME) + $(LD) -out:$@ $(LDFLAGS) $(OBJECTS) $(LDLIBS) $(RESNAME) + +$(OBJECTS): $(SOURCES) bldno.h + +bldno.h: bldno.exe + ./$< > $@ + +bldno.exe: bldno.cpp + $(CC) -o $@ $(CFLAGS) $< + +clean: + -$(RM) *.obj *.pdb $(RESNAME) bldno.h *.ilk + +realclean: clean + -$(RM) $(DLLNAME) $(LIBNAME) $(EXPNAME) bldno.exe diff --git a/GLideNHQ/README.txt b/GLideNHQ/README.txt new file mode 100644 index 00000000..c903e573 --- /dev/null +++ b/GLideNHQ/README.txt @@ -0,0 +1,94 @@ +/* + * GlideHQ (Texture enhancer library for Glide64) + * Version: 1.5 + * + * Copyright (C) 2007 Hiroshi Morii aka KoolSmoky All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +About: +This is a realtime texture enhancer library with hi-resolution texture +pack support for Glide64 (http://glide64.emuxhaven.net). Traditional and +non-traditional techniques have been used to achieve speed and high image +quality even on a 9 year old 3Dfx Voodoo2. + +Although the 3Dfx Glide3x texture format naming conventions are used, the +library can be expanded for generic use. + +Supported: +OS: 32bit Linux and MS Windows +Enhancers: Hq4x, Hq2x, Hq2xS, Lq2x, Lq2xS, Super2xSai, x2 +Filters: Smooth (1,2,3,4), Sharp (1,2) +Compressors: FXT1, S3TC +Input formats: GR_TEXFMT_ALPHA_8, + GR_TEXFMT_RGB_565, + GR_TEXFMT_ARGB_1555, + GR_TEXFMT_ARGB_4444, + GR_TEXFMT_ARGB_8888, + GR_TEXFMT_ALPHA_INTENSITY_44, + GR_TEXFMT_ALPHA_INTENSITY_88 +Output formats: Same as input unless compression or hires packs are used. +Hires texture packs: Rice format (Jabo and GlideHQ format coming later) + +Acknowledgments: +I hope you enjoy GlideHQ (texture enhancer library for Glide64). Greatest +thanks to Gonetz for making this happen in his busy time. We've rushed +everything to share the eye-candy with all of you N64 emulation fans. I +would also like to thank a great friend of mine, Daniel Borca for providing +the texture compression code, Maxim Stepin (hq2x 4x), and Derek Liauw Kie Fa +(2xSaI) for the filtering engines, Rice for his N64 graphics plugin source +code, and Mudlord for the hq2xS lq2xS code. GlideHQ also uses the boost C++ +libraries, zlib general purpose compression library, and the Portable Network +Graphics library. Thanks to all the developers for making them available. And +special thanks to the Glide64 beta testing crew. Without their feedbacks +this library would not have seen daylight. Thank you all. + +The source code for GlideHQ is released in hopes that it will be improved. +I know the coding is not on par after so much late night caffeine boosts. +If you have suggestions or modifications, please feel free to post them on +the Glide64 forum at emuxhaven. + +Porting the library to other platforms should not be so hard. The coding is +done with cross platform compatibility in mind and will build with GCC and +GNU make. Currently supported are 32bit Linux and MS Windows. + +If you are looking for driver updates for your 3Dfx Interactive Inc. gfx +card, grab them from the forums at http://www.3dfxzone.it/enboard/ +Unbelievable as it seems, drivers are still being updated after 6 years +from 3Dfx's demise. + +I know N64 rules, anyone up for PSX? :)) + +-KoolSmoky + +References: +[1] R.W. Floyd & L. Steinberg, An adaptive algorithm for spatial grey scale, + Proceedings of the Society of Information Display 17, pp75-77, 1976 +[2] Ken Turkowski, Filters for Common Resampling Tasks, Apple Computer 1990 + http://www.worldserver.com/turk/computergraphics/ResamplingFilters.pdf +[3] Don P. Mitchell and Arun N. Netravali, Reconstruction Filters in Computer + Graphics, SIGGRAPH '88, Proceedings of the 15th annual conference on + Computer graphics and interactive techniques, pp221-228, 1988 +[4] J. F. Kaiser and W. A. Reed, Data smoothing using low-pass digital + filters, Rev. Sci. instrum. 48 (11), pp1447-1457, 1977 +[5] Maxim Stepin, hq4x Magnification Filter, http://www.hiend3d.com/hq4x.html +[6] Derek Liauw Kie Fa, 2xSaI, http://elektron.its.tudelft.nl/~dalikifa +[7] Dirk Stevens, Eagle engine http://www.retrofx.com/rfxtech.html +[8] 3DFX_texture_compression_FXT1 and EXT_texture_compression_s3tc extension + specs from the OpenGL Extension Registry. http://oss.sgi.com/projects/ + ogl-sample/registry/ diff --git a/GLideNHQ/TextureFilters.cpp b/GLideNHQ/TextureFilters.cpp new file mode 100644 index 00000000..e0e2d9b4 --- /dev/null +++ b/GLideNHQ/TextureFilters.cpp @@ -0,0 +1,715 @@ +/* +Copyright (C) 2003 Rice1964 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +/* Copyright (C) 2007 Hiroshi Morii + * Modified for the Texture Filtering library + */ + +#include +#include "TextureFilters.h" + +/************************************************************************/ +/* 2X filters */ +/************************************************************************/ + +#define DWORD_MAKE(r, g, b, a) ((uint32) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))) +#define WORD_MAKE(r, g, b, a) ((uint16) (((a) << 12) | ((r) << 8) | ((g) << 4) | (b))) + +// Basic 2x R8G8B8A8 filter with interpolation + +void Texture2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint32 *pDst1, *pDst2; + uint32 *pSrc, *pSrc2; + uint32 nWidth = width; + uint32 nHeight = height; + + uint32 b1; + uint32 g1; + uint32 r1; + uint32 a1; + uint32 b2; + uint32 g2; + uint32 r2; + uint32 a2; + uint32 b3; + uint32 g3; + uint32 r3; + uint32 a3; + uint32 b4; + uint32 g4; + uint32 r4; + uint32 a4; + + uint32 xSrc; + uint32 ySrc; + + for (ySrc = 0; ySrc < nHeight; ySrc++) + { + pSrc = (uint32*)(((uint8*)srcPtr)+ySrc*srcPitch); + pSrc2 = (uint32*)(((uint8*)srcPtr)+(ySrc+1)*srcPitch); + pDst1 = (uint32*)(((uint8*)dstPtr)+(ySrc*2)*dstPitch); + pDst2 = (uint32*)(((uint8*)dstPtr)+(ySrc*2+1)*dstPitch); + + for (xSrc = 0; xSrc < nWidth; xSrc++) + { + b1 = (pSrc[xSrc]>>0)&0xFF; + g1 = (pSrc[xSrc]>>8)&0xFF; + r1 = (pSrc[xSrc]>>16)&0xFF; + a1 = (pSrc[xSrc]>>24)&0xFF; + + if( xSrc>0)&0xFF; + g2 = (pSrc[xSrc+1]>>8)&0xFF; + r2 = (pSrc[xSrc+1]>>16)&0xFF; + a2 = (pSrc[xSrc+1]>>24)&0xFF; + } + + if( ySrc>0)&0xFF; + g3 = (pSrc2[xSrc]>>8)&0xFF; + r3 = (pSrc2[xSrc]>>16)&0xFF; + a3 = (pSrc2[xSrc]>>24)&0xFF; + if( xSrc>0)&0xFF; + g4 = (pSrc2[xSrc+1]>>8)&0xFF; + r4 = (pSrc2[xSrc+1]>>16)&0xFF; + a4 = (pSrc2[xSrc+1]>>24)&0xFF; + } + } + + + // Pixel 1 + pDst1[xSrc*2] = pSrc[xSrc]; + + // Pixel 2 + if( xSrc> 0)&0xF; + g1 = (pSrc[xSrc]>> 4)&0xF; + r1 = (pSrc[xSrc]>> 8)&0xF; + a1 = (pSrc[xSrc]>>12)&0xF; + + if( xSrc> 0)&0xF; + g2 = (pSrc[xSrc+1]>> 4)&0xF; + r2 = (pSrc[xSrc+1]>> 8)&0xF; + a2 = (pSrc[xSrc+1]>>12)&0xF; + } + + if( ySrc> 0)&0xF; + g3 = (pSrc2[xSrc]>> 4)&0xF; + r3 = (pSrc2[xSrc]>> 8)&0xF; + a3 = (pSrc2[xSrc]>>12)&0xF; + if( xSrc> 0)&0xF; + g4 = (pSrc2[xSrc+1]>> 4)&0xF; + r4 = (pSrc2[xSrc+1]>> 8)&0xF; + a4 = (pSrc2[xSrc+1]>>12)&0xF; + } + } + + // Pixel 1 + pDst1[xSrc*2] = pSrc[xSrc]; + + // Pixel 2 + if( xSrc + */ +void SharpFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter) +{ + // NOTE: for now we get away with copying the boundaries + // filter the boundaries if we face problems + + uint32 mul1, mul2, mul3, shift4; + + uint32 x,y,z; + uint32 *_src1, *_src2, *_src3, *_dest; + uint32 val[4]; + uint32 t1,t2,t3,t4,t5,t6,t7,t8,t9; + + switch( filter ) + { + case SHARP_FILTER_2: + mul1=1; + mul2=8; + mul3=12; + shift4=2; + break; + case SHARP_FILTER_1: + default: + mul1=1; + mul2=8; + mul3=16; + shift4=3; + break; + } + + // setup rows + _src1 = src; + _src2 = _src1 + srcwidth; + _src3 = _src2 + srcwidth; + _dest = dest; + + // copy the first row + memcpy(_dest, _src1, (srcwidth << 2)); + _dest += srcwidth; + // filter 2nd row to 1 row before the last + for (y = 1; y < srcheight-1; y++) { + // copy the first pixel + _dest[0] = *_src2; + // filter 2nd pixel to 1 pixel before last + for (x = 1; x < srcwidth-1; x++) { + for (z=0; z<4; z++) { + t1 = *((uint8*)(_src1+x-1)+z); + t2 = *((uint8*)(_src1+x )+z); + t3 = *((uint8*)(_src1+x+1)+z); + t4 = *((uint8*)(_src2+x-1)+z); + t5 = *((uint8*)(_src2+x )+z); + t6 = *((uint8*)(_src2+x+1)+z); + t7 = *((uint8*)(_src3+x-1)+z); + t8 = *((uint8*)(_src3+x )+z); + t9 = *((uint8*)(_src3+x+1)+z); + + if( (t5*mul2) > (t1+t3+t7+t9+t2+t4+t6+t8)*mul1 ) { + val[z]= ((t5*mul3) - (t1+t3+t7+t9+t2+t4+t6+t8)*mul1)>>shift4; + if (val[z] > 0xFF) val[z] = 0xFF; + } else { + val[z] = t5; + } + } + _dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24); + } + // copy the ending pixel + _dest[srcwidth-1] = *(_src3 - 1); + // next row + _src1 += srcwidth; + _src2 += srcwidth; + _src3 += srcwidth; + _dest += srcwidth; + } + // copy the last row + memcpy(_dest, _src2, (srcwidth << 2)); +} + +#if !_16BPP_HACK +void SharpFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter) +{ + // NOTE: for now we get away with copying the boundaries + // filter the boundaries if we face problems + + uint16 mul1, mul2, mul3, shift4; + + uint32 x,y,z; + uint16 *_src1, *_src2, *_src3, *_dest; + uint16 val[4]; + uint16 t1,t2,t3,t4,t5,t6,t7,t8,t9; + + switch( filter ) { + case SHARP_FILTER_2: + mul1=1; + mul2=8; + mul3=12; + shift4=2; + break; + case SHARP_FILTER_1: + default: + mul1=1; + mul2=8; + mul3=16; + shift4=3; + break; + } + + // setup rows + _src1 = src; + _src2 = _src1 + srcwidth; + _src3 = _src2 + srcwidth; + _dest = dest; + + // copy the first row + memcpy(_dest, _src1, (srcwidth << 1)); + _dest += srcwidth; + // filter 2nd row to 1 row before the last + for( y = 1; y < srcheight - 1; y++) { + // copy the first pixel + _dest[0] = *_src2; + // filter 2nd pixel to 1 pixel before last + for( x = 1; x < srcwidth - 1; x++) { + for( z = 0; z < 4; z++ ) { + /* Hiroshi Morii + * Read the entire 16bit pixel and then extract the A,R,G,B components. + */ + uint32 shift = z << 2; + t1 = ((*((uint16*)(_src1+x-1))) >> shift) & 0xF; + t2 = ((*((uint16*)(_src1+x ))) >> shift) & 0xF; + t3 = ((*((uint16*)(_src1+x+1))) >> shift) & 0xF; + t4 = ((*((uint16*)(_src2+x-1))) >> shift) & 0xF; + t5 = ((*((uint16*)(_src2+x ))) >> shift) & 0xF; + t6 = ((*((uint16*)(_src2+x+1))) >> shift) & 0xF; + t7 = ((*((uint16*)(_src3+x-1))) >> shift) & 0xF; + t8 = ((*((uint16*)(_src3+x ))) >> shift) & 0xF; + t9 = ((*((uint16*)(_src3+x+1))) >> shift) & 0xF; + + if( (t5*mul2) > (t1+t3+t7+t9+t2+t4+t6+t8)*mul1 ) { + val[z] = ((t5*mul3) - (t1+t3+t7+t9+t2+t4+t6+t8)*mul1)>>shift4; + if (val[z] > 0xF) val[z] = 0xF; + } else { + val[z] = t5; + } + } + _dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12); + } + // copy the ending pixel + _dest[srcwidth-1] = *(_src3 - 1); + // next row + _src1 += srcwidth; + _src2 += srcwidth; + _src3 += srcwidth; + _dest += srcwidth; + } + // copy the last row + memcpy(_dest, _src2, (srcwidth << 1)); +} +#endif /* !_16BPP_HACK */ + +/* + * Smooth filters + * Hiroshi Morii + */ +void SmoothFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter) +{ + // NOTE: for now we get away with copying the boundaries + // filter the boundaries if we face problems + + uint32 mul1, mul2, mul3, shift4; + + uint32 x,y,z; + uint32 *_src1, *_src2, *_src3, *_dest; + uint32 val[4]; + uint32 t1,t2,t3,t4,t5,t6,t7,t8,t9; + + switch( filter ) { + case SMOOTH_FILTER_4: + mul1=1; + mul2=2; + mul3=4; + shift4=4; + break; + case SMOOTH_FILTER_3: + mul1=1; + mul2=1; + mul3=8; + shift4=4; + break; + case SMOOTH_FILTER_2: + mul1=1; + mul2=1; + mul3=2; + shift4=2; + break; + case SMOOTH_FILTER_1: + default: + mul1=1; + mul2=1; + mul3=6; + shift4=3; + break; + } + + switch (filter) { + case SMOOTH_FILTER_3: + case SMOOTH_FILTER_4: + // setup rows + _src1 = src; + _src2 = _src1 + srcwidth; + _src3 = _src2 + srcwidth; + _dest = dest; + // copy the first row + memcpy(_dest, _src1, (srcwidth << 2)); + _dest += srcwidth; + // filter 2nd row to 1 row before the last + for (y = 1; y < srcheight - 1; y++){ + // copy the first pixel + _dest[0] = _src2[0]; + // filter 2nd pixel to 1 pixel before last + for (x = 1; x < srcwidth - 1; x++) { + for (z = 0; z < 4; z++ ) { + t1 = *((uint8*)(_src1+x-1)+z); + t2 = *((uint8*)(_src1+x )+z); + t3 = *((uint8*)(_src1+x+1)+z); + t4 = *((uint8*)(_src2+x-1)+z); + t5 = *((uint8*)(_src2+x )+z); + t6 = *((uint8*)(_src2+x+1)+z); + t7 = *((uint8*)(_src3+x-1)+z); + t8 = *((uint8*)(_src3+x )+z); + t9 = *((uint8*)(_src3+x+1)+z); + /* the component value must not overflow 0xFF */ + val[z] = ((t1+t3+t7+t9)*mul1+((t2+t4+t6+t8)*mul2)+(t5*mul3))>>shift4; + if (val[z] > 0xFF) val[z] = 0xFF; + } + _dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24); + } + // copy the ending pixel + _dest[srcwidth-1] = *(_src3 - 1); + // next row + _src1 += srcwidth; + _src2 += srcwidth; + _src3 += srcwidth; + _dest += srcwidth; + } + // copy the last row + memcpy(_dest, _src2, (srcwidth << 2)); + break; + case SMOOTH_FILTER_1: + case SMOOTH_FILTER_2: + default: + // setup rows + _src1 = src; + _src2 = _src1 + srcwidth; + _src3 = _src2 + srcwidth; + _dest = dest; + // copy the first row + memcpy(_dest, _src1, (srcwidth << 2)); + _dest += srcwidth; + // filter 2nd row to 1 row before the last + for (y = 1; y < srcheight - 1; y++) { + // filter 1st pixel to the last + if (y & 1) { + for( x = 0; x < srcwidth; x++) { + for( z = 0; z < 4; z++ ) { + t2 = *((uint8*)(_src1+x )+z); + t5 = *((uint8*)(_src2+x )+z); + t8 = *((uint8*)(_src3+x )+z); + /* the component value must not overflow 0xFF */ + val[z] = ((t2+t8)*mul2+(t5*mul3))>>shift4; + if (val[z] > 0xFF) val[z] = 0xFF; + } + _dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24); + } + } else { + memcpy(_dest, _src2, (srcwidth << 2)); + } + // next row + _src1 += srcwidth; + _src2 += srcwidth; + _src3 += srcwidth; + _dest += srcwidth; + } + // copy the last row + memcpy(_dest, _src2, (srcwidth << 2)); + break; + } +} + +#if !_16BPP_HACK +void SmoothFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter) +{ + // NOTE: for now we get away with copying the boundaries + // filter the boundaries if we face problems + + uint16 mul1, mul2, mul3, shift4; + + uint32 x,y,z; + uint16 *_src1, *_src2, *_src3, *_dest; + uint16 val[4]; + uint16 t1,t2,t3,t4,t5,t6,t7,t8,t9; + + switch( filter ) { + case SMOOTH_FILTER_4: + mul1=1; + mul2=2; + mul3=4; + shift4=4; + break; + case SMOOTH_FILTER_3: + mul1=1; + mul2=1; + mul3=8; + shift4=4; + break; + case SMOOTH_FILTER_2: + mul1=1; + mul2=1; + mul3=2; + shift4=2; + break; + case SMOOTH_FILTER_1: + default: + mul1=1; + mul2=1; + mul3=6; + shift4=3; + break; + } + + switch (filter) { + case SMOOTH_FILTER_3: + case SMOOTH_FILTER_4: + // setup rows + _src1 = src; + _src2 = _src1 + srcwidth; + _src3 = _src2 + srcwidth; + _dest = dest; + // copy the first row + memcpy(_dest, _src1, (srcwidth << 1)); + _dest += srcwidth; + // filter 2nd row to 1 row before the last + for (y = 1; y < srcheight - 1; y++) { + // copy the first pixel + _dest[0] = *_src2; + // filter 2nd pixel to 1 pixel before last + for (x = 1; x < srcwidth - 1; x++) { + for (z = 0; z < 4; z++ ) { + /* Read the entire 16bit pixel and then extract the A,R,G,B components. */ + uint32 shift = z << 2; + t1 = ((*(uint16*)(_src1+x-1)) >> shift) & 0xF; + t2 = ((*(uint16*)(_src1+x )) >> shift) & 0xF; + t3 = ((*(uint16*)(_src1+x+1)) >> shift) & 0xF; + t4 = ((*(uint16*)(_src2+x-1)) >> shift) & 0xF; + t5 = ((*(uint16*)(_src2+x )) >> shift) & 0xF; + t6 = ((*(uint16*)(_src2+x+1)) >> shift) & 0xF; + t7 = ((*(uint16*)(_src3+x-1)) >> shift) & 0xF; + t8 = ((*(uint16*)(_src3+x )) >> shift) & 0xF; + t9 = ((*(uint16*)(_src3+x+1)) >> shift) & 0xF; + /* the component value must not overflow 0xF */ + val[z] = ((t1+t3+t7+t9)*mul1+((t2+t4+t6+t8)*mul2)+(t5*mul3))>>shift4; + if (val[z] > 0xF) val[z] = 0xF; + } + _dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12); + } + // copy the ending pixel + _dest[srcwidth-1] = *(_src3 - 1); + // next row + _src1 += srcwidth; + _src2 += srcwidth; + _src3 += srcwidth; + _dest += srcwidth; + } + // copy the last row + memcpy(_dest, _src2, (srcwidth << 1)); + break; + case SMOOTH_FILTER_1: + case SMOOTH_FILTER_2: + default: + // setup rows + _src1 = src; + _src2 = _src1 + srcwidth; + _src3 = _src2 + srcwidth; + _dest = dest; + // copy the first row + memcpy(_dest, _src1, (srcwidth << 1)); + _dest += srcwidth; + // filter 2nd row to 1 row before the last + for( y = 1; y < srcheight - 1; y++) { + if (y & 1) { + for( x = 0; x < srcwidth; x++) { + for( z = 0; z < 4; z++ ) { + /* Read the entire 16bit pixel and then extract the A,R,G,B components. */ + uint32 shift = z << 2; + t2 = ((*(uint16*)(_src1+x)) >> shift) & 0xF; + t5 = ((*(uint16*)(_src2+x)) >> shift) & 0xF; + t8 = ((*(uint16*)(_src3+x)) >> shift) & 0xF; + /* the component value must not overflow 0xF */ + val[z] = ((t2+t8)*mul2+(t5*mul3))>>shift4; + if (val[z] > 0xF) val[z] = 0xF; + } + _dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12); + } + } else { + memcpy(_dest, _src2, (srcwidth << 1)); + } + // next row + _src1 += srcwidth; + _src2 += srcwidth; + _src3 += srcwidth; + _dest += srcwidth; + } + // copy the last row + memcpy(_dest, _src2, (srcwidth << 1)); + break; + } +} +#endif /* !_16BPP_HACK */ + +void filter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter) { + switch (filter & ENHANCEMENT_MASK) { + case HQ4X_ENHANCEMENT: + hq4x_8888((uint8*)src, (uint8*)dest, srcwidth, srcheight, srcwidth, (srcwidth << 4)); + return; + case HQ2X_ENHANCEMENT: + hq2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight); + return; + case HQ2XS_ENHANCEMENT: + hq2xS_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight); + return; + case LQ2X_ENHANCEMENT: + lq2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight); + return; + case LQ2XS_ENHANCEMENT: + lq2xS_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight); + return; + case X2SAI_ENHANCEMENT: + Super2xSaI_8888((uint32*)src, (uint32*)dest, srcwidth, srcheight, srcwidth); + return; + case X2_ENHANCEMENT: + Texture2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight); + return; + } + + switch (filter & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK)) { + case SMOOTH_FILTER_1: + case SMOOTH_FILTER_2: + case SMOOTH_FILTER_3: + case SMOOTH_FILTER_4: + SmoothFilter_8888((uint32*)src, srcwidth, srcheight, (uint32*)dest, (filter & SMOOTH_FILTER_MASK)); + return; + case SHARP_FILTER_1: + case SHARP_FILTER_2: + SharpFilter_8888((uint32*)src, srcwidth, srcheight, (uint32*)dest, (filter & SHARP_FILTER_MASK)); + return; + } +} diff --git a/GLideNHQ/TextureFilters.h b/GLideNHQ/TextureFilters.h new file mode 100644 index 00000000..7830eac5 --- /dev/null +++ b/GLideNHQ/TextureFilters.h @@ -0,0 +1,81 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __TEXTUREFILTERS_H__ +#define __TEXTUREFILTERS_H__ + +/* 16bpp filters are somewhat buggy and output image is not clean. + * Since there's not much time, we'll just convert them to ARGB8888 + * and use 32bpp filters until fixed. + * (1:enable hack, 0:disable hack) */ +#define _16BPP_HACK 1 + +#include "TxInternal.h" + +/* enhancers */ +void hq4x_8888(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL); + +void hq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); +void hq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); + +void lq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); +void lq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); + +void Super2xSaI_8888(uint32 *srcPtr, uint32 *destPtr, uint32 width, uint32 height, uint32 pitch); + +void Texture2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); + +/* filters */ +void SharpFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter); + +void SmoothFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter); + +/* helper */ +void filter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter); + +#if !_16BPP_HACK +void hq4x_init(void); +void hq4x_4444(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL); +void hq4x_1555(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL); +void hq4x_565 (unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL); + +void hq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); +void hq2xS_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); + +void lq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); +void lq2xS_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); + +void Super2xSaI_4444(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch); +void Super2xSaI_1555(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch); +void Super2xSaI_565 (uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch); +void Super2xSaI_8 (uint8 *srcPtr, uint8 *destPtr, uint32 width, uint32 height, uint32 pitch); + +void Texture2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); + +void SharpFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter); + +void SmoothFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter); +#endif + +#endif /* __TEXTUREFILTERS_H__ */ diff --git a/GLideNHQ/TextureFilters_2xsai.cpp b/GLideNHQ/TextureFilters_2xsai.cpp new file mode 100644 index 00000000..38226df2 --- /dev/null +++ b/GLideNHQ/TextureFilters_2xsai.cpp @@ -0,0 +1,155 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Based on Derek Liauw Kie Fa and Rice1964 Super2xSaI code */ + +#include "TextureFilters.h" + +#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) + +void Super2xSaI_8888(uint32 *srcPtr, uint32 *destPtr, uint32 width, uint32 height, uint32 pitch) +{ +#define SAI_INTERPOLATE_8888(A, B) ((A & 0xFEFEFEFE) >> 1) + ((B & 0xFEFEFEFE) >> 1) + (A & B & 0x01010101) +#define SAI_Q_INTERPOLATE_8888(A, B, C, D) ((A & 0xFCFCFCFC) >> 2) + ((B & 0xFCFCFCFC) >> 2) + ((C & 0xFCFCFCFC) >> 2) + ((D & 0xFCFCFCFC) >> 2) \ + + ((((A & 0x03030303) + (B & 0x03030303) + (C & 0x03030303) + (D & 0x03030303)) >> 2) & 0x03030303) + +#define SAI_INTERPOLATE SAI_INTERPOLATE_8888 +#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_8888 + + uint32 destWidth = width << 1; + uint32 destHeight = height << 1; + + uint32 color4, color5, color6; + uint32 color1, color2, color3; + uint32 colorA0, colorA1, colorA2, colorA3; + uint32 colorB0, colorB1, colorB2, colorB3; + uint32 colorS1, colorS2; + uint32 product1a, product1b, product2a, product2b; + +#include "TextureFilters_2xsai.h" + +#undef SAI_INTERPOLATE +#undef SAI_Q_INTERPOLATE +} + +#if !_16BPP_HACK +void Super2xSaI_4444(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch) +{ +#define SAI_INTERPOLATE_4444(A, B) ((A & 0xEEEE) >> 1) + ((B & 0xEEEE) >> 1) + (A & B & 0x1111) +#define SAI_Q_INTERPOLATE_4444(A, B, C, D) ((A & 0xCCCC) >> 2) + ((B & 0xCCCC) >> 2) + ((C & 0xCCCC) >> 2) + ((D & 0xCCCC) >> 2) \ + + ((((A & 0x3333) + (B & 0x3333) + (C & 0x3333) + (D & 0x3333)) >> 2) & 0x3333) + +#define SAI_INTERPOLATE SAI_INTERPOLATE_4444 +#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_4444 + + uint32 destWidth = width << 1; + uint32 destHeight = height << 1; + + uint16 color4, color5, color6; + uint16 color1, color2, color3; + uint16 colorA0, colorA1, colorA2, colorA3; + uint16 colorB0, colorB1, colorB2, colorB3; + uint16 colorS1, colorS2; + uint16 product1a, product1b, product2a, product2b; + +#include "TextureFilters_2xsai.h" + +#undef SAI_INTERPOLATE +#undef SAI_Q_INTERPOLATE +} + +void Super2xSaI_1555(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch) +{ +#define SAI_INTERPOLATE_1555(A, B) ((A & 0x7BDE) >> 1) + ((B & 0x7BDE) >> 1) + (A & B & 0x8421) +#define SAI_Q_INTERPOLATE_1555(A, B, C, D) ((A & 0x739C) >> 2) + ((B & 0x739C) >> 2) + ((C & 0x739C) >> 2) + ((D & 0x739C) >> 2) \ + + ((((A & 0x8C63) + (B & 0x8C63) + (C & 0x8C63) + (D & 0x8C63)) >> 2) & 0x8C63) + +#define SAI_INTERPOLATE SAI_INTERPOLATE_1555 +#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_1555 + + uint32 destWidth = width << 1; + uint32 destHeight = height << 1; + + uint16 color4, color5, color6; + uint16 color1, color2, color3; + uint16 colorA0, colorA1, colorA2, colorA3; + uint16 colorB0, colorB1, colorB2, colorB3; + uint16 colorS1, colorS2; + uint16 product1a, product1b, product2a, product2b; + +#include "TextureFilters_2xsai.h" + +#undef SAI_INTERPOLATE +#undef SAI_Q_INTERPOLATE +} + +void Super2xSaI_565(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch) +{ +#define SAI_INTERPOLATE_565(A, B) ((A & 0xF7DE) >> 1) + ((B & 0xF7DE) >> 1) + (A & B & 0x0821) +#define SAI_Q_INTERPOLATE_565(A, B, C, D) ((A & 0xE79C) >> 2) + ((B & 0xE79C) >> 2) + ((C & 0xE79C) >> 2) + ((D & 0xE79C) >> 2) \ + + ((((A & 0x1863) + (B & 0x1863) + (C & 0x1863) + (D & 0x1863)) >> 2) & 0x1863) + +#define SAI_INTERPOLATE SAI_INTERPOLATE_565 +#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_565 + + uint32 destWidth = width << 1; + uint32 destHeight = height << 1; + + uint16 color4, color5, color6; + uint16 color1, color2, color3; + uint16 colorA0, colorA1, colorA2, colorA3; + uint16 colorB0, colorB1, colorB2, colorB3; + uint16 colorS1, colorS2; + uint16 product1a, product1b, product2a, product2b; + +#include "TextureFilters_2xsai.h" + +#undef SAI_INTERPOLATE +#undef SAI_Q_INTERPOLATE +} + +void Super2xSaI_8(uint8 *srcPtr, uint8 *destPtr, uint32 width, uint32 height, uint32 pitch) +{ +#define SAI_INTERPOLATE_8(A, B) ((A & 0xFE) >> 1) + ((B & 0xFE) >> 1) + (A & B & 0x01) +#define SAI_Q_INTERPOLATE_8(A, B, C, D) ((A & 0xFC) >> 2) + ((B & 0xFC) >> 2) + ((C & 0xFC) >> 2) + ((D & 0xFC) >> 2) \ + + ((((A & 0x03) + (B & 0x03) + (C & 0x03) + (D & 0x03)) >> 2) & 0x03) + +#define SAI_INTERPOLATE SAI_INTERPOLATE_8 +#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_8 + + uint32 destWidth = width << 1; + uint32 destHeight = height << 1; + + uint8 color4, color5, color6; + uint8 color1, color2, color3; + uint8 colorA0, colorA1, colorA2, colorA3; + uint8 colorB0, colorB1, colorB2, colorB3; + uint8 colorS1, colorS2; + uint8 product1a, product1b, product2a, product2b; + +#include "TextureFilters_2xsai.h" + +#undef SAI_INTERPOLATE +#undef SAI_Q_INTERPOLATE +} +#endif /* !_16BPP_HACK */ diff --git a/GLideNHQ/TextureFilters_2xsai.h b/GLideNHQ/TextureFilters_2xsai.h new file mode 100644 index 00000000..f6696ae0 --- /dev/null +++ b/GLideNHQ/TextureFilters_2xsai.h @@ -0,0 +1,145 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Based on Derek Liauw Kie Fa and Rice1964 Super2xSaI code */ + + int row0, row1, row2, row3; + int col0, col1, col2, col3; + + uint16 x; + uint16 y; + + for (y = 0; y < height; y++) { + if ((y > 0) && (y < height - 1)) { + row0 = width; + row0 = -row0; + row1 = 0; + row2 = width; + row3 = (y == height - 2 ? width : width << 1); + } else { + row0 = 0; + row1 = 0; + row2 = 0; + row3 = 0; + } + + for (x = 0; x < width; x++) { +//--------------------------------------- B0 B1 B2 B3 +// 4 5 6 S2 +// 1 2 3 S1 +// A0 A1 A2 A3 + if ((x > 0) && (x < width - 1)) { + col0 = -1; + col1 = 0; + col2 = 1; + col3 = (x == width - 2 ? 1 : 2); + } else { + col0 = 0; + col1 = 0; + col2 = 0; + col3 = 0; + } + + colorB0 = *(srcPtr + col0 + row0); + colorB1 = *(srcPtr + col1 + row0); + colorB2 = *(srcPtr + col2 + row0); + colorB3 = *(srcPtr + col3 + row0); + + color4 = *(srcPtr + col0 + row1); + color5 = *(srcPtr + col1 + row1); + color6 = *(srcPtr + col2 + row1); + colorS2 = *(srcPtr + col3 + row1); + + color1 = *(srcPtr + col0 + row2); + color2 = *(srcPtr + col1 + row2); + color3 = *(srcPtr + col2 + row2); + colorS1 = *(srcPtr + col3 + row2); + + colorA0 = *(srcPtr + col0 + row3); + colorA1 = *(srcPtr + col1 + row3); + colorA2 = *(srcPtr + col2 + row3); + colorA3 = *(srcPtr + col3 + row3); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + product2b = product1b = color2; + else if (color5 == color3 && color2 != color6) + product2b = product1b = color5; + else if (color5 == color3 && color2 == color6) { + int r = 0; + + r += GET_RESULT(color6, color5, color1, colorA1); + r += GET_RESULT(color6, color5, color4, colorB1); + r += GET_RESULT(color6, color5, colorA2, colorS1); + r += GET_RESULT(color6, color5, colorB2, colorS2); + + if (r > 0) + product2b = product1b = color6; + else if (r < 0) + product2b = product1b = color5; + else + product2b = product1b = SAI_INTERPOLATE(color5, color6); + + } else { + + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = SAI_Q_INTERPOLATE(color3, color3, color3, color2); + else if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = SAI_Q_INTERPOLATE(color2, color2, color2, color3); + else + product2b = SAI_INTERPOLATE(color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = SAI_Q_INTERPOLATE(color6, color6, color6, color5); + else if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = SAI_Q_INTERPOLATE(color6, color5, color5, color5); + else + product1b = SAI_INTERPOLATE(color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = SAI_INTERPOLATE(color2, color5); + else if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = SAI_INTERPOLATE(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = SAI_INTERPOLATE(color2, color5); + else if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = SAI_INTERPOLATE(color2, color5); + else + product1a = color5; + + + destPtr[0] = product1a; + destPtr[1] = product1b; + destPtr[destWidth] = product2a; + destPtr[destWidth + 1] = product2b; + + srcPtr++; + destPtr += 2; + } + srcPtr += (pitch-width); + destPtr += (((pitch-width)<<1)+(pitch<<1)); + } diff --git a/GLideNHQ/TextureFilters_hq2x.cpp b/GLideNHQ/TextureFilters_hq2x.cpp new file mode 100644 index 00000000..33cb9953 --- /dev/null +++ b/GLideNHQ/TextureFilters_hq2x.cpp @@ -0,0 +1,1510 @@ +/* +Copyright (C) 2003 Rice1964 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +/* Copyright (C) 2007 Hiroshi Morii + * Modified for the Texture Filtering library + */ + +/* 2007 Mudlord - Added hq2xS lq2xS filters */ + +#include "TextureFilters.h" + +/************************************************************************/ +/* hq2x filters */ +/************************************************************************/ + +/***************************************************************************/ +/* Basic types */ + +/***************************************************************************/ +/* interpolation */ + +//static unsigned interp_bits_per_pixel; + +#if !_16BPP_HACK +#define INTERP_16_MASK_1_3(v) ((v)&0x0F0F) +#define INTERP_16_MASK_SHIFT_2_4(v) (((v)&0xF0F0)>>4) +#define INTERP_16_MASK_SHIFTBACK_2_4(v) ((INTERP_16_MASK_1_3(v))<<4) + +static uint16 hq2x_interp_16_521(uint16 p1, uint16 p2, uint16 p3) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*5 + INTERP_16_MASK_1_3(p2)*2 + INTERP_16_MASK_1_3(p3)*1) / 8) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*5 + INTERP_16_MASK_SHIFT_2_4(p2)*2 + INTERP_16_MASK_SHIFT_2_4(p3)*1) / 8); +} + +static uint16 hq2x_interp_16_332(uint16 p1, uint16 p2, uint16 p3) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*3 + INTERP_16_MASK_1_3(p2)*3 + INTERP_16_MASK_1_3(p3)*2) / 8) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*3 + INTERP_16_MASK_SHIFT_2_4(p2)*3 + INTERP_16_MASK_SHIFT_2_4(p3)*2) / 8); +} + +static uint16 hq2x_interp_16_611(uint16 p1, uint16 p2, uint16 p3) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*6 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 8) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*6 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 8); +} + +static uint16 hq2x_interp_16_71(uint16 p1, uint16 p2) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*7 + INTERP_16_MASK_1_3(p2)) / 8) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*7 + INTERP_16_MASK_SHIFT_2_4(p2)) / 8); +} + +static uint16 hq2x_interp_16_211(uint16 p1, uint16 p2, uint16 p3) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*2 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 4) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*2 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 4); +} + +static uint16 hq2x_interp_16_772(uint16 p1, uint16 p2, uint16 p3) +{ + return INTERP_16_MASK_1_3(((INTERP_16_MASK_1_3(p1) + INTERP_16_MASK_1_3(p2))*7 + INTERP_16_MASK_1_3(p3)*2) / 16) + | INTERP_16_MASK_SHIFTBACK_2_4(((INTERP_16_MASK_SHIFT_2_4(p1) + INTERP_16_MASK_SHIFT_2_4(p2))*7 + INTERP_16_MASK_SHIFT_2_4(p3)*2) / 16); +} + +static uint16 hq2x_interp_16_11(uint16 p1, uint16 p2) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1) + INTERP_16_MASK_1_3(p2)) / 2) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1) + INTERP_16_MASK_SHIFT_2_4(p2)) / 2); +} + +static uint16 hq2x_interp_16_31(uint16 p1, uint16 p2) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*3 + INTERP_16_MASK_1_3(p2)) / 4) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*3 + INTERP_16_MASK_SHIFT_2_4(p2)) / 4); +} + +static uint16 hq2x_interp_16_1411(uint16 p1, uint16 p2, uint16 p3) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*14 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 16) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*14 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 16); +} + +static uint16 hq2x_interp_16_431(uint16 p1, uint16 p2, uint16 p3) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*4 + INTERP_16_MASK_1_3(p2)*3 + INTERP_16_MASK_1_3(p3)) / 8) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*4 + INTERP_16_MASK_SHIFT_2_4(p2)*3 + INTERP_16_MASK_SHIFT_2_4(p3)) / 8); +} + +static uint16 hq2x_interp_16_53(uint16 p1, uint16 p2) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*5 + INTERP_16_MASK_1_3(p2)*3) / 8) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*5 + INTERP_16_MASK_SHIFT_2_4(p2)*3) / 8); +} + +static uint16 hq2x_interp_16_151(uint16 p1, uint16 p2) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*15 + INTERP_16_MASK_1_3(p2)) / 16) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*15 + INTERP_16_MASK_SHIFT_2_4(p2)) / 16); +} + +static uint16 hq2x_interp_16_97(uint16 p1, uint16 p2) +{ + return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*9 + INTERP_16_MASK_1_3(p2)*7) / 16) + | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*9 + INTERP_16_MASK_SHIFT_2_4(p2)*7) / 16); +} +#endif /* !_16BPP_HACK */ + +#define INTERP_32_MASK_1_3(v) ((v)&0x00FF00FF) +#define INTERP_32_MASK_SHIFT_2_4(v) (((v)&0xFF00FF00)>>8) +#define INTERP_32_MASK_SHIFTBACK_2_4(v) (((INTERP_32_MASK_1_3(v))<<8)) + +static uint32 hq2x_interp_32_521(uint32 p1, uint32 p2, uint32 p3) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*5 + INTERP_32_MASK_1_3(p2)*2 + INTERP_32_MASK_1_3(p3)*1) / 8) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*5 + INTERP_32_MASK_SHIFT_2_4(p2)*2 + INTERP_32_MASK_SHIFT_2_4(p3)*1) / 8); +} + +static uint32 hq2x_interp_32_332(uint32 p1, uint32 p2, uint32 p3) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*3 + INTERP_32_MASK_1_3(p2)*3 + INTERP_32_MASK_1_3(p3)*2) / 8) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*3 + INTERP_32_MASK_SHIFT_2_4(p2)*3 + INTERP_32_MASK_SHIFT_2_4(p3)*2) / 8); +} + +static uint32 hq2x_interp_32_211(uint32 p1, uint32 p2, uint32 p3) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*2 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 4) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*2 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 4); +} + +static uint32 hq2x_interp_32_611(uint32 p1, uint32 p2, uint32 p3) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*6 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 8) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*6 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 8); +} + +static uint32 hq2x_interp_32_71(uint32 p1, uint32 p2) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*7 + INTERP_32_MASK_1_3(p2)) / 8) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*7 + INTERP_32_MASK_SHIFT_2_4(p2)) / 8); +} + +static uint32 hq2x_interp_32_772(uint32 p1, uint32 p2, uint32 p3) +{ + return INTERP_32_MASK_1_3(((INTERP_32_MASK_1_3(p1) + INTERP_32_MASK_1_3(p2))*7 + INTERP_32_MASK_1_3(p3)*2) / 16) + | INTERP_32_MASK_SHIFTBACK_2_4(((INTERP_32_MASK_SHIFT_2_4(p1) + INTERP_32_MASK_SHIFT_2_4(p2))*7 + INTERP_32_MASK_SHIFT_2_4(p3)*2) / 16); +} + +static uint32 hq2x_interp_32_11(uint32 p1, uint32 p2) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1) + INTERP_32_MASK_1_3(p2)) / 2) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1) + INTERP_32_MASK_SHIFT_2_4(p2)) / 2); +} + +static uint32 hq2x_interp_32_31(uint32 p1, uint32 p2) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*3 + INTERP_32_MASK_1_3(p2)) / 4) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*3 + INTERP_32_MASK_SHIFT_2_4(p2)) / 4); +} + +static uint32 hq2x_interp_32_1411(uint32 p1, uint32 p2, uint32 p3) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*14 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 16) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*14 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 16); +} + +static uint32 hq2x_interp_32_431(uint32 p1, uint32 p2, uint32 p3) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*4 + INTERP_32_MASK_1_3(p2)*3 + INTERP_32_MASK_1_3(p3)) / 8) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*4 + INTERP_32_MASK_SHIFT_2_4(p2)*3 + INTERP_32_MASK_SHIFT_2_4(p3)) / 8); +} + +static uint32 hq2x_interp_32_53(uint32 p1, uint32 p2) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*5 + INTERP_32_MASK_1_3(p2)*3) / 8) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*5 + INTERP_32_MASK_SHIFT_2_4(p2)*3) / 8); +} + +static uint32 hq2x_interp_32_151(uint32 p1, uint32 p2) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*15 + INTERP_32_MASK_1_3(p2)) / 16) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*15 + INTERP_32_MASK_SHIFT_2_4(p2)) / 16); +} + +static uint32 hq2x_interp_32_97(uint32 p1, uint32 p2) +{ + return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*9 + INTERP_32_MASK_1_3(p2)*7) / 16) + | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*9 + INTERP_32_MASK_SHIFT_2_4(p2)*7) / 16); +} + +/***************************************************************************/ +/* diff */ + +#define INTERP_Y_LIMIT (0x30*4) +#define INTERP_U_LIMIT (0x07*4) +#define INTERP_V_LIMIT (0x06*8) + +#if !_16BPP_HACK +static int hq2x_interp_16_diff(uint16 p1, uint16 p2) +{ + int r, g, b; + int y, u, v; + + if (p1 == p2) + return 0; + + b = (int)((p1 & 0x000F) - (p2 & 0x000F)); + g = (int)((p1 & 0x00F0) - (p2 & 0x00F0)) >> 4; + r = (int)((p1 & 0x0F00) - (p2 & 0x0F00)) >> 8; + + y = r + g + b; + u = r - b; + v = -r + 2*g - b; + + if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) + return 1; + + if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) + return 1; + + if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) + return 1; + + return 0; +} +#endif /* !_16BPP_HACK */ + +static int hq2x_interp_32_diff(uint32 p1, uint32 p2) +{ + int r, g, b; + int y, u, v; + + if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8)) + return 0; + + b = (int)((p1 & 0xFF) - (p2 & 0xFF)); + g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8; + r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16; + + y = r + g + b; + u = r - b; + v = -r + 2*g - b; + + if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) + return 1; + + if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) + return 1; + + if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) + return 1; + + return 0; +} + +/*static void interp_set(unsigned bits_per_pixel) +{ + interp_bits_per_pixel = bits_per_pixel; +}*/ + +#if !_16BPP_HACK +static void hq2x_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count) +{ + unsigned i; + + for(i=0;i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i> 3; + r = (int)((c[j] & 0xF800)) >> 8; + } else { + b = (int)((c[j] & 0x1F)) << 3; + g = (int)((c[j] & 0x3E0)) >> 2; + r = (int)((c[j] & 0x7C00)) >> 7; + } + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) { +#define ABS(x) ((x) < 0 ? -(x) : (x)) + + const int centerBright = brightArray[4]; + if(ABS(brightArray[0] - centerBright) > diffBright) + mask |= 1 << 0; + if(ABS(brightArray[1] - centerBright) > diffBright) + mask |= 1 << 1; + if(ABS(brightArray[2] - centerBright) > diffBright) + mask |= 1 << 2; + if(ABS(brightArray[3] - centerBright) > diffBright) + mask |= 1 << 3; + if(ABS(brightArray[5] - centerBright) > diffBright) + mask |= 1 << 4; + if(ABS(brightArray[6] - centerBright) > diffBright) + mask |= 1 << 5; + if(ABS(brightArray[7] - centerBright) > diffBright) + mask |= 1 << 6; + if(ABS(brightArray[8] - centerBright) > diffBright) + mask |= 1 << 7; + } + +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define HQ2X_MUR false +#define HQ2X_MDR false +#define HQ2X_MDL false +#define HQ2X_MUL false +#define IC(p0) c[p0] +#define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1]) +#define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1]) +#define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1]) +#define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1]) +#define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1]) + + switch (mask) { +#include "TextureFilters_hq2x.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef HQ2X_MUR +#undef HQ2X_MDR +#undef HQ2X_MDL +#undef HQ2X_MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} +#endif /* !_16BPP_HACK */ + +static void hq2x_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count) +{ + unsigned i; + + for(i=0;i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = src0[0]; + c[3] = src1[0]; + c[6] = src2[0]; + } + + if (i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = src0[0]; + c[3] = src1[0]; + c[6] = src2[0]; + } + + if (i> 8; + const int r = (int)((c[j] & 0xF80000)) >> 16; + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) { +#define ABS(x) ((x) < 0 ? -(x) : (x)) + + const int centerBright = brightArray[4]; + if(ABS(brightArray[0] - centerBright) > diffBright) + mask |= 1 << 0; + if(ABS(brightArray[1] - centerBright) > diffBright) + mask |= 1 << 1; + if(ABS(brightArray[2] - centerBright) > diffBright) + mask |= 1 << 2; + if(ABS(brightArray[3] - centerBright) > diffBright) + mask |= 1 << 3; + if(ABS(brightArray[5] - centerBright) > diffBright) + mask |= 1 << 4; + if(ABS(brightArray[6] - centerBright) > diffBright) + mask |= 1 << 5; + if(ABS(brightArray[7] - centerBright) > diffBright) + mask |= 1 << 6; + if(ABS(brightArray[8] - centerBright) > diffBright) + mask |= 1 << 7; + } +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define HQ2X_MUR false +#define HQ2X_MDR false +#define HQ2X_MDL false +#define HQ2X_MUL false +#define IC(p0) c[p0] +#define I11(p0,p1) hq2x_interp_32_11(c[p0], c[p1]) +#define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1]) +#define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) hq2x_interp_32_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) hq2x_interp_32_53(c[p0], c[p1]) +#define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) hq2x_interp_32_71(c[p0], c[p1]) +#define I772(p0,p1,p2) hq2x_interp_32_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) hq2x_interp_32_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) hq2x_interp_32_151(c[p0], c[p1]) + + switch (mask) { +#include "TextureFilters_hq2x.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef HQ2X_MUR +#undef HQ2X_MDR +#undef HQ2X_MDL +#undef HQ2X_MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} + +/***************************************************************************/ +/* LQ2x C implementation */ + +/* +* This effect is derived from the hq2x effect made by Maxim Stepin +*/ + +#if !_16BPP_HACK +static void lq2x_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count) +{ + unsigned i; + + for(i=0;i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i> 8; + const int r = (int)((c[j] & 0xF80000)) >> 16; + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) { +#define ABS(x) ((x) < 0 ? -(x) : (x)) + + const int centerBright = brightArray[4]; + if(ABS(brightArray[0] - centerBright) > diffBright) + mask |= 1 << 0; + if(ABS(brightArray[1] - centerBright) > diffBright) + mask |= 1 << 1; + if(ABS(brightArray[2] - centerBright) > diffBright) + mask |= 1 << 2; + if(ABS(brightArray[3] - centerBright) > diffBright) + mask |= 1 << 3; + if(ABS(brightArray[5] - centerBright) > diffBright) + mask |= 1 << 4; + if(ABS(brightArray[6] - centerBright) > diffBright) + mask |= 1 << 5; + if(ABS(brightArray[7] - centerBright) > diffBright) + mask |= 1 << 6; + if(ABS(brightArray[8] - centerBright) > diffBright) + mask |= 1 << 7; + } + +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define HQ2X_MUR false +#define HQ2X_MDR false +#define HQ2X_MDL false +#define HQ2X_MUL false +#define IC(p0) c[p0] +#define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1]) +#define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1]) +#define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1]) +#define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1]) +#define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1]) + + switch (mask) { +#include "TextureFilters_lq2x.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef HQ2X_MUR +#undef HQ2X_MDR +#undef HQ2X_MDL +#undef HQ2X_MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} +#endif /* !_16BPP_HACK */ + +static void lq2x_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count) +{ + unsigned i; + + for(i=0;i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i> 8; + const int r = (int)((c[j] & 0xF80000)) >> 16; + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) { +#define ABS(x) ((x) < 0 ? -(x) : (x)) + + const int centerBright = brightArray[4]; + if(ABS(brightArray[0] - centerBright) > diffBright) + mask |= 1 << 0; + if(ABS(brightArray[1] - centerBright) > diffBright) + mask |= 1 << 1; + if(ABS(brightArray[2] - centerBright) > diffBright) + mask |= 1 << 2; + if(ABS(brightArray[3] - centerBright) > diffBright) + mask |= 1 << 3; + if(ABS(brightArray[5] - centerBright) > diffBright) + mask |= 1 << 4; + if(ABS(brightArray[6] - centerBright) > diffBright) + mask |= 1 << 5; + if(ABS(brightArray[7] - centerBright) > diffBright) + mask |= 1 << 6; + if(ABS(brightArray[8] - centerBright) > diffBright) + mask |= 1 << 7; + } + +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define HQ2X_MUR false +#define HQ2X_MDR false +#define HQ2X_MDL false +#define HQ2X_MUL false +#define IC(p0) c[p0] +#define I11(p0,p1) hq2x_interp_32_11(c[p0], c[p1]) +#define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1]) +#define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) hq2x_interp_32_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) hq2x_interp_32_53(c[p0], c[p1]) +#define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) hq2x_interp_32_71(c[p0], c[p1]) +#define I772(p0,p1,p2) hq2x_interp_32_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) hq2x_interp_32_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) hq2x_interp_32_151(c[p0], c[p1]) + + switch (mask) { +#include "TextureFilters_lq2x.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef HQ2X_MUR +#undef HQ2X_MDR +#undef HQ2X_MDL +#undef HQ2X_MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} + +#if !_16BPP_HACK +void hq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint16 *dst0 = (uint16 *)dstPtr; + uint16 *dst1 = dst0 + (dstPitch >> 1); + + uint16 *src0 = (uint16 *)srcPtr; + uint16 *src1 = src0 + (srcPitch >> 1); + uint16 *src2 = src1 + (srcPitch >> 1); + + int count; + + hq2x_16_def(dst0, dst1, src0, src0, src1, width); + if( height == 1 ) return; + + count = height; + + count -= 2; + while(count>0) { + dst0 += dstPitch; + dst1 += dstPitch; + hq2x_16_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 1; + --count; + } + dst0 += dstPitch; + dst1 += dstPitch; + hq2x_16_def(dst0, dst1, src0, src1, src1, width); +} + + +void hq2xS_16(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u16 *dst0 = (u16 *)dstPtr; + u16 *dst1 = dst0 + (dstPitch >> 1); + + u16 *src0 = (u16 *)srcPtr; + u16 *src1 = src0 + (srcPitch >> 1); + u16 *src2 = src1 + (srcPitch >> 1); + + hq2xS_16_def(dst0, dst1, src0, src0, src1, width); + + int count = height; + + count -= 2; + while(count) { + dst0 += dstPitch; + dst1 += dstPitch; + hq2xS_16_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 1; + --count; + } + dst0 += dstPitch; + dst1 += dstPitch; + hq2xS_16_def(dst0, dst1, src0, src1, src1, width); +} +#endif /* !_16BPP_HACK */ + +void hq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint32 *dst0 = (uint32 *)dstPtr; + uint32 *dst1 = dst0 + (dstPitch >> 2); + + uint32 *src0 = (uint32 *)srcPtr; + uint32 *src1 = src0 + (srcPitch >> 2); + uint32 *src2 = src1 + (srcPitch >> 2); + + int count; + + hq2x_32_def(dst0, dst1, src0, src0, src1, width); + if( height == 1 ) return; + + count = height; + + count -= 2; + while(count>0) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src1, width); +} + +void hq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint32 *dst0 = (uint32 *)dstPtr; + uint32 *dst1 = dst0 + (dstPitch >> 2); + + uint32 *src0 = (uint32 *)srcPtr; + uint32 *src1 = src0 + (srcPitch >> 2); + uint32 *src2 = src1 + (srcPitch >> 2); + hq2xS_32_def(dst0, dst1, src0, src0, src1, width); + + int count = height; + + count -= 2; + while(count) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2xS_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2xS_32_def(dst0, dst1, src0, src1, src1, width); +} + +#if !_16BPP_HACK +void lq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint16 *dst0 = (uint16 *)dstPtr; + uint16 *dst1 = dst0 + (dstPitch >> 1); + + uint16 *src0 = (uint16 *)srcPtr; + uint16 *src1 = src0 + (srcPitch >> 1); + uint16 *src2 = src1 + (srcPitch >> 1); + + int count; + + lq2x_16_def(dst0, dst1, src0, src0, src1, width); + if( height == 1 ) return; + + count = height; + + count -= 2; + while(count>0) { + dst0 += dstPitch; + dst1 += dstPitch; + hq2x_16_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 1; + --count; + } + dst0 += dstPitch; + dst1 += dstPitch; + lq2x_16_def(dst0, dst1, src0, src1, src1, width); +} + +void lq2xS_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint16 *dst0 = (uint16 *)dstPtr; + uint16 *dst1 = dst0 + (dstPitch >> 1); + + uint16 *src0 = (uint16 *)srcPtr; + uint16 *src1 = src0 + (srcPitch >> 1); + uint16 *src2 = src1 + (srcPitch >> 1); + + int count; + + lq2xS_16_def(dst0, dst1, src0, src0, src1, width); + if( height == 1 ) return; + + count = height; + + count -= 2; + while(count>0) { + dst0 += dstPitch; + dst1 += dstPitch; + hq2x_16_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 1; + --count; + } + dst0 += dstPitch; + dst1 += dstPitch; + lq2xS_16_def(dst0, dst1, src0, src1, src1, width); +} +#endif /* !_16BPP_HACK */ + +void lq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint32 *dst0 = (uint32 *)dstPtr; + uint32 *dst1 = dst0 + (dstPitch >> 2); + + uint32 *src0 = (uint32 *)srcPtr; + uint32 *src1 = src0 + (srcPitch >> 2); + uint32 *src2 = src1 + (srcPitch >> 2); + + int count; + + lq2x_32_def(dst0, dst1, src0, src0, src1, width); + if( height == 1 ) return; + + count = height; + + count -= 2; + while(count>0) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + lq2x_32_def(dst0, dst1, src0, src1, src1, width); +} + +void lq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint32 *dst0 = (uint32 *)dstPtr; + uint32 *dst1 = dst0 + (dstPitch >> 2); + + uint32 *src0 = (uint32 *)srcPtr; + uint32 *src1 = src0 + (srcPitch >> 2); + uint32 *src2 = src1 + (srcPitch >> 2); + + int count; + + lq2xS_32_def(dst0, dst1, src0, src0, src1, width); + if( height == 1 ) return; + + count = height; + + count -= 2; + while(count>0) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + lq2xS_32_def(dst0, dst1, src0, src1, src1, width); +} + +/************************************************************************/ +/* hq3x filters */ +/************************************************************************/ + +/************************************************************************/ +/* scale2x filters */ +/************************************************************************/ + +/************************************************************************/ +/* scale3x filters */ +/************************************************************************/ + diff --git a/GLideNHQ/TextureFilters_hq2x.h b/GLideNHQ/TextureFilters_hq2x.h new file mode 100644 index 00000000..7946323b --- /dev/null +++ b/GLideNHQ/TextureFilters_hq2x.h @@ -0,0 +1,1847 @@ +/* +Copyright (C) 2003 Rice1964 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +/* Copyright (C) 2007 Hiroshi Morii + * Modified for the Texture Filtering library + */ + +case 0 : +case 1 : +case 4 : +case 5 : +case 32 : +case 33 : +case 36 : +case 37 : +case 128 : +case 129 : +case 132 : +case 133 : +case 160 : +case 161 : +case 164 : +case 165 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 2 : +case 34 : +case 130 : +case 162 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 3 : +case 35 : +case 131 : +case 163 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 6 : +case 38 : +case 134 : +case 166 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 7 : +case 39 : +case 135 : +case 167 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 8 : +case 12 : +case 136 : +case 140 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); +} break; +case 9 : +case 13 : +case 137 : +case 141 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); +} break; +case 10 : +case 138 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 11 : +case 139 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 14 : +case 142 : +{ + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (HQ2X_MUL) { + P0 = I31(4, 0); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 15 : +case 143 : +{ + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (HQ2X_MUL) { + P0 = IC(4); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 16 : +case 17 : +case 48 : +case 49 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); +} break; +case 18 : +case 50 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 19 : +case 51 : +{ + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (HQ2X_MUR) { + P0 = I31(4, 3); + P1 = I31(4, 2); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 20 : +case 21 : +case 52 : +case 53 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); +} break; +case 22 : +case 54 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 23 : +case 55 : +{ + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (HQ2X_MUR) { + P0 = I31(4, 3); + P1 = IC(4); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 24 : +case 66 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 25 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 26 : +case 31 : +case 95 : +{ + P2 = I31(4, 6); + P3 = I31(4, 8); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 27 : +case 75 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 28 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 29 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 30 : +case 86 : +{ + P0 = I31(4, 0); + P2 = I31(4, 6); + P3 = I31(4, 8); + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 40 : +case 44 : +case 168 : +case 172 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); +} break; +case 41 : +case 45 : +case 169 : +case 173 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); +} break; +case 42 : +case 170 : +{ + P1 = I31(4, 2); + P3 = I211(4, 5, 7); + if (HQ2X_MUL) { + P0 = I31(4, 0); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 43 : +case 171 : +{ + P1 = I31(4, 2); + P3 = I211(4, 5, 7); + if (HQ2X_MUL) { + P0 = IC(4); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 46 : +case 174 : +{ + P1 = I31(4, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 47 : +case 175 : +{ + P1 = I31(4, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 56 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 57 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 58 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 59 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 60 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 61 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 62 : +{ + P0 = I31(4, 0); + P2 = I31(4, 7); + P3 = I31(4, 8); + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 63 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 64 : +case 65 : +case 68 : +case 69 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 67 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 70 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 71 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 72 : +case 76 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 73 : +case 77 : +{ + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P0 = I31(4, 1); + P2 = I31(4, 6); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 74 : +case 107 : +case 123 : +{ + P1 = I31(4, 2); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 78 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 79 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 80 : +case 81 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 82 : +case 214 : +case 222 : +{ + P0 = I31(4, 0); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 83 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 84 : +case 85 : +{ + P0 = I211(4, 1, 3); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P1 = I31(4, 1); + P3 = I31(4, 8); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 87 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 88 : +case 248 : +case 250 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 89 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 90 : +{ + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 91 : +{ + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 92 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 93 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 94 : +{ + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 96 : +case 97 : +case 100 : +case 101 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 98 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 99 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 102 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 103 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 104 : +case 108 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 105 : +case 109 : +{ + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P0 = I31(4, 1); + P2 = IC(4); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 106 : +case 120 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 110 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 111 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 112 : +case 113 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + if (HQ2X_MDR) { + P2 = I31(4, 3); + P3 = I31(4, 8); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 114 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 115 : +{ + P0 = I31(4, 3); + P2 = I31(4, 3); + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 116 : +case 117 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I31(4, 3); + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 118 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + P3 = I31(4, 8); + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 119 : +{ + P2 = I31(4, 3); + P3 = I31(4, 8); + if (HQ2X_MUR) { + P0 = I31(4, 3); + P1 = IC(4); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 121 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 122 : +{ + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 124 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 125 : +{ + P1 = I31(4, 1); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P0 = I31(4, 1); + P2 = IC(4); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 126 : +{ + P0 = I31(4, 0); + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 127 : +{ + P3 = I31(4, 8); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 144 : +case 145 : +case 176 : +case 177 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); +} break; +case 146 : +case 178 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + if (HQ2X_MUR) { + P1 = I31(4, 2); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 147 : +case 179 : +{ + P0 = I31(4, 3); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 148 : +case 149 : +case 180 : +case 181 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); +} break; +case 150 : +case 182 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + if (HQ2X_MUR) { + P1 = IC(4); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 151 : +case 183 : +{ + P0 = I31(4, 3); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 152 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 153 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 154 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 155 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 156 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 157 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 158 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 159 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 184 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 185 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 186 : +{ + P2 = I31(4, 7); + P3 = I31(4, 7); + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 187 : +{ + P1 = I31(4, 2); + P3 = I31(4, 7); + if (HQ2X_MUL) { + P0 = IC(4); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 188 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 189 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 190 : +{ + P0 = I31(4, 0); + P2 = I31(4, 7); + if (HQ2X_MUR) { + P1 = IC(4); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 191 : +{ + P2 = I31(4, 7); + P3 = I31(4, 7); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 192 : +case 193 : +case 196 : +case 197 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 194 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 195 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 198 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 199 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 200 : +case 204 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + if (HQ2X_MDL) { + P2 = I31(4, 6); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 201 : +case 205 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P3 = I31(4, 5); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } +} break; +case 202 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 203 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 206 : +{ + P1 = I31(4, 5); + P3 = I31(4, 5); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 207 : +{ + P2 = I31(4, 6); + P3 = I31(4, 5); + if (HQ2X_MUL) { + P0 = IC(4); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 208 : +case 209 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 210 : +case 216 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 211 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 212 : +case 213 : +{ + P0 = I211(4, 1, 3); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P1 = I31(4, 1); + P3 = IC(4); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 215 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 217 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 218 : +{ + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 219 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 220 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (HQ2X_MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 221 : +{ + P0 = I31(4, 1); + P2 = I31(4, 6); + if (HQ2X_MDR) { + P1 = I31(4, 1); + P3 = IC(4); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 223 : +{ + P2 = I31(4, 6); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 224 : +case 225 : +case 228 : +case 229 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 226 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 227 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 230 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 231 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 232 : +case 236 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + if (HQ2X_MDL) { + P2 = IC(4); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 233 : +case 237 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P3 = I31(4, 5); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } +} break; +case 234 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 235 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 238 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + if (HQ2X_MDL) { + P2 = IC(4); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 239 : +{ + P1 = I31(4, 5); + P3 = I31(4, 5); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 240 : +case 241 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + if (HQ2X_MDR) { + P2 = I31(4, 3); + P3 = IC(4); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 242 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 243 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + if (HQ2X_MDR) { + P2 = I31(4, 3); + P3 = IC(4); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 244 : +case 245 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I31(4, 3); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 246 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 247 : +{ + P0 = I31(4, 3); + P2 = I31(4, 3); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 249 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 251 : +{ + P1 = I31(4, 2); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 252 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 253 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 254 : +{ + P0 = I31(4, 0); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 255 : +{ + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; diff --git a/GLideNHQ/TextureFilters_hq4x.cpp b/GLideNHQ/TextureFilters_hq4x.cpp new file mode 100644 index 00000000..89c14ea2 --- /dev/null +++ b/GLideNHQ/TextureFilters_hq4x.cpp @@ -0,0 +1,892 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Based on Maxim Stepin and Rice1964 hq4x code */ + +#include +#include +#include "TextureFilters.h" + +#if !_16BPP_HACK +static uint32 RGB444toYUV[4096]; +#define RGB444toYUV(val) RGB444toYUV[val & 0x0FFF] /* val = ARGB4444 */ + +/*inline static uint32 RGB444toYUV(uint32 val) +{ + uint32 r, g, b, Y, u, v; + + r = (val & 0x0F00) >> 4; + g = (val & 0x00F0); + b = val & 0x000F; + r |= r >> 4; + g |= g >> 4; + b |= b << 4; + + Y = (r + g + b) >> 2; + u = 128 + ((r - b) >> 2); + v = 128 + ((2*g - r - b)>>3); + + return ((Y << 16) | (u << 8) | v); +}*/ + +static uint32 RGB555toYUV(uint32 val) +{ + uint32 r, g, b, Y, u, v; + + r = (val & 0x7C00) >> 7; + g = (val & 0x03E0) >> 2; + b = (val & 0x001F) << 3; + r |= r >> 5; + g |= g >> 5; + b |= b >> 5; + + Y = (r + g + b) >> 2; + u = 128 + ((r - b) >> 2); + v = 128 + ((2*g - r - b)>>3); + + return ((Y << 16) | (u << 8) | v); +} + +static uint32 RGB565toYUV(uint32 val) +{ + uint32 r, g, b, Y, u, v; + + r = (val & 0xF800) >> 8; + g = (val & 0x07E0) >> 3; + b = (val & 0x001F) << 3; + r |= r >> 5; + g |= g >> 6; + b |= b >> 5; + + Y = (r + g + b) >> 2; + u = 128 + ((r - b) >> 2); + v = 128 + ((2*g - r - b)>>3); + + return ((Y << 16) | (u << 8) | v); +} +#endif /* !_16BPP_HACK */ + +static uint32 RGB888toYUV(uint32 val) +{ +#if 0 + uint32 Yuv; + + __asm { + mov eax, dword ptr [val]; + mov ebx, eax; + mov ecx, eax; + and ebx, 0x000000ff; // b + and eax, 0x00ff0000; // r + and ecx, 0x0000ff00; // g + shl ebx, 14; + shr eax, 2; + shl ecx, 6; + mov edx, ebx; + add edx, eax; + add edx, ecx; + and edx, 0xffff0000; + + sub eax, ebx; + add eax, 0x00800000; + shr eax, 8; + or edx, eax; + sub eax, 0x00800000; + and edx, 0xffffff00; + + add ecx, 0x00800000; + shr ecx, 5; + shr ebx, 7; + add eax, ebx; + sub ecx, eax; + shr ecx, 11; + or edx, ecx; + + mov dword ptr [Yuv], edx; + } + + return Yuv; +#else + uint32 r, g, b, Y, u, v; + + r = (val & 0x00ff0000) >> 16; + g = (val & 0x0000ff00) >> 8; + b = val & 0x000000ff; + + Y = (r + g + b) >> 2; + u = (0x00000200 + r - b) >> 2; + v = (0x00000400 + (g << 1) - r - b) >> 3; + + return ((Y << 16) | (u << 8) | v); +#endif +} + +#define Ymask 0x00FF0000 +#define Umask 0x0000FF00 +#define Vmask 0x000000FF +#define trY 0x00300000 // ? +#define trU 0x00000700 // ?? +#define trV 0x00000006 // ??? + +#define HQ4X_INTERP1(n, b) \ +static void hq4x_Interp1_##n (uint8 * pc, uint##b p1, uint##b p2) \ +{ \ + /* *((uint##b*)pc) = (p1*3+p2) >> 2; */ \ + *((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*3 + INTERP_##n##_MASK_1_3(p2)) / 4) \ + | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*3 + INTERP_##n##_MASK_SHIFT_2_4(p2)) / 4 ); \ +} + +#define HQ4X_INTERP2(n, b) \ +static void hq4x_Interp2_##n (uint8 * pc, uint##b p1, uint##b p2, uint##b p3) \ +{ \ + /**((uint##b*)pc) = (p1*2+p2+p3) >> 2;*/ \ + *((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*2 + INTERP_##n##_MASK_1_3(p2) + INTERP_##n##_MASK_1_3(p3)) / 4) \ + | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*2 + INTERP_##n##_MASK_SHIFT_2_4(p2) + INTERP_##n##_MASK_SHIFT_2_4(p3)) / 4); \ +} + +#define HQ4X_INTERP3(n, b) \ +static void hq4x_Interp3_##n (uint8 * pc, uint##b p1, uint##b p2) \ +{ \ + /**((uint##b*)pc) = (p1*7+p2)/8;*/ \ + *((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*7 + INTERP_##n##_MASK_1_3(p2)) / 8) \ + | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*7 + INTERP_##n##_MASK_SHIFT_2_4(p2)) / 8); \ +} + +#define HQ4X_INTERP5(n, b) \ +static void hq4x_Interp5_##n (uint8 * pc, uint##b p1, uint##b p2) \ +{ \ + /**((uint##b*)pc) = (p1+p2) >> 1;*/ \ + *((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1) + INTERP_##n##_MASK_1_3(p2)) / 2) \ + | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1) + INTERP_##n##_MASK_SHIFT_2_4(p2)) / 2); \ +} + +#define HQ4X_INTERP6(n, b) \ +static void hq4x_Interp6_##n (uint8 * pc, uint##b p1, uint##b p2, uint##b p3) \ +{ \ + /**((uint##b*)pc) = (p1*5+p2*2+p3)/8;*/ \ + *((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*5 + INTERP_##n##_MASK_1_3(p2)*2 + INTERP_##n##_MASK_1_3(p3)) / 8) \ + | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*5 + INTERP_##n##_MASK_SHIFT_2_4(p2)*2 + INTERP_##n##_MASK_SHIFT_2_4(p3)) / 8); \ +} + +#define HQ4X_INTERP7(n, b) \ +static void hq4x_Interp7_##n (uint8 * pc, uint##b p1, uint##b p2, uint##b p3) \ +{ \ + /**((uint##b*)pc) = (p1*6+p2+p3)/8;*/ \ + *((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*6 + INTERP_##n##_MASK_1_3(p2) + INTERP_##n##_MASK_1_3(p3)) / 8) \ + | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*6 + INTERP_##n##_MASK_SHIFT_2_4(p2) + INTERP_##n##_MASK_SHIFT_2_4(p3)) / 8); \ +} + +#define HQ4X_INTERP8(n, b) \ +static void hq4x_Interp8_##n (uint8 * pc, uint##b p1, uint##b p2) \ +{ \ + /**((uint##b*)pc) = (p1*5+p2*3)/8;*/ \ + *((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*5 + INTERP_##n##_MASK_1_3(p2)*3) / 8) \ + | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*5 + INTERP_##n##_MASK_SHIFT_2_4(p2)*3) / 8); \ +} + +#if !_16BPP_HACK +#define INTERP_4444_MASK_1_3(v) (v & 0x0F0F) +#define INTERP_4444_MASK_SHIFT_2_4(v) ((v & 0xF0F0) >> 4) +#define INTERP_4444_MASK_SHIFTBACK_2_4(v) (INTERP_4444_MASK_1_3(v) << 4) +HQ4X_INTERP1(4444, 16) +HQ4X_INTERP2(4444, 16) +HQ4X_INTERP3(4444, 16) +HQ4X_INTERP5(4444, 16) +HQ4X_INTERP6(4444, 16) +HQ4X_INTERP7(4444, 16) +HQ4X_INTERP8(4444, 16) + +#define INTERP_1555_MASK_1_3(v) (v & 0x7C1F) +#define INTERP_1555_MASK_SHIFT_2_4(v) ((v & 0x83E0) >> 5) +#define INTERP_1555_MASK_SHIFTBACK_2_4(v) (INTERP_1555_MASK_1_3(v) << 5) +HQ4X_INTERP1(1555, 16) +HQ4X_INTERP2(1555, 16) +HQ4X_INTERP3(1555, 16) +HQ4X_INTERP5(1555, 16) +HQ4X_INTERP6(1555, 16) +HQ4X_INTERP7(1555, 16) +HQ4X_INTERP8(1555, 16) + +#define INTERP_565_MASK_1_3(v) (v & 0xF81F) +#define INTERP_565_MASK_SHIFT_2_4(v) ((v & 0x7E0) >> 5) +#define INTERP_565_MASK_SHIFTBACK_2_4(v) (INTERP_565_MASK_1_3(v) << 5) +HQ4X_INTERP1(565, 16) +HQ4X_INTERP2(565, 16) +HQ4X_INTERP3(565, 16) +HQ4X_INTERP5(565, 16) +HQ4X_INTERP6(565, 16) +HQ4X_INTERP7(565, 16) +HQ4X_INTERP8(565, 16) +#endif /* !_16BPP_HACK */ + +#define INTERP_8888_MASK_1_3(v) (v & 0x00FF00FF) +#define INTERP_8888_MASK_SHIFT_2_4(v) ((v & 0xFF00FF00) >> 8) +#define INTERP_8888_MASK_SHIFTBACK_2_4(v) (INTERP_8888_MASK_1_3(v) << 8) +HQ4X_INTERP1(8888, 32) +HQ4X_INTERP2(8888, 32) +HQ4X_INTERP3(8888, 32) +HQ4X_INTERP5(8888, 32) +HQ4X_INTERP6(8888, 32) +HQ4X_INTERP7(8888, 32) +HQ4X_INTERP8(8888, 32) + +#define PIXEL00_0 *((int*)(pOut)) = c[5]; +#define PIXEL00_11 hq4x_Interp1(pOut, c[5], c[4]); +#define PIXEL00_12 hq4x_Interp1(pOut, c[5], c[2]); +#define PIXEL00_20 hq4x_Interp2(pOut, c[5], c[2], c[4]); +#define PIXEL00_50 hq4x_Interp5(pOut, c[2], c[4]); +#define PIXEL00_80 hq4x_Interp8(pOut, c[5], c[1]); +#define PIXEL00_81 hq4x_Interp8(pOut, c[5], c[4]); +#define PIXEL00_82 hq4x_Interp8(pOut, c[5], c[2]); +#define PIXEL01_0 *((int*)(pOut+BPP)) = c[5]; +#define PIXEL01_10 hq4x_Interp1(pOut+BPP, c[5], c[1]); +#define PIXEL01_12 hq4x_Interp1(pOut+BPP, c[5], c[2]); +#define PIXEL01_14 hq4x_Interp1(pOut+BPP, c[2], c[5]); +#define PIXEL01_21 hq4x_Interp2(pOut+BPP, c[2], c[5], c[4]); +#define PIXEL01_31 hq4x_Interp3(pOut+BPP, c[5], c[4]); +#define PIXEL01_50 hq4x_Interp5(pOut+BPP, c[2], c[5]); +#define PIXEL01_60 hq4x_Interp6(pOut+BPP, c[5], c[2], c[4]); +#define PIXEL01_61 hq4x_Interp6(pOut+BPP, c[5], c[2], c[1]); +#define PIXEL01_82 hq4x_Interp8(pOut+BPP, c[5], c[2]); +#define PIXEL01_83 hq4x_Interp8(pOut+BPP, c[2], c[4]); +#define PIXEL02_0 *((int*)(pOut+BPP2)) = c[5]; +#define PIXEL02_10 hq4x_Interp1(pOut+BPP2, c[5], c[3]); +#define PIXEL02_11 hq4x_Interp1(pOut+BPP2, c[5], c[2]); +#define PIXEL02_13 hq4x_Interp1(pOut+BPP2, c[2], c[5]); +#define PIXEL02_21 hq4x_Interp2(pOut+BPP2, c[2], c[5], c[6]); +#define PIXEL02_32 hq4x_Interp3(pOut+BPP2, c[5], c[6]); +#define PIXEL02_50 hq4x_Interp5(pOut+BPP2, c[2], c[5]); +#define PIXEL02_60 hq4x_Interp6(pOut+BPP2, c[5], c[2], c[6]); +#define PIXEL02_61 hq4x_Interp6(pOut+BPP2, c[5], c[2], c[3]); +#define PIXEL02_81 hq4x_Interp8(pOut+BPP2, c[5], c[2]); +#define PIXEL02_83 hq4x_Interp8(pOut+BPP2, c[2], c[6]); +#define PIXEL03_0 *((int*)(pOut+BPP3)) = c[5]; +#define PIXEL03_11 hq4x_Interp1(pOut+BPP3, c[5], c[2]); +#define PIXEL03_12 hq4x_Interp1(pOut+BPP3, c[5], c[6]); +#define PIXEL03_20 hq4x_Interp2(pOut+BPP3, c[5], c[2], c[6]); +#define PIXEL03_50 hq4x_Interp5(pOut+BPP3, c[2], c[6]); +#define PIXEL03_80 hq4x_Interp8(pOut+BPP3, c[5], c[3]); +#define PIXEL03_81 hq4x_Interp8(pOut+BPP3, c[5], c[2]); +#define PIXEL03_82 hq4x_Interp8(pOut+BPP3, c[5], c[6]); +#define PIXEL10_0 *((int*)(pOut+BpL)) = c[5]; +#define PIXEL10_10 hq4x_Interp1(pOut+BpL, c[5], c[1]); +#define PIXEL10_11 hq4x_Interp1(pOut+BpL, c[5], c[4]); +#define PIXEL10_13 hq4x_Interp1(pOut+BpL, c[4], c[5]); +#define PIXEL10_21 hq4x_Interp2(pOut+BpL, c[4], c[5], c[2]); +#define PIXEL10_32 hq4x_Interp3(pOut+BpL, c[5], c[2]); +#define PIXEL10_50 hq4x_Interp5(pOut+BpL, c[4], c[5]); +#define PIXEL10_60 hq4x_Interp6(pOut+BpL, c[5], c[4], c[2]); +#define PIXEL10_61 hq4x_Interp6(pOut+BpL, c[5], c[4], c[1]); +#define PIXEL10_81 hq4x_Interp8(pOut+BpL, c[5], c[4]); +#define PIXEL10_83 hq4x_Interp8(pOut+BpL, c[4], c[2]); +#define PIXEL11_0 *((int*)(pOut+BpL+BPP)) = c[5]; +#define PIXEL11_30 hq4x_Interp3(pOut+BpL+BPP, c[5], c[1]); +#define PIXEL11_31 hq4x_Interp3(pOut+BpL+BPP, c[5], c[4]); +#define PIXEL11_32 hq4x_Interp3(pOut+BpL+BPP, c[5], c[2]); +#define PIXEL11_70 hq4x_Interp7(pOut+BpL+BPP, c[5], c[4], c[2]); +#define PIXEL12_0 *((int*)(pOut+BpL+BPP2)) = c[5]; +#define PIXEL12_30 hq4x_Interp3(pOut+BpL+BPP2, c[5], c[3]); +#define PIXEL12_31 hq4x_Interp3(pOut+BpL+BPP2, c[5], c[2]); +#define PIXEL12_32 hq4x_Interp3(pOut+BpL+BPP2, c[5], c[6]); +#define PIXEL12_70 hq4x_Interp7(pOut+BpL+BPP2, c[5], c[6], c[2]); +#define PIXEL13_0 *((int*)(pOut+BpL+BPP3)) = c[5]; +#define PIXEL13_10 hq4x_Interp1(pOut+BpL+BPP3, c[5], c[3]); +#define PIXEL13_12 hq4x_Interp1(pOut+BpL+BPP3, c[5], c[6]); +#define PIXEL13_14 hq4x_Interp1(pOut+BpL+BPP3, c[6], c[5]); +#define PIXEL13_21 hq4x_Interp2(pOut+BpL+BPP3, c[6], c[5], c[2]); +#define PIXEL13_31 hq4x_Interp3(pOut+BpL+BPP3, c[5], c[2]); +#define PIXEL13_50 hq4x_Interp5(pOut+BpL+BPP3, c[6], c[5]); +#define PIXEL13_60 hq4x_Interp6(pOut+BpL+BPP3, c[5], c[6], c[2]); +#define PIXEL13_61 hq4x_Interp6(pOut+BpL+BPP3, c[5], c[6], c[3]); +#define PIXEL13_82 hq4x_Interp8(pOut+BpL+BPP3, c[5], c[6]); +#define PIXEL13_83 hq4x_Interp8(pOut+BpL+BPP3, c[6], c[2]); +#define PIXEL20_0 *((int*)(pOut+BpL+BpL)) = c[5]; +#define PIXEL20_10 hq4x_Interp1(pOut+BpL+BpL, c[5], c[7]); +#define PIXEL20_12 hq4x_Interp1(pOut+BpL+BpL, c[5], c[4]); +#define PIXEL20_14 hq4x_Interp1(pOut+BpL+BpL, c[4], c[5]); +#define PIXEL20_21 hq4x_Interp2(pOut+BpL+BpL, c[4], c[5], c[8]); +#define PIXEL20_31 hq4x_Interp3(pOut+BpL+BpL, c[5], c[8]); +#define PIXEL20_50 hq4x_Interp5(pOut+BpL+BpL, c[4], c[5]); +#define PIXEL20_60 hq4x_Interp6(pOut+BpL+BpL, c[5], c[4], c[8]); +#define PIXEL20_61 hq4x_Interp6(pOut+BpL+BpL, c[5], c[4], c[7]); +#define PIXEL20_82 hq4x_Interp8(pOut+BpL+BpL, c[5], c[4]); +#define PIXEL20_83 hq4x_Interp8(pOut+BpL+BpL, c[4], c[8]); +#define PIXEL21_0 *((int*)(pOut+BpL+BpL+BPP)) = c[5]; +#define PIXEL21_30 hq4x_Interp3(pOut+BpL+BpL+BPP, c[5], c[7]); +#define PIXEL21_31 hq4x_Interp3(pOut+BpL+BpL+BPP, c[5], c[8]); +#define PIXEL21_32 hq4x_Interp3(pOut+BpL+BpL+BPP, c[5], c[4]); +#define PIXEL21_70 hq4x_Interp7(pOut+BpL+BpL+BPP, c[5], c[4], c[8]); +#define PIXEL22_0 *((int*)(pOut+BpL+BpL+BPP2)) = c[5]; +#define PIXEL22_30 hq4x_Interp3(pOut+BpL+BpL+BPP2, c[5], c[9]); +#define PIXEL22_31 hq4x_Interp3(pOut+BpL+BpL+BPP2, c[5], c[6]); +#define PIXEL22_32 hq4x_Interp3(pOut+BpL+BpL+BPP2, c[5], c[8]); +#define PIXEL22_70 hq4x_Interp7(pOut+BpL+BpL+BPP2, c[5], c[6], c[8]); +#define PIXEL23_0 *((int*)(pOut+BpL+BpL+BPP3)) = c[5]; +#define PIXEL23_10 hq4x_Interp1(pOut+BpL+BpL+BPP3, c[5], c[9]); +#define PIXEL23_11 hq4x_Interp1(pOut+BpL+BpL+BPP3, c[5], c[6]); +#define PIXEL23_13 hq4x_Interp1(pOut+BpL+BpL+BPP3, c[6], c[5]); +#define PIXEL23_21 hq4x_Interp2(pOut+BpL+BpL+BPP3, c[6], c[5], c[8]); +#define PIXEL23_32 hq4x_Interp3(pOut+BpL+BpL+BPP3, c[5], c[8]); +#define PIXEL23_50 hq4x_Interp5(pOut+BpL+BpL+BPP3, c[6], c[5]); +#define PIXEL23_60 hq4x_Interp6(pOut+BpL+BpL+BPP3, c[5], c[6], c[8]); +#define PIXEL23_61 hq4x_Interp6(pOut+BpL+BpL+BPP3, c[5], c[6], c[9]); +#define PIXEL23_81 hq4x_Interp8(pOut+BpL+BpL+BPP3, c[5], c[6]); +#define PIXEL23_83 hq4x_Interp8(pOut+BpL+BpL+BPP3, c[6], c[8]); +#define PIXEL30_0 *((int*)(pOut+BpL+BpL+BpL)) = c[5]; +#define PIXEL30_11 hq4x_Interp1(pOut+BpL+BpL+BpL, c[5], c[8]); +#define PIXEL30_12 hq4x_Interp1(pOut+BpL+BpL+BpL, c[5], c[4]); +#define PIXEL30_20 hq4x_Interp2(pOut+BpL+BpL+BpL, c[5], c[8], c[4]); +#define PIXEL30_50 hq4x_Interp5(pOut+BpL+BpL+BpL, c[8], c[4]); +#define PIXEL30_80 hq4x_Interp8(pOut+BpL+BpL+BpL, c[5], c[7]); +#define PIXEL30_81 hq4x_Interp8(pOut+BpL+BpL+BpL, c[5], c[8]); +#define PIXEL30_82 hq4x_Interp8(pOut+BpL+BpL+BpL, c[5], c[4]); +#define PIXEL31_0 *((int*)(pOut+BpL+BpL+BpL+BPP)) = c[5]; +#define PIXEL31_10 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP, c[5], c[7]); +#define PIXEL31_11 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP, c[5], c[8]); +#define PIXEL31_13 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP, c[8], c[5]); +#define PIXEL31_21 hq4x_Interp2(pOut+BpL+BpL+BpL+BPP, c[8], c[5], c[4]); +#define PIXEL31_32 hq4x_Interp3(pOut+BpL+BpL+BpL+BPP, c[5], c[4]); +#define PIXEL31_50 hq4x_Interp5(pOut+BpL+BpL+BpL+BPP, c[8], c[5]); +#define PIXEL31_60 hq4x_Interp6(pOut+BpL+BpL+BpL+BPP, c[5], c[8], c[4]); +#define PIXEL31_61 hq4x_Interp6(pOut+BpL+BpL+BpL+BPP, c[5], c[8], c[7]); +#define PIXEL31_81 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP, c[5], c[8]); +#define PIXEL31_83 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP, c[8], c[4]); +#define PIXEL32_0 *((int*)(pOut+BpL+BpL+BpL+BPP2)) = c[5]; +#define PIXEL32_10 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP2, c[5], c[9]); +#define PIXEL32_12 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP2, c[5], c[8]); +#define PIXEL32_14 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP2, c[8], c[5]); +#define PIXEL32_21 hq4x_Interp2(pOut+BpL+BpL+BpL+BPP2, c[8], c[5], c[6]); +#define PIXEL32_31 hq4x_Interp3(pOut+BpL+BpL+BpL+BPP2, c[5], c[6]); +#define PIXEL32_50 hq4x_Interp5(pOut+BpL+BpL+BpL+BPP2, c[8], c[5]); +#define PIXEL32_60 hq4x_Interp6(pOut+BpL+BpL+BpL+BPP2, c[5], c[8], c[6]); +#define PIXEL32_61 hq4x_Interp6(pOut+BpL+BpL+BpL+BPP2, c[5], c[8], c[9]); +#define PIXEL32_82 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP2, c[5], c[8]); +#define PIXEL32_83 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP2, c[8], c[6]); +#define PIXEL33_0 *((int*)(pOut+BpL+BpL+BpL+BPP3)) = c[5]; +#define PIXEL33_11 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP3, c[5], c[6]); +#define PIXEL33_12 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP3, c[5], c[8]); +#define PIXEL33_20 hq4x_Interp2(pOut+BpL+BpL+BpL+BPP3, c[5], c[8], c[6]); +#define PIXEL33_50 hq4x_Interp5(pOut+BpL+BpL+BpL+BPP3, c[8], c[6]); +#define PIXEL33_80 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP3, c[5], c[9]); +#define PIXEL33_81 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP3, c[5], c[6]); +#define PIXEL33_82 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP3, c[5], c[8]); + +#define HQ4X_DIFF(n, b) \ +static int Diff_##n (uint##b w1, uint##b w2) \ +{ \ + int YUV1, YUV2; \ + YUV1 = RGB##n##toYUV(w1); \ + YUV2 = RGB##n##toYUV(w2); \ + return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || \ + ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || \ + ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ); \ +} + +HQ4X_DIFF(888, 32) + +#if !_16BPP_HACK +HQ4X_DIFF(444, 16) +HQ4X_DIFF(555, 16) +HQ4X_DIFF(565, 16) + +void hq4x_4444(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL) +{ +#define hq4x_Interp1 hq4x_Interp1_4444 +#define hq4x_Interp2 hq4x_Interp2_4444 +#define hq4x_Interp3 hq4x_Interp3_4444 +#define hq4x_Interp4 hq4x_Interp4_4444 +#define hq4x_Interp5 hq4x_Interp5_4444 +#define hq4x_Interp6 hq4x_Interp6_4444 +#define hq4x_Interp7 hq4x_Interp7_4444 +#define hq4x_Interp8 hq4x_Interp8_4444 +#define Diff Diff_444 +#define BPP 2 +#define BPP2 4 +#define BPP3 6 + + int i, j, k; + int prevline, nextline; + uint16 w[10]; + uint16 c[10]; + + int pattern; + int flag; + + int YUV1, YUV2; + + // +----+----+----+ + // | | | | + // | w1 | w2 | w3 | + // +----+----+----+ + // | | | | + // | w4 | w5 | w6 | + // +----+----+----+ + // | | | | + // | w7 | w8 | w9 | + // +----+----+----+ + + for (j = 0; j < Yres; j++) { + if (j>0) prevline = -SrcPPL*2; else prevline = 0; + if (j0) { + w[1] = *((uint16*)(pIn + prevline - 2)); + w[4] = *((uint16*)(pIn - 2)); + w[7] = *((uint16*)(pIn + nextline - 2)); + } else { + w[1] = w[2]; + w[4] = w[5]; + w[7] = w[8]; + } + + if (i trY ) || + ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || + ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) + pattern |= flag; + } + flag <<= 1; + } + + for (k=1; k<=9; k++) + c[k] = w[k]; + +#include "TextureFilters_hq4x.h" + + pIn+=2; + pOut+=8; + } + pIn += 2*(SrcPPL-Xres); + pOut+= 8*(SrcPPL-Xres); + pOut+=BpL; + pOut+=BpL; + pOut+=BpL; + } + +#undef BPP +#undef BPP2 +#undef BPP3 +#undef Diff +#undef hq4x_Interp1 +#undef hq4x_Interp2 +#undef hq4x_Interp3 +#undef hq4x_Interp4 +#undef hq4x_Interp5 +#undef hq4x_Interp6 +#undef hq4x_Interp7 +#undef hq4x_Interp8 +} + +void hq4x_1555(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL) +{ +#define hq4x_Interp1 hq4x_Interp1_1555 +#define hq4x_Interp2 hq4x_Interp2_1555 +#define hq4x_Interp3 hq4x_Interp3_1555 +#define hq4x_Interp4 hq4x_Interp4_1555 +#define hq4x_Interp5 hq4x_Interp5_1555 +#define hq4x_Interp6 hq4x_Interp6_1555 +#define hq4x_Interp7 hq4x_Interp7_1555 +#define hq4x_Interp8 hq4x_Interp8_1555 +#define Diff Diff_555 +#define BPP 2 +#define BPP2 4 +#define BPP3 6 + + int i, j, k; + int prevline, nextline; + uint16 w[10]; + uint16 c[10]; + + int pattern; + int flag; + + int YUV1, YUV2; + + // +----+----+----+ + // | | | | + // | w1 | w2 | w3 | + // +----+----+----+ + // | | | | + // | w4 | w5 | w6 | + // +----+----+----+ + // | | | | + // | w7 | w8 | w9 | + // +----+----+----+ + + for (j = 0; j < Yres; j++) { + if (j>0) prevline = -SrcPPL*2; else prevline = 0; + if (j0) { + w[1] = *((uint16*)(pIn + prevline - 2)); + w[4] = *((uint16*)(pIn - 2)); + w[7] = *((uint16*)(pIn + nextline - 2)); + } else { + w[1] = w[2]; + w[4] = w[5]; + w[7] = w[8]; + } + + if (i trY ) || + ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || + ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) + pattern |= flag; + } + flag <<= 1; + } + + for (k=1; k<=9; k++) + c[k] = w[k]; + +#include "TextureFilters_hq4x.h" + + pIn+=2; + pOut+=8; + } + pIn += 2*(SrcPPL-Xres); + pOut+= 8*(SrcPPL-Xres); + pOut+=BpL; + pOut+=BpL; + pOut+=BpL; + } + +#undef BPP +#undef BPP2 +#undef BPP3 +#undef Diff +#undef hq4x_Interp1 +#undef hq4x_Interp2 +#undef hq4x_Interp3 +#undef hq4x_Interp4 +#undef hq4x_Interp5 +#undef hq4x_Interp6 +#undef hq4x_Interp7 +#undef hq4x_Interp8 +} + +void hq4x_565(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL) +{ +#define hq4x_Interp1 hq4x_Interp1_565 +#define hq4x_Interp2 hq4x_Interp2_565 +#define hq4x_Interp3 hq4x_Interp3_565 +#define hq4x_Interp4 hq4x_Interp4_565 +#define hq4x_Interp5 hq4x_Interp5_565 +#define hq4x_Interp6 hq4x_Interp6_565 +#define hq4x_Interp7 hq4x_Interp7_565 +#define hq4x_Interp8 hq4x_Interp8_565 +#define Diff Diff_565 +#define BPP 2 +#define BPP2 4 +#define BPP3 6 + + int i, j, k; + int prevline, nextline; + uint16 w[10]; + uint16 c[10]; + + int pattern; + int flag; + + int YUV1, YUV2; + + // +----+----+----+ + // | | | | + // | w1 | w2 | w3 | + // +----+----+----+ + // | | | | + // | w4 | w5 | w6 | + // +----+----+----+ + // | | | | + // | w7 | w8 | w9 | + // +----+----+----+ + + for (j = 0; j < Yres; j++) { + if (j>0) prevline = -SrcPPL*2; else prevline = 0; + if (j0) { + w[1] = *((uint16*)(pIn + prevline - 2)); + w[4] = *((uint16*)(pIn - 2)); + w[7] = *((uint16*)(pIn + nextline - 2)); + } else { + w[1] = w[2]; + w[4] = w[5]; + w[7] = w[8]; + } + + if (i trY ) || + ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || + ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) + pattern |= flag; + } + flag <<= 1; + } + + for (k=1; k<=9; k++) + c[k] = w[k]; + +#include "TextureFilters_hq4x.h" + + pIn+=2; + pOut+=8; + } + pIn += 2*(SrcPPL-Xres); + pOut+= 8*(SrcPPL-Xres); + pOut+=BpL; + pOut+=BpL; + pOut+=BpL; + } + +#undef BPP +#undef BPP2 +#undef BPP3 +#undef Diff +#undef hq4x_Interp1 +#undef hq4x_Interp2 +#undef hq4x_Interp3 +#undef hq4x_Interp4 +#undef hq4x_Interp5 +#undef hq4x_Interp6 +#undef hq4x_Interp7 +#undef hq4x_Interp8 +} +#endif /* !_16BPP_HACK */ + +void hq4x_8888(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL) +{ +#define hq4x_Interp1 hq4x_Interp1_8888 +#define hq4x_Interp2 hq4x_Interp2_8888 +#define hq4x_Interp3 hq4x_Interp3_8888 +#define hq4x_Interp4 hq4x_Interp4_8888 +#define hq4x_Interp5 hq4x_Interp5_8888 +#define hq4x_Interp6 hq4x_Interp6_8888 +#define hq4x_Interp7 hq4x_Interp7_8888 +#define hq4x_Interp8 hq4x_Interp8_8888 +#define Diff Diff_888 +#define BPP 4 +#define BPP2 8 +#define BPP3 12 + + int i, j, k; + int prevline, nextline; + uint32 w[10]; + uint32 c[10]; + + int pattern; + int flag; + + int YUV1, YUV2; + + // +----+----+----+ + // | | | | + // | w1 | w2 | w3 | + // +----+----+----+ + // | | | | + // | w4 | w5 | w6 | + // +----+----+----+ + // | | | | + // | w7 | w8 | w9 | + // +----+----+----+ + + for (j = 0; j < Yres; j++) { + if (j>0) prevline = -SrcPPL*4; else prevline = 0; + if (j0) { + w[1] = *((uint32*)(pIn + prevline - 4)); + w[4] = *((uint32*)(pIn - 4)); + w[7] = *((uint32*)(pIn + nextline - 4)); + } else { + w[1] = w[2]; + w[4] = w[5]; + w[7] = w[8]; + } + + if (i trY ) || + ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || + ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) + pattern |= flag; + } + flag <<= 1; + } + + for (k=1; k<=9; k++) + c[k] = w[k]; + +#include "TextureFilters_hq4x.h" + + pIn+=4; + pOut+=16; + } + + pIn += 4*(SrcPPL-Xres); + pOut+= 16*(SrcPPL-Xres); + pOut+=BpL; + pOut+=BpL; + pOut+=BpL; + } + +#undef BPP +#undef BPP2 +#undef BPP3 +#undef Diff +#undef hq4x_Interp1 +#undef hq4x_Interp2 +#undef hq4x_Interp3 +#undef hq4x_Interp4 +#undef hq4x_Interp5 +#undef hq4x_Interp6 +#undef hq4x_Interp7 +#undef hq4x_Interp8 +} + +#if !_16BPP_HACK +void hq4x_init(void) +{ + static int done = 0; + int r, g, b, Y, u, v, i, j, k; + + if (done ) return; + + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + for (k = 0; k < 16; k++) { + r = (i << 4) | i; + g = (j << 4) | j; + b = (k << 4) | k; + + /* Microsoft's RGB888->YUV conversion */ + /*Y = ((( 66 * r + 129 * g + 25 * b + 128) >> 8) + 16) & 0xFF; + u = ((( -38 * r - 74 * g + 112 * b + 128) >> 8) + 128) & 0xFF; + v = ((( 112 * r - 94 * g - 18 * b + 128) >> 8) + 128) & 0xFF;*/ + + Y = (r + g + b) >> 2; + u = 128 + ((r - b) >> 2); + v = 128 + ((-r + 2*g -b)>>3); + + RGB444toYUV[(i << 8) | (j << 4) | k] = (Y << 16) | (u << 8) | v; + } + } + } + + done = 1; +} +#endif /* !_16BPP_HACK */ diff --git a/GLideNHQ/TextureFilters_hq4x.h b/GLideNHQ/TextureFilters_hq4x.h new file mode 100644 index 00000000..a3a27403 --- /dev/null +++ b/GLideNHQ/TextureFilters_hq4x.h @@ -0,0 +1,4999 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Based on Maxim Stepin and Rice1964 hq4x code */ + + switch (pattern) + { + case 0: + case 1: + case 4: + case 32: + case 128: + case 5: + case 132: + case 160: + case 33: + case 129: + case 36: + case 133: + case 164: + case 161: + case 37: + case 165: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + break; + } + case 2: + case 34: + case 130: + case 162: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + break; + } + case 16: + case 17: + case 48: + case 49: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + break; + } + case 64: + case 65: + case 68: + case 69: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 8: + case 12: + case 136: + case 140: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + break; + } + case 3: + case 35: + case 131: + case 163: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + break; + } + case 6: + case 38: + case 134: + case 166: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + break; + } + case 20: + case 21: + case 52: + case 53: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + break; + } + case 144: + case 145: + case 176: + case 177: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + break; + } + case 192: + case 193: + case 196: + case 197: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + break; + } + case 96: + case 97: + case 100: + case 101: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + break; + } + case 40: + case 44: + case 168: + case 172: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + break; + } + case 9: + case 13: + case 137: + case 141: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + break; + } + case 18: + case 50: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL12_0 + PIXEL13_50 + } + PIXEL10_61 + PIXEL11_30 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + break; + } + case 80: + case 81: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_61 + PIXEL21_30 + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 72: + case 76: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_50 + PIXEL21_0 + PIXEL30_50 + PIXEL31_50 + } + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 10: + case 138: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + PIXEL11_0 + } + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + break; + } + case 66: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 24: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + break; + } + case 7: + case 39: + case 135: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + break; + } + case 148: + case 149: + case 180: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + break; + } + case 224: + case 228: + case 225: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + break; + } + case 41: + case 169: + case 45: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + break; + } + case 22: + case 54: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + break; + } + case 208: + case 209: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 104: + case 108: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 11: + case 139: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + break; + } + case 19: + case 51: + { + if (Diff(w[2], w[6])) + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL00_12 + PIXEL01_14 + PIXEL02_83 + PIXEL03_50 + PIXEL12_70 + PIXEL13_21 + } + PIXEL10_81 + PIXEL11_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + break; + } + case 146: + case 178: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + PIXEL23_32 + PIXEL33_82 + } + else + { + PIXEL02_21 + PIXEL03_50 + PIXEL12_70 + PIXEL13_83 + PIXEL23_13 + PIXEL33_11 + } + PIXEL10_61 + PIXEL11_30 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + break; + } + case 84: + case 85: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + if (Diff(w[6], w[8])) + { + PIXEL03_81 + PIXEL13_31 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL03_12 + PIXEL13_14 + PIXEL22_70 + PIXEL23_83 + PIXEL32_21 + PIXEL33_50 + } + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL20_61 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + break; + } + case 112: + case 113: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_82 + PIXEL21_32 + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_70 + PIXEL23_21 + PIXEL30_11 + PIXEL31_13 + PIXEL32_83 + PIXEL33_50 + } + break; + } + case 200: + case 204: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + } + else + { + PIXEL20_21 + PIXEL21_70 + PIXEL30_50 + PIXEL31_83 + PIXEL32_14 + PIXEL33_12 + } + PIXEL22_31 + PIXEL23_81 + break; + } + case 73: + case 77: + { + if (Diff(w[8], w[4])) + { + PIXEL00_82 + PIXEL10_32 + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL00_11 + PIXEL10_13 + PIXEL20_83 + PIXEL21_70 + PIXEL30_50 + PIXEL31_21 + } + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 42: + case 170: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + PIXEL20_31 + PIXEL30_81 + } + else + { + PIXEL00_50 + PIXEL01_21 + PIXEL10_83 + PIXEL11_70 + PIXEL20_14 + PIXEL30_12 + } + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + break; + } + case 14: + case 142: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_50 + PIXEL01_83 + PIXEL02_13 + PIXEL03_11 + PIXEL10_21 + PIXEL11_70 + } + PIXEL12_32 + PIXEL13_82 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + break; + } + case 67: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 70: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 28: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + break; + } + case 152: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + break; + } + case 194: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + break; + } + case 98: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + break; + } + case 56: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + break; + } + case 25: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + break; + } + case 26: + case 31: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL11_0 + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + break; + } + case 82: + case 214: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 88: + case 248: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + break; + } + case 74: + case 107: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 27: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + break; + } + case 86: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 216: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 106: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 30: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + break; + } + case 210: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 120: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 75: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 29: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + break; + } + case 198: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + break; + } + case 184: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + break; + } + case 99: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + break; + } + case 57: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + break; + } + case 71: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 156: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + break; + } + case 226: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + break; + } + case 60: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + break; + } + case 195: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + break; + } + case 102: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + break; + } + case 153: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + break; + } + case 58: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + break; + } + case 83: + { + PIXEL00_81 + PIXEL01_31 + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL10_81 + PIXEL11_31 + PIXEL20_61 + PIXEL21_30 + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 92: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + break; + } + case 202: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + PIXEL22_31 + PIXEL23_81 + PIXEL32_31 + PIXEL33_81 + break; + } + case 78: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + PIXEL02_32 + PIXEL03_82 + PIXEL12_32 + PIXEL13_82 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 154: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + break; + } + case 114: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL10_61 + PIXEL11_30 + PIXEL20_82 + PIXEL21_32 + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + PIXEL30_82 + PIXEL31_32 + break; + } + case 89: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + break; + } + case 90: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + break; + } + case 55: + case 23: + { + if (Diff(w[2], w[6])) + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_0 + PIXEL03_0 + PIXEL12_0 + PIXEL13_0 + } + else + { + PIXEL00_12 + PIXEL01_14 + PIXEL02_83 + PIXEL03_50 + PIXEL12_70 + PIXEL13_21 + } + PIXEL10_81 + PIXEL11_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + break; + } + case 182: + case 150: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL12_0 + PIXEL13_0 + PIXEL23_32 + PIXEL33_82 + } + else + { + PIXEL02_21 + PIXEL03_50 + PIXEL12_70 + PIXEL13_83 + PIXEL23_13 + PIXEL33_11 + } + PIXEL10_61 + PIXEL11_30 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + break; + } + case 213: + case 212: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + if (Diff(w[6], w[8])) + { + PIXEL03_81 + PIXEL13_31 + PIXEL22_0 + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL03_12 + PIXEL13_14 + PIXEL22_70 + PIXEL23_83 + PIXEL32_21 + PIXEL33_50 + } + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL20_61 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + break; + } + case 241: + case 240: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_82 + PIXEL21_32 + if (Diff(w[6], w[8])) + { + PIXEL22_0 + PIXEL23_0 + PIXEL30_82 + PIXEL31_32 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL22_70 + PIXEL23_21 + PIXEL30_11 + PIXEL31_13 + PIXEL32_83 + PIXEL33_50 + } + break; + } + case 236: + case 232: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL21_0 + PIXEL30_0 + PIXEL31_0 + PIXEL32_31 + PIXEL33_81 + } + else + { + PIXEL20_21 + PIXEL21_70 + PIXEL30_50 + PIXEL31_83 + PIXEL32_14 + PIXEL33_12 + } + PIXEL22_31 + PIXEL23_81 + break; + } + case 109: + case 105: + { + if (Diff(w[8], w[4])) + { + PIXEL00_82 + PIXEL10_32 + PIXEL20_0 + PIXEL21_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL00_11 + PIXEL10_13 + PIXEL20_83 + PIXEL21_70 + PIXEL30_50 + PIXEL31_21 + } + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 171: + case 43: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + PIXEL11_0 + PIXEL20_31 + PIXEL30_81 + } + else + { + PIXEL00_50 + PIXEL01_21 + PIXEL10_83 + PIXEL11_70 + PIXEL20_14 + PIXEL30_12 + } + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + break; + } + case 143: + case 15: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL02_32 + PIXEL03_82 + PIXEL10_0 + PIXEL11_0 + } + else + { + PIXEL00_50 + PIXEL01_83 + PIXEL02_13 + PIXEL03_11 + PIXEL10_21 + PIXEL11_70 + } + PIXEL12_32 + PIXEL13_82 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + break; + } + case 124: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 203: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + PIXEL20_10 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + break; + } + case 62: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + break; + } + case 211: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_10 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 118: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_10 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + break; + } + case 217: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 110: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_10 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 155: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + break; + } + case 188: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + break; + } + case 185: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + break; + } + case 61: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + break; + } + case 157: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + break; + } + case 103: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + break; + } + case 227: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + break; + } + case 230: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + break; + } + case 199: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + break; + } + case 220: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + break; + } + case 158: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + break; + } + case 234: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_31 + PIXEL23_81 + PIXEL32_31 + PIXEL33_81 + break; + } + case 242: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL10_61 + PIXEL11_30 + PIXEL20_82 + PIXEL21_32 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_82 + PIXEL31_32 + break; + } + case 59: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL11_0 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + break; + } + case 121: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + break; + } + case 87: + { + PIXEL00_81 + PIXEL01_31 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_81 + PIXEL11_31 + PIXEL12_0 + PIXEL20_61 + PIXEL21_30 + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 79: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_32 + PIXEL03_82 + PIXEL11_0 + PIXEL12_32 + PIXEL13_82 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 122: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + break; + } + case 94: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL12_0 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + break; + } + case 218: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + break; + } + case 91: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL11_0 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + break; + } + case 229: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + break; + } + case 167: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + break; + } + case 173: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + break; + } + case 181: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + break; + } + case 186: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + break; + } + case 115: + { + PIXEL00_81 + PIXEL01_31 + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL10_81 + PIXEL11_31 + PIXEL20_82 + PIXEL21_32 + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + PIXEL30_82 + PIXEL31_32 + break; + } + case 93: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + break; + } + case 206: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + PIXEL02_32 + PIXEL03_82 + PIXEL12_32 + PIXEL13_82 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + PIXEL22_31 + PIXEL23_81 + PIXEL32_31 + PIXEL33_81 + break; + } + case 205: + case 201: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + if (Diff(w[8], w[4])) + { + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + } + else + { + PIXEL20_12 + PIXEL21_0 + PIXEL30_20 + PIXEL31_11 + } + PIXEL22_31 + PIXEL23_81 + PIXEL32_31 + PIXEL33_81 + break; + } + case 174: + case 46: + { + if (Diff(w[4], w[2])) + { + PIXEL00_80 + PIXEL01_10 + PIXEL10_10 + PIXEL11_30 + } + else + { + PIXEL00_20 + PIXEL01_12 + PIXEL10_11 + PIXEL11_0 + } + PIXEL02_32 + PIXEL03_82 + PIXEL12_32 + PIXEL13_82 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + break; + } + case 179: + case 147: + { + PIXEL00_81 + PIXEL01_31 + if (Diff(w[2], w[6])) + { + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + } + else + { + PIXEL02_11 + PIXEL03_20 + PIXEL12_0 + PIXEL13_12 + } + PIXEL10_81 + PIXEL11_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + break; + } + case 117: + case 116: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_82 + PIXEL21_32 + if (Diff(w[6], w[8])) + { + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + } + else + { + PIXEL22_0 + PIXEL23_11 + PIXEL32_12 + PIXEL33_20 + } + PIXEL30_82 + PIXEL31_32 + break; + } + case 189: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + break; + } + case 231: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + break; + } + case 126: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 219: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 125: + { + if (Diff(w[8], w[4])) + { + PIXEL00_82 + PIXEL10_32 + PIXEL20_0 + PIXEL21_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL00_11 + PIXEL10_13 + PIXEL20_83 + PIXEL21_70 + PIXEL30_50 + PIXEL31_21 + } + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 221: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + if (Diff(w[6], w[8])) + { + PIXEL03_81 + PIXEL13_31 + PIXEL22_0 + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL03_12 + PIXEL13_14 + PIXEL22_70 + PIXEL23_83 + PIXEL32_21 + PIXEL33_50 + } + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + break; + } + case 207: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL02_32 + PIXEL03_82 + PIXEL10_0 + PIXEL11_0 + } + else + { + PIXEL00_50 + PIXEL01_83 + PIXEL02_13 + PIXEL03_11 + PIXEL10_21 + PIXEL11_70 + } + PIXEL12_32 + PIXEL13_82 + PIXEL20_10 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + break; + } + case 238: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_10 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL21_0 + PIXEL30_0 + PIXEL31_0 + PIXEL32_31 + PIXEL33_81 + } + else + { + PIXEL20_21 + PIXEL21_70 + PIXEL30_50 + PIXEL31_83 + PIXEL32_14 + PIXEL33_12 + } + PIXEL22_31 + PIXEL23_81 + break; + } + case 190: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL12_0 + PIXEL13_0 + PIXEL23_32 + PIXEL33_82 + } + else + { + PIXEL02_21 + PIXEL03_50 + PIXEL12_70 + PIXEL13_83 + PIXEL23_13 + PIXEL33_11 + } + PIXEL10_10 + PIXEL11_30 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + break; + } + case 187: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + PIXEL11_0 + PIXEL20_31 + PIXEL30_81 + } + else + { + PIXEL00_50 + PIXEL01_21 + PIXEL10_83 + PIXEL11_70 + PIXEL20_14 + PIXEL30_12 + } + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + break; + } + case 243: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_10 + PIXEL20_82 + PIXEL21_32 + if (Diff(w[6], w[8])) + { + PIXEL22_0 + PIXEL23_0 + PIXEL30_82 + PIXEL31_32 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL22_70 + PIXEL23_21 + PIXEL30_11 + PIXEL31_13 + PIXEL32_83 + PIXEL33_50 + } + break; + } + case 119: + { + if (Diff(w[2], w[6])) + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_0 + PIXEL03_0 + PIXEL12_0 + PIXEL13_0 + } + else + { + PIXEL00_12 + PIXEL01_14 + PIXEL02_83 + PIXEL03_50 + PIXEL12_70 + PIXEL13_21 + } + PIXEL10_81 + PIXEL11_31 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_10 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + break; + } + case 237: + case 233: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL20_0 + PIXEL21_0 + PIXEL22_31 + PIXEL23_81 + if (Diff(w[8], w[4])) + { + PIXEL30_0 + } + else + { + PIXEL30_20 + } + PIXEL31_0 + PIXEL32_31 + PIXEL33_81 + break; + } + case 175: + case 47: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + } + else + { + PIXEL00_20 + } + PIXEL01_0 + PIXEL02_32 + PIXEL03_82 + PIXEL10_0 + PIXEL11_0 + PIXEL12_32 + PIXEL13_82 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + break; + } + case 183: + case 151: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_0 + if (Diff(w[2], w[6])) + { + PIXEL03_0 + } + else + { + PIXEL03_20 + } + PIXEL10_81 + PIXEL11_31 + PIXEL12_0 + PIXEL13_0 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + break; + } + case 245: + case 244: + { + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_82 + PIXEL21_32 + PIXEL22_0 + PIXEL23_0 + PIXEL30_82 + PIXEL31_32 + PIXEL32_0 + if (Diff(w[6], w[8])) + { + PIXEL33_0 + } + else + { + PIXEL33_20 + } + break; + } + case 250: + { + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + break; + } + case 123: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 95: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL11_0 + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 222: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 252: + { + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_0 + PIXEL23_0 + PIXEL32_0 + if (Diff(w[6], w[8])) + { + PIXEL33_0 + } + else + { + PIXEL33_20 + } + break; + } + case 249: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_0 + PIXEL21_0 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + if (Diff(w[8], w[4])) + { + PIXEL30_0 + } + else + { + PIXEL30_20 + } + PIXEL31_0 + break; + } + case 235: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + PIXEL20_0 + PIXEL21_0 + PIXEL22_31 + PIXEL23_81 + if (Diff(w[8], w[4])) + { + PIXEL30_0 + } + else + { + PIXEL30_20 + } + PIXEL31_0 + PIXEL32_31 + PIXEL33_81 + break; + } + case 111: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + } + else + { + PIXEL00_20 + } + PIXEL01_0 + PIXEL02_32 + PIXEL03_82 + PIXEL10_0 + PIXEL11_0 + PIXEL12_32 + PIXEL13_82 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + break; + } + case 63: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + } + else + { + PIXEL00_20 + } + PIXEL01_0 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_0 + PIXEL11_0 + PIXEL12_0 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + break; + } + case 159: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_0 + if (Diff(w[2], w[6])) + { + PIXEL03_0 + } + else + { + PIXEL03_20 + } + PIXEL11_0 + PIXEL12_0 + PIXEL13_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + break; + } + case 215: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_0 + if (Diff(w[2], w[6])) + { + PIXEL03_0 + } + else + { + PIXEL03_20 + } + PIXEL10_81 + PIXEL11_31 + PIXEL12_0 + PIXEL13_0 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 246: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_82 + PIXEL21_32 + PIXEL22_0 + PIXEL23_0 + PIXEL30_82 + PIXEL31_32 + PIXEL32_0 + if (Diff(w[6], w[8])) + { + PIXEL33_0 + } + else + { + PIXEL33_20 + } + break; + } + case 254: + { + PIXEL00_80 + PIXEL01_10 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_0 + PIXEL23_0 + PIXEL32_0 + if (Diff(w[6], w[8])) + { + PIXEL33_0 + } + else + { + PIXEL33_20 + } + break; + } + case 253: + { + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_0 + PIXEL21_0 + PIXEL22_0 + PIXEL23_0 + if (Diff(w[8], w[4])) + { + PIXEL30_0 + } + else + { + PIXEL30_20 + } + PIXEL31_0 + PIXEL32_0 + if (Diff(w[6], w[8])) + { + PIXEL33_0 + } + else + { + PIXEL33_20 + } + break; + } + case 251: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + PIXEL20_0 + PIXEL21_0 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + if (Diff(w[8], w[4])) + { + PIXEL30_0 + } + else + { + PIXEL30_20 + } + PIXEL31_0 + break; + } + case 239: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + } + else + { + PIXEL00_20 + } + PIXEL01_0 + PIXEL02_32 + PIXEL03_82 + PIXEL10_0 + PIXEL11_0 + PIXEL12_32 + PIXEL13_82 + PIXEL20_0 + PIXEL21_0 + PIXEL22_31 + PIXEL23_81 + if (Diff(w[8], w[4])) + { + PIXEL30_0 + } + else + { + PIXEL30_20 + } + PIXEL31_0 + PIXEL32_31 + PIXEL33_81 + break; + } + case 127: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + } + else + { + PIXEL00_20 + } + PIXEL01_0 + if (Diff(w[2], w[6])) + { + PIXEL02_0 + PIXEL03_0 + PIXEL13_0 + } + else + { + PIXEL02_50 + PIXEL03_50 + PIXEL13_50 + } + PIXEL10_0 + PIXEL11_0 + PIXEL12_0 + if (Diff(w[8], w[4])) + { + PIXEL20_0 + PIXEL30_0 + PIXEL31_0 + } + else + { + PIXEL20_50 + PIXEL30_50 + PIXEL31_50 + } + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + break; + } + case 191: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + } + else + { + PIXEL00_20 + } + PIXEL01_0 + PIXEL02_0 + if (Diff(w[2], w[6])) + { + PIXEL03_0 + } + else + { + PIXEL03_20 + } + PIXEL10_0 + PIXEL11_0 + PIXEL12_0 + PIXEL13_0 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + break; + } + case 223: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + PIXEL01_0 + PIXEL10_0 + } + else + { + PIXEL00_50 + PIXEL01_50 + PIXEL10_50 + } + PIXEL02_0 + if (Diff(w[2], w[6])) + { + PIXEL03_0 + } + else + { + PIXEL03_20 + } + PIXEL11_0 + PIXEL12_0 + PIXEL13_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + if (Diff(w[6], w[8])) + { + PIXEL23_0 + PIXEL32_0 + PIXEL33_0 + } + else + { + PIXEL23_50 + PIXEL32_50 + PIXEL33_50 + } + PIXEL30_80 + PIXEL31_10 + break; + } + case 247: + { + PIXEL00_81 + PIXEL01_31 + PIXEL02_0 + if (Diff(w[2], w[6])) + { + PIXEL03_0 + } + else + { + PIXEL03_20 + } + PIXEL10_81 + PIXEL11_31 + PIXEL12_0 + PIXEL13_0 + PIXEL20_82 + PIXEL21_32 + PIXEL22_0 + PIXEL23_0 + PIXEL30_82 + PIXEL31_32 + PIXEL32_0 + if (Diff(w[6], w[8])) + { + PIXEL33_0 + } + else + { + PIXEL33_20 + } + break; + } + case 255: + { + if (Diff(w[4], w[2])) + { + PIXEL00_0 + } + else + { + PIXEL00_20 + } + PIXEL01_0 + PIXEL02_0 + if (Diff(w[2], w[6])) + { + PIXEL03_0 + } + else + { + PIXEL03_20 + } + PIXEL10_0 + PIXEL11_0 + PIXEL12_0 + PIXEL13_0 + PIXEL20_0 + PIXEL21_0 + PIXEL22_0 + PIXEL23_0 + if (Diff(w[8], w[4])) + { + PIXEL30_0 + } + else + { + PIXEL30_20 + } + PIXEL31_0 + PIXEL32_0 + if (Diff(w[6], w[8])) + { + PIXEL33_0 + } + else + { + PIXEL33_20 + } + break; + } + } diff --git a/GLideNHQ/TextureFilters_lq2x.h b/GLideNHQ/TextureFilters_lq2x.h new file mode 100644 index 00000000..b5318ab8 --- /dev/null +++ b/GLideNHQ/TextureFilters_lq2x.h @@ -0,0 +1,1307 @@ +/* +Copyright (C) 2003 Rice1964 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +/* Copyright (C) 2007 Hiroshi Morii + * Modified for the Texture Filtering library + */ + +case 0 : +case 2 : +case 4 : +case 6 : +case 8 : +case 12 : +case 16 : +case 20 : +case 24 : +case 28 : +case 32 : +case 34 : +case 36 : +case 38 : +case 40 : +case 44 : +case 48 : +case 52 : +case 56 : +case 60 : +case 64 : +case 66 : +case 68 : +case 70 : +case 96 : +case 98 : +case 100 : +case 102 : +case 128 : +case 130 : +case 132 : +case 134 : +case 136 : +case 140 : +case 144 : +case 148 : +case 152 : +case 156 : +case 160 : +case 162 : +case 164 : +case 166 : +case 168 : +case 172 : +case 176 : +case 180 : +case 184 : +case 188 : +case 192 : +case 194 : +case 196 : +case 198 : +case 224 : +case 226 : +case 228 : +case 230 : +{ + P0 = IC(0); + P1 = IC(0); + P2 = IC(0); + P3 = IC(0); +} break; +case 1 : +case 5 : +case 9 : +case 13 : +case 17 : +case 21 : +case 25 : +case 29 : +case 33 : +case 37 : +case 41 : +case 45 : +case 49 : +case 53 : +case 57 : +case 61 : +case 65 : +case 69 : +case 97 : +case 101 : +case 129 : +case 133 : +case 137 : +case 141 : +case 145 : +case 149 : +case 153 : +case 157 : +case 161 : +case 165 : +case 169 : +case 173 : +case 177 : +case 181 : +case 185 : +case 189 : +case 193 : +case 197 : +case 225 : +case 229 : +{ + P0 = IC(1); + P1 = IC(1); + P2 = IC(1); + P3 = IC(1); +} break; +case 3 : +case 35 : +case 67 : +case 99 : +case 131 : +case 163 : +case 195 : +case 227 : +{ + P0 = IC(2); + P1 = IC(2); + P2 = IC(2); + P3 = IC(2); +} break; +case 7 : +case 39 : +case 71 : +case 103 : +case 135 : +case 167 : +case 199 : +case 231 : +{ + P0 = IC(3); + P1 = IC(3); + P2 = IC(3); + P3 = IC(3); +} break; +case 10 : +case 138 : +{ + P1 = IC(0); + P2 = IC(0); + P3 = IC(0); + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I211(0, 1, 3); + } +} break; +case 11 : +case 27 : +case 75 : +case 139 : +case 155 : +case 203 : +{ + P1 = IC(2); + P2 = IC(2); + P3 = IC(2); + if (HQ2X_MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 14 : +case 142 : +{ + P2 = IC(0); + P3 = IC(0); + if (HQ2X_MUL) { + P0 = IC(0); + P1 = IC(0); + } else { + P0 = I332(1, 3, 0); + P1 = I31(0, 1); + } +} break; +case 15 : +case 143 : +case 207 : +{ + P2 = IC(4); + P3 = IC(4); + if (HQ2X_MUL) { + P0 = IC(4); + P1 = IC(4); + } else { + P0 = I332(1, 3, 4); + P1 = I31(4, 1); + } +} break; +case 18 : +case 22 : +case 30 : +case 50 : +case 54 : +case 62 : +case 86 : +case 118 : +{ + P0 = IC(0); + P2 = IC(0); + P3 = IC(0); + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 19 : +case 51 : +{ + P2 = IC(2); + P3 = IC(2); + if (HQ2X_MUR) { + P0 = IC(2); + P1 = IC(2); + } else { + P0 = I31(2, 1); + P1 = I332(1, 5, 2); + } +} break; +case 23 : +case 55 : +case 119 : +{ + P2 = IC(3); + P3 = IC(3); + if (HQ2X_MUR) { + P0 = IC(3); + P1 = IC(3); + } else { + P0 = I31(3, 1); + P1 = I332(1, 5, 3); + } +} break; +case 26 : +{ + P2 = IC(0); + P3 = IC(0); + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I211(0, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 31 : +case 95 : +{ + P2 = IC(4); + P3 = IC(4); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 42 : +case 170 : +{ + P1 = IC(0); + P3 = IC(0); + if (HQ2X_MUL) { + P0 = IC(0); + P2 = IC(0); + } else { + P0 = I332(1, 3, 0); + P2 = I31(0, 3); + } +} break; +case 43 : +case 171 : +case 187 : +{ + P1 = IC(2); + P3 = IC(2); + if (HQ2X_MUL) { + P0 = IC(2); + P2 = IC(2); + } else { + P0 = I332(1, 3, 2); + P2 = I31(2, 3); + } +} break; +case 46 : +case 174 : +{ + P1 = IC(0); + P2 = IC(0); + P3 = IC(0); + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } +} break; +case 47 : +case 175 : +{ + P1 = IC(4); + P2 = IC(4); + P3 = IC(4); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 58 : +case 154 : +case 186 : +{ + P2 = IC(0); + P3 = IC(0); + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 59 : +{ + P2 = IC(2); + P3 = IC(2); + if (HQ2X_MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(2); + } else { + P1 = I611(2, 1, 5); + } +} break; +case 63 : +{ + P2 = IC(4); + P3 = IC(4); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 72 : +case 76 : +case 104 : +case 106 : +case 108 : +case 110 : +case 120 : +case 124 : +{ + P0 = IC(0); + P1 = IC(0); + P3 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } +} break; +case 73 : +case 77 : +case 105 : +case 109 : +case 125 : +{ + P1 = IC(1); + P3 = IC(1); + if (HQ2X_MDL) { + P0 = IC(1); + P2 = IC(1); + } else { + P0 = I31(1, 3); + P2 = I332(3, 7, 1); + } +} break; +case 74 : +{ + P1 = IC(0); + P3 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I211(0, 1, 3); + } +} break; +case 78 : +case 202 : +case 206 : +{ + P1 = IC(0); + P3 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } +} break; +case 79 : +{ + P1 = IC(4); + P3 = IC(4); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I611(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 80 : +case 208 : +case 210 : +case 216 : +{ + P0 = IC(0); + P1 = IC(0); + P2 = IC(0); + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } +} break; +case 81 : +case 209 : +case 217 : +{ + P0 = IC(1); + P1 = IC(1); + P2 = IC(1); + if (HQ2X_MDR) { + P3 = IC(1); + } else { + P3 = I211(1, 5, 7); + } +} break; +case 82 : +case 214 : +case 222 : +{ + P0 = IC(0); + P2 = IC(0); + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 83 : +case 115 : +{ + P0 = IC(2); + P2 = IC(2); + if (HQ2X_MDR) { + P3 = IC(2); + } else { + P3 = I611(2, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(2); + } else { + P1 = I611(2, 1, 5); + } +} break; +case 84 : +case 212 : +{ + P0 = IC(0); + P2 = IC(0); + if (HQ2X_MDR) { + P1 = IC(0); + P3 = IC(0); + } else { + P1 = I31(0, 5); + P3 = I332(5, 7, 0); + } +} break; +case 85 : +case 213 : +case 221 : +{ + P0 = IC(1); + P2 = IC(1); + if (HQ2X_MDR) { + P1 = IC(1); + P3 = IC(1); + } else { + P1 = I31(1, 5); + P3 = I332(5, 7, 1); + } +} break; +case 87 : +{ + P0 = IC(3); + P2 = IC(3); + if (HQ2X_MDR) { + P3 = IC(3); + } else { + P3 = I611(3, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(3); + } else { + P1 = I211(3, 1, 5); + } +} break; +case 88 : +case 248 : +case 250 : +{ + P0 = IC(0); + P1 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } +} break; +case 89 : +case 93 : +{ + P0 = IC(1); + P1 = IC(1); + if (HQ2X_MDL) { + P2 = IC(1); + } else { + P2 = I611(1, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(1); + } else { + P3 = I611(1, 5, 7); + } +} break; +case 90 : +{ + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 91 : +{ + if (HQ2X_MDL) { + P2 = IC(2); + } else { + P2 = I611(2, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(2); + } else { + P3 = I611(2, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(2); + } else { + P1 = I611(2, 1, 5); + } +} break; +case 92 : +{ + P0 = IC(0); + P1 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } +} break; +case 94 : +{ + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 107 : +case 123 : +{ + P1 = IC(2); + P3 = IC(2); + if (HQ2X_MDL) { + P2 = IC(2); + } else { + P2 = I211(2, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 111 : +{ + P1 = IC(4); + P3 = IC(4); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 112 : +case 240 : +{ + P0 = IC(0); + P1 = IC(0); + if (HQ2X_MDR) { + P2 = IC(0); + P3 = IC(0); + } else { + P2 = I31(0, 7); + P3 = I332(5, 7, 0); + } +} break; +case 113 : +case 241 : +{ + P0 = IC(1); + P1 = IC(1); + if (HQ2X_MDR) { + P2 = IC(1); + P3 = IC(1); + } else { + P2 = I31(1, 7); + P3 = I332(5, 7, 1); + } +} break; +case 114 : +{ + P0 = IC(0); + P2 = IC(0); + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 116 : +{ + P0 = IC(0); + P1 = IC(0); + P2 = IC(0); + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } +} break; +case 117 : +{ + P0 = IC(1); + P1 = IC(1); + P2 = IC(1); + if (HQ2X_MDR) { + P3 = IC(1); + } else { + P3 = I611(1, 5, 7); + } +} break; +case 121 : +{ + P0 = IC(1); + P1 = IC(1); + if (HQ2X_MDL) { + P2 = IC(1); + } else { + P2 = I211(1, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(1); + } else { + P3 = I611(1, 5, 7); + } +} break; +case 122 : +{ + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 126 : +{ + P0 = IC(0); + P3 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 127 : +{ + P3 = IC(4); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 146 : +case 150 : +case 178 : +case 182 : +case 190 : +{ + P0 = IC(0); + P2 = IC(0); + if (HQ2X_MUR) { + P1 = IC(0); + P3 = IC(0); + } else { + P1 = I332(1, 5, 0); + P3 = I31(0, 5); + } +} break; +case 147 : +case 179 : +{ + P0 = IC(2); + P2 = IC(2); + P3 = IC(2); + if (HQ2X_MUR) { + P1 = IC(2); + } else { + P1 = I611(2, 1, 5); + } +} break; +case 151 : +case 183 : +{ + P0 = IC(3); + P2 = IC(3); + P3 = IC(3); + if (HQ2X_MUR) { + P1 = IC(3); + } else { + P1 = I1411(3, 1, 5); + } +} break; +case 158 : +{ + P2 = IC(0); + P3 = IC(0); + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 159 : +{ + P2 = IC(4); + P3 = IC(4); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 191 : +{ + P2 = IC(4); + P3 = IC(4); + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 200 : +case 204 : +case 232 : +case 236 : +case 238 : +{ + P0 = IC(0); + P1 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + P3 = IC(0); + } else { + P2 = I332(3, 7, 0); + P3 = I31(0, 7); + } +} break; +case 201 : +case 205 : +{ + P0 = IC(1); + P1 = IC(1); + P3 = IC(1); + if (HQ2X_MDL) { + P2 = IC(1); + } else { + P2 = I611(1, 3, 7); + } +} break; +case 211 : +{ + P0 = IC(2); + P1 = IC(2); + P2 = IC(2); + if (HQ2X_MDR) { + P3 = IC(2); + } else { + P3 = I211(2, 5, 7); + } +} break; +case 215 : +{ + P0 = IC(3); + P2 = IC(3); + if (HQ2X_MDR) { + P3 = IC(3); + } else { + P3 = I211(3, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(3); + } else { + P1 = I1411(3, 1, 5); + } +} break; +case 218 : +{ + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 219 : +{ + P1 = IC(2); + P2 = IC(2); + if (HQ2X_MDR) { + P3 = IC(2); + } else { + P3 = I211(2, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 220 : +{ + P0 = IC(0); + P1 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } +} break; +case 223 : +{ + P2 = IC(4); + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 233 : +case 237 : +{ + P0 = IC(1); + P1 = IC(1); + P3 = IC(1); + if (HQ2X_MDL) { + P2 = IC(1); + } else { + P2 = I1411(1, 3, 7); + } +} break; +case 234 : +{ + P1 = IC(0); + P3 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } +} break; +case 235 : +{ + P1 = IC(2); + P3 = IC(2); + if (HQ2X_MDL) { + P2 = IC(2); + } else { + P2 = I1411(2, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 239 : +{ + P1 = IC(4); + P3 = IC(4); + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 242 : +{ + P0 = IC(0); + P2 = IC(0); + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 243 : +{ + P0 = IC(2); + P1 = IC(2); + if (HQ2X_MDR) { + P2 = IC(2); + P3 = IC(2); + } else { + P2 = I31(2, 7); + P3 = I332(5, 7, 2); + } +} break; +case 244 : +{ + P0 = IC(0); + P1 = IC(0); + P2 = IC(0); + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I1411(0, 5, 7); + } +} break; +case 245 : +{ + P0 = IC(1); + P1 = IC(1); + P2 = IC(1); + if (HQ2X_MDR) { + P3 = IC(1); + } else { + P3 = I1411(1, 5, 7); + } +} break; +case 246 : +{ + P0 = IC(0); + P2 = IC(0); + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I1411(0, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 247 : +{ + P0 = IC(3); + P2 = IC(3); + if (HQ2X_MDR) { + P3 = IC(3); + } else { + P3 = I1411(3, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(3); + } else { + P1 = I1411(3, 1, 5); + } +} break; +case 249 : +{ + P0 = IC(1); + P1 = IC(1); + if (HQ2X_MDL) { + P2 = IC(1); + } else { + P2 = I1411(1, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(1); + } else { + P3 = I211(1, 5, 7); + } +} break; +case 251 : +{ + P1 = IC(2); + if (HQ2X_MDL) { + P2 = IC(2); + } else { + P2 = I1411(2, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(2); + } else { + P3 = I211(2, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 252 : +{ + P0 = IC(0); + P1 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I1411(0, 5, 7); + } +} break; +case 253 : +{ + P0 = IC(1); + P1 = IC(1); + if (HQ2X_MDL) { + P2 = IC(1); + } else { + P2 = I1411(1, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(1); + } else { + P3 = I1411(1, 5, 7); + } +} break; +case 254 : +{ + P0 = IC(0); + if (HQ2X_MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(0); + } else { + P3 = I1411(0, 5, 7); + } + if (HQ2X_MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 255 : +{ + if (HQ2X_MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (HQ2X_MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (HQ2X_MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (HQ2X_MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; diff --git a/GLideNHQ/TxCache.cpp b/GLideNHQ/TxCache.cpp new file mode 100644 index 00000000..a89e16f2 --- /dev/null +++ b/GLideNHQ/TxCache.cpp @@ -0,0 +1,449 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __MSC__ +#pragma warning(disable: 4786) +#endif + +#include "TxCache.h" +#include "TxDbg.h" +#include +#include + +TxCache::~TxCache() +{ + /* free memory, clean up, etc */ + clear(); + + delete _txUtil; +} + +TxCache::TxCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident, + dispInfoFuncExt callback) +{ + _txUtil = new TxUtil(); + + _options = options; + _cacheSize = cachesize; + _callback = callback; + _totalSize = 0; + + /* save path name */ + if (path) + _path.assign(path); + + /* save ROM name */ + if (ident) + _ident.assign(ident); + + /* zlib memory buffers to (de)compress hires textures */ + if (_options & (GZ_TEXCACHE|GZ_HIRESTEXCACHE)) { + _gzdest0 = TxMemBuf::getInstance()->get(0); + _gzdest1 = TxMemBuf::getInstance()->get(1); + _gzdestLen = (TxMemBuf::getInstance()->size_of(0) < TxMemBuf::getInstance()->size_of(1)) ? + TxMemBuf::getInstance()->size_of(0) : TxMemBuf::getInstance()->size_of(1); + + if (!_gzdest0 || !_gzdest1 || !_gzdestLen) { + _options &= ~(GZ_TEXCACHE|GZ_HIRESTEXCACHE); + _gzdest0 = NULL; + _gzdest1 = NULL; + _gzdestLen = 0; + } + } +} + +boolean +TxCache::add(uint64 checksum, GHQTexInfo *info, int dataSize) +{ + /* NOTE: dataSize must be provided if info->data is zlib compressed. */ + + if (!checksum || !info->data) return 0; + + uint8 *dest = info->data; + uint16 format = info->format; + + if (!dataSize) { + dataSize = _txUtil->sizeofTx(info->width, info->height, info->format); + + if (!dataSize) return 0; + + if (_options & (GZ_TEXCACHE|GZ_HIRESTEXCACHE)) { + /* zlib compress it. compression level:1 (best speed) */ + uint32 destLen = _gzdestLen; + dest = (dest == _gzdest0) ? _gzdest1 : _gzdest0; + if (compress2(dest, &destLen, info->data, dataSize, 1) != Z_OK) { + dest = info->data; + DBG_INFO(80, L"Error: zlib compression failed!\n"); + } else { + DBG_INFO(80, L"zlib compressed: %.02fkb->%.02fkb\n", (float)dataSize/1000, (float)destLen/1000); + dataSize = destLen; + format |= GR_TEXFMT_GZ; + } + } + } + + /* if cache size exceeds limit, remove old cache */ + if (_cacheSize > 0) { + _totalSize += dataSize; + if ((_totalSize > _cacheSize) && !_cachelist.empty()) { + /* _cachelist is arranged so that frequently used textures are in the back */ + std::list::iterator itList = _cachelist.begin(); + while (itList != _cachelist.end()) { + /* find it in _cache */ + std::map::iterator itMap = _cache.find(*itList); + if (itMap != _cache.end()) { + /* yep we have it. remove it. */ + _totalSize -= (*itMap).second->size; + free((*itMap).second->info.data); + delete (*itMap).second; + _cache.erase(itMap); + } + itList++; + + /* check if memory cache has enough space */ + if (_totalSize <= _cacheSize) + break; + } + /* remove from _cachelist */ + _cachelist.erase(_cachelist.begin(), itList); + + DBG_INFO(80, L"+++++++++\n"); + } + _totalSize -= dataSize; + } + + /* cache it */ + uint8 *tmpdata = (uint8*)malloc(dataSize); + if (tmpdata) { + TXCACHE *txCache = new TXCACHE; + if (txCache) { + /* we can directly write as we filter, but for now we get away + * with doing memcpy after all the filtering is done. + */ + memcpy(tmpdata, dest, dataSize); + + /* copy it */ + memcpy(&txCache->info, info, sizeof(GHQTexInfo)); + txCache->info.data = tmpdata; + txCache->info.format = format; + txCache->size = dataSize; + + /* add to cache */ + if (_cacheSize > 0) { + _cachelist.push_back(checksum); + txCache->it = --(_cachelist.end()); + } + /* _cache[checksum] = txCache; */ + _cache.insert(std::map::value_type(checksum, txCache)); + +#ifdef DEBUG + DBG_INFO(80, L"[%5d] added!! crc:%08X %08X %d x %d gfmt:%x total:%.02fmb\n", + _cache.size(), (uint32)(checksum >> 32), (uint32)(checksum & 0xffffffff), + info->width, info->height, info->format, (float)_totalSize/1000000); + + DBG_INFO(80, L"smalllodlog2:%d largelodlog2:%d aspectratiolog2:%d\n", + txCache->info.smallLodLog2, txCache->info.largeLodLog2, txCache->info.aspectRatioLog2); + + if (info->tiles) { + DBG_INFO(80, L"tiles:%d un-tiled size:%d x %d\n", info->tiles, info->untiled_width, info->untiled_height); + } + + if (_cacheSize > 0) { + DBG_INFO(80, L"cache max config:%.02fmb\n", (float)_cacheSize/1000000); + + if (_cache.size() != _cachelist.size()) { + DBG_INFO(80, L"Error: cache/cachelist mismatch! (%d/%d)\n", _cache.size(), _cachelist.size()); + } + } +#endif + + /* total cache size */ + _totalSize += dataSize; + + return 1; + } + free(tmpdata); + } + + return 0; +} + +boolean +TxCache::get(uint64 checksum, GHQTexInfo *info) +{ + if (!checksum || _cache.empty()) return 0; + + /* find a match in cache */ + std::map::iterator itMap = _cache.find(checksum); + if (itMap != _cache.end()) { + /* yep, we've got it. */ + memcpy(info, &(((*itMap).second)->info), sizeof(GHQTexInfo)); + + /* push it to the back of the list */ + if (_cacheSize > 0) { + _cachelist.erase(((*itMap).second)->it); + _cachelist.push_back(checksum); + ((*itMap).second)->it = --(_cachelist.end()); + } + + /* zlib decompress it */ + if (info->format & GR_TEXFMT_GZ) { + uint32 destLen = _gzdestLen; + uint8 *dest = (_gzdest0 == info->data) ? _gzdest1 : _gzdest0; + if (uncompress(dest, &destLen, info->data, ((*itMap).second)->size) != Z_OK) { + DBG_INFO(80, L"Error: zlib decompression failed!\n"); + return 0; + } + info->data = dest; + info->format &= ~GR_TEXFMT_GZ; + DBG_INFO(80, L"zlib decompressed: %.02fkb->%.02fkb\n", (float)(((*itMap).second)->size)/1000, (float)destLen/1000); + } + + return 1; + } + + return 0; +} + +boolean +TxCache::save(const wchar_t *path, const wchar_t *filename, int config) +{ + if (!_cache.empty()) { + /* dump cache to disk */ + char cbuf[MAX_PATH]; + + boost::filesystem::wpath cachepath(path); + boost::filesystem::create_directory(cachepath); + + /* Ugly hack to enable fopen/gzopen in Win9x */ +#ifdef WIN32 + wchar_t curpath[MAX_PATH]; + GETCWD(MAX_PATH, curpath); + CHDIR(cachepath.wstring().c_str()); +#else + char curpath[MAX_PATH]; + wcstombs(cbuf, cachepath.string().c_str(), MAX_PATH); + GETCWD(MAX_PATH, curpath); + CHDIR(cbuf); +#endif + + wcstombs(cbuf, filename, MAX_PATH); + + gzFile gzfp = gzopen(cbuf, "wb1"); + DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename); + if (gzfp) { + /* write header to determine config match */ + gzwrite(gzfp, &config, 4); + + std::map::iterator itMap = _cache.begin(); + while (itMap != _cache.end()) { + uint8 *dest = (*itMap).second->info.data; + uint32 destLen = (*itMap).second->size; + uint16 format = (*itMap).second->info.format; + + /* to keep things simple, we save the texture data in a zlib uncompressed state. */ + /* sigh... for those who cannot wait the extra few seconds. changed to keep + * texture data in a zlib compressed state. if the GZ_TEXCACHE or GZ_HIRESTEXCACHE + * option is toggled, the cache will need to be rebuilt. + */ + /*if (format & GR_TEXFMT_GZ) { + dest = _gzdest0; + destLen = _gzdestLen; + if (dest && destLen) { + if (uncompress(dest, &destLen, (*itMap).second->info.data, (*itMap).second->size) != Z_OK) { + dest = NULL; + destLen = 0; + } + format &= ~GR_TEXFMT_GZ; + } + }*/ + + if (dest && destLen) { + /* texture checksum */ + gzwrite(gzfp, &((*itMap).first), 8); + + /* other texture info */ + gzwrite(gzfp, &((*itMap).second->info.width), 4); + gzwrite(gzfp, &((*itMap).second->info.height), 4); + gzwrite(gzfp, &format, 2); + + gzwrite(gzfp, &((*itMap).second->info.smallLodLog2), 4); + gzwrite(gzfp, &((*itMap).second->info.largeLodLog2), 4); + gzwrite(gzfp, &((*itMap).second->info.aspectRatioLog2), 4); + + gzwrite(gzfp, &((*itMap).second->info.tiles), 4); + gzwrite(gzfp, &((*itMap).second->info.untiled_width), 4); + gzwrite(gzfp, &((*itMap).second->info.untiled_height), 4); + + gzwrite(gzfp, &((*itMap).second->info.is_hires_tex), 1); + + gzwrite(gzfp, &destLen, 4); + gzwrite(gzfp, dest, destLen); + } + + itMap++; + + /* not ready yet */ + /*if (_callback) + (*_callback)(L"Total textures saved to HDD: %d\n", std::distance(itMap, _cache.begin()));*/ + } + gzclose(gzfp); + } + + CHDIR(curpath); + } + + return _cache.empty(); +} + +boolean +TxCache::load(const wchar_t *path, const wchar_t *filename, int config) +{ + /* find it on disk */ + char cbuf[MAX_PATH]; + + boost::filesystem::wpath cachepath(path); + +#ifdef WIN32 + wchar_t curpath[MAX_PATH]; + GETCWD(MAX_PATH, curpath); + CHDIR(cachepath.wstring().c_str()); +#else + char curpath[MAX_PATH]; + wcstombs(cbuf, cachepath.string().c_str(), MAX_PATH); + GETCWD(MAX_PATH, curpath); + CHDIR(cbuf); +#endif + + wcstombs(cbuf, filename, MAX_PATH); + + gzFile gzfp = gzopen(cbuf, "rb"); + DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename); + if (gzfp) { + /* yep, we have it. load it into memory cache. */ + int dataSize; + uint64 checksum; + GHQTexInfo tmpInfo; + int tmpconfig; + /* read header to determine config match */ + gzread(gzfp, &tmpconfig, 4); + + if (tmpconfig == config) { + do { + memset(&tmpInfo, 0, sizeof(GHQTexInfo)); + + gzread(gzfp, &checksum, 8); + + gzread(gzfp, &tmpInfo.width, 4); + gzread(gzfp, &tmpInfo.height, 4); + gzread(gzfp, &tmpInfo.format, 2); + + gzread(gzfp, &tmpInfo.smallLodLog2, 4); + gzread(gzfp, &tmpInfo.largeLodLog2, 4); + gzread(gzfp, &tmpInfo.aspectRatioLog2, 4); + + gzread(gzfp, &tmpInfo.tiles, 4); + gzread(gzfp, &tmpInfo.untiled_width, 4); + gzread(gzfp, &tmpInfo.untiled_height, 4); + + gzread(gzfp, &tmpInfo.is_hires_tex, 1); + + gzread(gzfp, &dataSize, 4); + + tmpInfo.data = (uint8*)malloc(dataSize); + if (tmpInfo.data) { + gzread(gzfp, tmpInfo.data, dataSize); + + /* add to memory cache */ + add(checksum, &tmpInfo, (tmpInfo.format & GR_TEXFMT_GZ) ? dataSize : 0); + + free(tmpInfo.data); + } else { + gzseek(gzfp, dataSize, SEEK_CUR); + } + + /* skip in between to prevent the loop from being tied down to vsync */ + if (_callback && (!(_cache.size() % 100) || gzeof(gzfp))) + (*_callback)(L"[%d] total mem:%.02fmb - %ls\n", _cache.size(), (float)_totalSize/1000000, filename); + + } while (!gzeof(gzfp)); + gzclose(gzfp); + } + } + + CHDIR(curpath); + + return !_cache.empty(); +} + +boolean +TxCache::del(uint64 checksum) +{ + if (!checksum || _cache.empty()) return 0; + + std::map::iterator itMap = _cache.find(checksum); + if (itMap != _cache.end()) { + + /* for texture cache (not hi-res cache) */ + if (!_cachelist.empty()) _cachelist.erase(((*itMap).second)->it); + + /* remove from cache */ + free((*itMap).second->info.data); + _totalSize -= (*itMap).second->size; + delete (*itMap).second; + _cache.erase(itMap); + + DBG_INFO(80, L"removed from cache: checksum = %08X %08X\n", (uint32)(checksum & 0xffffffff), (uint32)(checksum >> 32)); + + return 1; + } + + return 0; +} + +boolean +TxCache::is_cached(uint64 checksum) +{ + std::map::iterator itMap = _cache.find(checksum); + if (itMap != _cache.end()) return 1; + + return 0; +} + +void +TxCache::clear() +{ + if (!_cache.empty()) { + std::map::iterator itMap = _cache.begin(); + while (itMap != _cache.end()) { + free((*itMap).second->info.data); + delete (*itMap).second; + itMap++; + } + _cache.clear(); + } + + if (!_cachelist.empty()) _cachelist.clear(); + + _totalSize = 0; +} diff --git a/GLideNHQ/TxCache.h b/GLideNHQ/TxCache.h new file mode 100644 index 00000000..0b31b544 --- /dev/null +++ b/GLideNHQ/TxCache.h @@ -0,0 +1,69 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TXCACHE_H__ +#define __TXCACHE_H__ + +#include "TxInternal.h" +#include "TxUtil.h" +#include +#include +#include + +class TxCache +{ +private: + std::list _cachelist; + uint8 *_gzdest0; + uint8 *_gzdest1; + uint32 _gzdestLen; +protected: + int _options; + std::wstring _ident; + std::wstring _path; + dispInfoFuncExt _callback; + TxUtil *_txUtil; + struct TXCACHE { + int size; + GHQTexInfo info; + std::list::iterator it; + }; + int _totalSize; + int _cacheSize; + std::map _cache; + boolean save(const wchar_t *path, const wchar_t *filename, const int config); + boolean load(const wchar_t *path, const wchar_t *filename, const int config); + boolean del(uint64 checksum); /* checksum hi:palette low:texture */ + boolean is_cached(uint64 checksum); /* checksum hi:palette low:texture */ + void clear(); +public: + ~TxCache(); + TxCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident, + dispInfoFuncExt callback); + boolean add(uint64 checksum, /* checksum hi:palette low:texture */ + GHQTexInfo *info, int dataSize = 0); + boolean get(uint64 checksum, /* checksum hi:palette low:texture */ + GHQTexInfo *info); +}; + +#endif /* __TXCACHE_H__ */ diff --git a/GLideNHQ/TxDbg.cpp b/GLideNHQ/TxDbg.cpp new file mode 100644 index 00000000..a54cba4c --- /dev/null +++ b/GLideNHQ/TxDbg.cpp @@ -0,0 +1,75 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define DBG_LEVEL 80 + +#include "TxDbg.h" +#include +#include +#include + +TxDbg::TxDbg() +{ + _level = DBG_LEVEL; + + if (!_dbgfile) +#ifdef GHQCHK + _dbgfile = fopen("ghqchk.txt", "w"); +#else + _dbgfile = fopen("glidehq.dbg", "w"); +#endif +} + +TxDbg::~TxDbg() +{ + if (_dbgfile) { + fclose(_dbgfile); + _dbgfile = 0; + } + + _level = DBG_LEVEL; +} + +void +TxDbg::output(const int level, const wchar_t *format, ...) +{ + va_list args; + //wchar_t newformat[4095]; + std::wstring newformat; + + if (level > _level) + return; + + va_start(args, format); + //swprintf(newformat, 4095, L"%d:\t", level); + //wcscat(newformat, format); + //vfwprintf(_dbgfile, newformat, args); + newformat = boost::str(boost::wformat(L"%d:\t%ls") % level % format); + vfwprintf(_dbgfile, newformat.c_str(), args); + fflush(_dbgfile); +#ifdef GHQCHK + //vwprintf(newformat, args); + vwprintf(newformat.c_str(), args); +#endif + va_end(args); +} diff --git a/GLideNHQ/TxDbg.h b/GLideNHQ/TxDbg.h new file mode 100644 index 00000000..0a64d6ac --- /dev/null +++ b/GLideNHQ/TxDbg.h @@ -0,0 +1,61 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TXDBG_H__ +#define __TXDBG_H__ + +#include +#include "TxInternal.h" + +class TxDbg +{ +private: + FILE* _dbgfile; + int _level; + TxDbg(); +public: + static TxDbg* getInstance() { + static TxDbg txDbg; + return &txDbg; + } + ~TxDbg(); + void output(const int level, const wchar_t *format, ...); +}; + +#ifdef DEBUG +#define DBG_INFO TxDbg::getInstance()->output +#define INFO DBG_INFO +#else +#define DBG_INFO(A, ...) +#ifdef GHQCHK +#define INFO TxDbg::getInstance()->output +#else +#if 0 /* XXX enable this to log basic hires texture checks */ +#define INFO TxDbg::getInstance()->output +#else +#define INFO DBG_INFO +#endif +#endif +#endif + +#endif /* __TXDBG_H__ */ diff --git a/GLideNHQ/TxFilter.cpp b/GLideNHQ/TxFilter.cpp new file mode 100644 index 00000000..58b44648 --- /dev/null +++ b/GLideNHQ/TxFilter.cpp @@ -0,0 +1,683 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __MSC__ +#pragma warning(disable: 4786) +#endif + +#include "TxFilter.h" +#include "TextureFilters.h" +#include "TxDbg.h" +#include "bldno.h" +#include +#include +#include + +void TxFilter::clear() +{ + /* clear hires texture cache */ + delete _txHiResCache; + + /* clear texture cache */ + delete _txTexCache; + + /* free memory */ + TxMemBuf::getInstance()->shutdown(); + + /* clear other stuff */ + delete _txImage; + delete _txQuantize; + delete _txUtil; +} + +TxFilter::~TxFilter() +{ + clear(); +} + +TxFilter::TxFilter(int maxwidth, int maxheight, int maxbpp, int options, + int cachesize, wchar_t *path, wchar_t *ident, + dispInfoFuncExt callback) +{ + /* HACKALERT: the emulator misbehaves and sometimes forgets to shutdown */ + if ((ident && wcscmp(ident, L"DEFAULT") != 0 && _ident.compare(ident) == 0) && + _maxwidth == maxwidth && + _maxheight == maxheight && + _maxbpp == maxbpp && + _options == options && + _cacheSize == cachesize) return; + clear(); /* gcc does not allow the destructor to be called */ + + /* shamelessness :P this first call to the debug output message creates + * a file in the executable directory. */ + INFO(0, L"------------------------------------------------------------------\n"); +#ifdef GHQCHK + INFO(0, L" GlideHQ Hires Texture Checker 1.02.00.%d\n", BUILD_NUMBER); +#else + INFO(0, L" GlideHQ version 1.02.00.%d\n", BUILD_NUMBER); +#endif + INFO(0, L" Copyright (C) 2010 Hiroshi Morii All Rights Reserved\n"); + INFO(0, L" email : koolsmoky(at)users.sourceforge.net\n"); + INFO(0, L" website : http://www.3dfxzone.it/koolsmoky\n"); + INFO(0, L"\n"); + INFO(0, L" Glide64 official website : http://glide64.emuxhaven.net\n"); + INFO(0, L"------------------------------------------------------------------\n"); + + _options = options; + + _txImage = new TxImage(); + _txQuantize = new TxQuantize(); + _txUtil = new TxUtil(); + + /* get number of CPU cores. */ + _numcore = _txUtil->getNumberofProcessors(); + + _initialized = 0; + + _tex1 = NULL; + _tex2 = NULL; + + /* XXX: anything larger than 1024 * 1024 is overkill */ + _maxwidth = maxwidth > 1024 ? 1024 : maxwidth; + _maxheight = maxheight > 1024 ? 1024 : maxheight; + _maxbpp = maxbpp; + + _cacheSize = cachesize; + + /* TODO: validate options and do overrides here*/ + + /* save path name */ + if (path) + _path.assign(path); + + /* save ROM name */ + if (ident && wcscmp(ident, L"DEFAULT") != 0) + _ident.assign(ident); + + /* check for dxtn extensions */ + if (!TxLoadLib::getInstance()->getdxtCompressTexFuncExt()) + _options &= ~S3TC_COMPRESSION; + + if (!TxLoadLib::getInstance()->getfxtCompressTexFuncExt()) + _options &= ~FXT1_COMPRESSION; + + switch (options & COMPRESSION_MASK) { + case FXT1_COMPRESSION: + case S3TC_COMPRESSION: + break; + case NCC_COMPRESSION: + default: + _options &= ~COMPRESSION_MASK; + } + + if (TxMemBuf::getInstance()->init(_maxwidth, _maxheight)) { + if (!_tex1) + _tex1 = TxMemBuf::getInstance()->get(0); + + if (!_tex2) + _tex2 = TxMemBuf::getInstance()->get(1); + } + +#if !_16BPP_HACK + /* initialize hq4x filter */ + hq4x_init(); +#endif + + /* initialize texture cache in bytes. 128Mb will do nicely in most cases */ + _txTexCache = new TxTexCache(_options, _cacheSize, _path.c_str(), _ident.c_str(), callback); + + /* hires texture */ +#if HIRES_TEXTURE + _txHiResCache = new TxHiResCache(_maxwidth, _maxheight, _maxbpp, _options, _path.c_str(), _ident.c_str(), callback); + + if (_txHiResCache->empty()) + _options &= ~HIRESTEXTURES_MASK; +#endif + + if (!(_options & COMPRESS_TEX)) + _options &= ~COMPRESSION_MASK; + + if (_tex1 && _tex2) + _initialized = 1; +} + +boolean +TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint64 g64crc, GHQTexInfo *info) +{ + uint8 *texture = src; + uint8 *tmptex = _tex1; + uint16 destformat = srcformat; + + /* We need to be initialized first! */ + if (!_initialized) return 0; + + /* find cached textures */ + if (_cacheSize) { + + /* calculate checksum of source texture */ + if (!g64crc) + g64crc = (uint64)(_txUtil->checksumTx(texture, srcwidth, srcheight, srcformat)); + + DBG_INFO(80, L"filter: crc:%08X %08X %d x %d gfmt:%x\n", + (uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff), srcwidth, srcheight, srcformat); + +#if 0 /* use hirestex to retrieve cached textures. */ + /* check if we have it in cache */ + if (!(g64crc & 0xffffffff00000000) && /* we reach here only when there is no hires texture for this crc */ + _txTexCache->get(g64crc, info)) { + DBG_INFO(80, L"cache hit: %d x %d gfmt:%x\n", info->width, info->height, info->format); + return 1; /* yep, we've got it */ + } +#endif + } + + /* Leave small textures alone because filtering makes little difference. + * Moreover, some filters require at least 4 * 4 to work. + * Bypass _options to do ARGB8888->16bpp if _maxbpp=16 or forced color reduction. + */ + if ((srcwidth >= 4 && srcheight >= 4) && + ((_options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESSION_MASK)) || + (srcformat == GR_TEXFMT_ARGB_8888 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)))) { + +#if !_16BPP_HACK + /* convert textures to a format that the compressor accepts (ARGB8888) */ + if (_options & COMPRESSION_MASK) { +#endif + if (srcformat != GR_TEXFMT_ARGB_8888) { + if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, srcformat, GR_TEXFMT_ARGB_8888)) { + DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", srcformat); + return 0; + } + texture = tmptex; + destformat = GR_TEXFMT_ARGB_8888; + } +#if !_16BPP_HACK + } +#endif + + switch (destformat) { + case GR_TEXFMT_ARGB_8888: + + /* + * prepare texture enhancements (x2, x4 scalers) + */ + int scale_shift = 0, num_filters = 0; + uint32 filter = 0; + + if ((_options & ENHANCEMENT_MASK) == HQ4X_ENHANCEMENT) { + if (srcwidth <= (_maxwidth >> 2) && srcheight <= (_maxheight >> 2)) { + filter |= HQ4X_ENHANCEMENT; + scale_shift = 2; + num_filters++; + } else if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) { + filter |= HQ2X_ENHANCEMENT; + scale_shift = 1; + num_filters++; + } + } else if (_options & ENHANCEMENT_MASK) { + if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) { + filter |= (_options & ENHANCEMENT_MASK); + scale_shift = 1; + num_filters++; + } + } + + /* + * prepare texture filters + */ + if (_options & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK)) { + filter |= (_options & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK)); + num_filters++; + } + + /* + * execute texture enhancements and filters + */ + while (num_filters > 0) { + + tmptex = (texture == _tex1) ? _tex2 : _tex1; + + uint8 *_texture = texture; + uint8 *_tmptex = tmptex; + + unsigned int numcore = _numcore; + unsigned int blkrow = 0; + while (numcore > 1 && blkrow == 0) { + blkrow = (srcheight >> 2) / numcore; + numcore--; + } + if (blkrow > 0 && numcore > 1) { + boost::thread *thrd[MAX_NUMCORE]; + unsigned int i; + int blkheight = blkrow << 2; + unsigned int srcStride = (srcwidth * blkheight) << 2; + unsigned int destStride = srcStride << scale_shift << scale_shift; + for (i = 0; i < numcore - 1; i++) { + thrd[i] = new boost::thread(boost::bind(filter_8888, + (uint32*)_texture, + srcwidth, + blkheight, + (uint32*)_tmptex, + filter)); + _texture += srcStride; + _tmptex += destStride; + } + thrd[i] = new boost::thread(boost::bind(filter_8888, + (uint32*)_texture, + srcwidth, + srcheight - blkheight * i, + (uint32*)_tmptex, + filter)); + for (i = 0; i < numcore; i++) { + thrd[i]->join(); + delete thrd[i]; + } + } else { + filter_8888((uint32*)_texture, srcwidth, srcheight, (uint32*)_tmptex, filter); + } + + if (filter & ENHANCEMENT_MASK) { + srcwidth <<= scale_shift; + srcheight <<= scale_shift; + filter &= ~ENHANCEMENT_MASK; + scale_shift = 0; + } + + texture = tmptex; + num_filters--; + } + + /* + * texture compression + */ + /* ignored if we only have texture compression option on. + * only done when texture enhancer is used. see constructor. */ + if ((_options & COMPRESSION_MASK) && + (srcwidth >= 64 && srcheight >= 64) /* Texture compression is not suitable for low pixel coarse detail + * textures. The assumption here is that textures larger than 64x64 + * have enough detail to produce decent quality when compressed. The + * down side is that narrow stripped textures that the N64 often use + * for large background textures are also ignored. It would be more + * reasonable if decisions are made based on fourier-transform + * spectrum or RMS error. + */ + ) { + int compressionType = _options & COMPRESSION_MASK; + int tmpwidth, tmpheight; + uint16 tmpformat; + /* XXX: textures that use 8bit alpha channel look bad with the current + * fxt1 library, so we substitute it with dxtn for now. afaik all gfx + * cards that support fxt1 also support dxtn. (3dfx and Intel) */ + if ((destformat == GR_TEXFMT_ALPHA_INTENSITY_88) || + (destformat == GR_TEXFMT_ARGB_8888) || + (destformat == GR_TEXFMT_ALPHA_8)) { + compressionType = S3TC_COMPRESSION; + } + tmptex = (texture == _tex1) ? _tex2 : _tex1; + if (_txQuantize->compress(texture, tmptex, + srcwidth, srcheight, srcformat, + &tmpwidth, &tmpheight, &tmpformat, + compressionType)) { + srcwidth = tmpwidth; + srcheight = tmpheight; + destformat = tmpformat; + texture = tmptex; + } + } + + + /* + * texture (re)conversions + */ + if (destformat == GR_TEXFMT_ARGB_8888) { + if (srcformat == GR_TEXFMT_ARGB_8888 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)) srcformat = GR_TEXFMT_ARGB_4444; + if (srcformat != GR_TEXFMT_ARGB_8888) { + tmptex = (texture == _tex1) ? _tex2 : _tex1; + if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, GR_TEXFMT_ARGB_8888, srcformat)) { + DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", srcformat); + return 0; + } + texture = tmptex; + destformat = srcformat; + } + } + + break; +#if !_16BPP_HACK + case GR_TEXFMT_ARGB_4444: + + int scale_shift = 0; + tmptex = (texture == _tex1) ? _tex2 : _tex1; + + switch (_options & ENHANCEMENT_MASK) { + case HQ4X_ENHANCEMENT: + if (srcwidth <= (_maxwidth >> 2) && srcheight <= (_maxheight >> 2)) { + hq4x_4444((uint8*)texture, (uint8*)tmptex, srcwidth, srcheight, srcwidth, srcwidth * 4 * 2); + scale_shift = 2; + }/* else if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) { + hq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight); + scale_shift = 1; + }*/ + break; + case HQ2X_ENHANCEMENT: + if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) { + hq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight); + scale_shift = 1; + } + break; + case HQ2XS_ENHANCEMENT: + if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) { + hq2xS_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight); + scale_shift = 1; + } + break; + case LQ2X_ENHANCEMENT: + if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) { + lq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight); + scale_shift = 1; + } + break; + case LQ2XS_ENHANCEMENT: + if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) { + lq2xS_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight); + scale_shift = 1; + } + break; + case X2SAI_ENHANCEMENT: + if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) { + Super2xSaI_4444((uint16*)texture, (uint16*)tmptex, srcwidth, srcheight, srcwidth); + scale_shift = 1; + } + break; + case X2_ENHANCEMENT: + if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) { + Texture2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight); + scale_shift = 1; + } + } + if (scale_shift) { + srcwidth <<= scale_shift; + srcheight <<= scale_shift; + texture = tmptex; + } + + if (_options & SMOOTH_FILTER_MASK) { + tmptex = (texture == _tex1) ? _tex2 : _tex1; + SmoothFilter_4444((uint16*)texture, srcwidth, srcheight, (uint16*)tmptex, (_options & SMOOTH_FILTER_MASK)); + texture = tmptex; + } else if (_options & SHARP_FILTER_MASK) { + tmptex = (texture == _tex1) ? _tex2 : _tex1; + SharpFilter_4444((uint16*)texture, srcwidth, srcheight, (uint16*)tmptex, (_options & SHARP_FILTER_MASK)); + texture = tmptex; + } + + break; + case GR_TEXFMT_ARGB_1555: + break; + case GR_TEXFMT_RGB_565: + break; + case GR_TEXFMT_ALPHA_8: + break; +#endif /* _16BPP_HACK */ + } + } + + /* fill in the texture info. */ + info->data = texture; + info->width = srcwidth; + info->height = srcheight; + info->format = destformat; + info->smallLodLog2 = _txUtil->grLodLog2(srcwidth, srcheight); + info->largeLodLog2 = info->smallLodLog2; + info->aspectRatioLog2 = _txUtil->grAspectRatioLog2(srcwidth, srcheight); + info->is_hires_tex = 0; + + /* cache the texture. */ + if (_cacheSize) _txTexCache->add(g64crc, info); + + DBG_INFO(80, L"filtered texture: %d x %d gfmt:%x\n", info->width, info->height, info->format); + + return 1; +} + +boolean +TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info) +{ + /* NOTE: Rice CRC32 sometimes return the same value for different textures. + * As a workaround, Glide64 CRC32 is used for the key for NON-hires + * texture cache. + * + * r_crc64 = hi:palette low:texture + * (separate crc. doesn't necessary have to be rice crc) + * g64crc = texture + palette glide64 crc32 + * (can be any other crc if robust) + */ + + DBG_INFO(80, L"hirestex: r_crc64:%08X %08X, g64crc:%08X %08X\n", + (uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff), + (uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff)); + +#if HIRES_TEXTURE + /* check if we have it in hires memory cache. */ + if ((_options & HIRESTEXTURES_MASK) && r_crc64) { + if (_txHiResCache->get(r_crc64, info)) { + DBG_INFO(80, L"hires hit: %d x %d gfmt:%x\n", info->width, info->height, info->format); + + /* TODO: Enable emulation for special N64 combiner modes. There are few ways + * to get this done. Also applies for CI textures below. + * + * Solution 1. Load the hiresolution textures in ARGB8888 (or A8, IA88) format + * to cache. When a cache is hit, then we take the modes passed in from Glide64 + * (also TODO) and apply the modification. Then we do color reduction or format + * conversion or compression if desired and stuff it into the non-hires texture + * cache. + * + * Solution 2. When a cache is hit and if the combiner modes are present, + * convert the texture to ARGB4444 and pass it back to Glide64 to process. + * If a texture is compressed, it needs to be decompressed first. Then add + * the processed texture to the non-hires texture cache. + * + * Solution 3. Hybrid of the above 2. Load the textures in ARGB8888 (A8, IA88) + * format. Convert the texture to ARGB4444 and pass it back to Glide64 when + * the combiner modes are present. Get the processed texture back from Glide64 + * and compress if desired and add it to the non-hires texture cache. + * + * Solution 4. Take the easy way out and forget about this whole thing. + */ + + return 1; /* yep, got it */ + } + if (_txHiResCache->get((r_crc64 & 0xffffffff), info)) { + DBG_INFO(80, L"hires hit: %d x %d gfmt:%x\n", info->width, info->height, info->format); + + /* for true CI textures, we use the passed in palette to convert to + * ARGB1555 and add it to memory cache. + * + * NOTE: we do this AFTER all other texture cache searches because + * only a few texture packs actually use true CI textures. + * + * NOTE: the pre-converted palette from Glide64 is in RGBA5551 format. + * A comp comes before RGB comp. + */ + if (palette && info->format == GR_TEXFMT_P_8) { + DBG_INFO(80, L"found GR_TEXFMT_P_8 format. Need conversion!!\n"); + + int width = info->width; + int height = info->height; + uint16 format = info->format; + /* XXX: avoid collision with zlib compression buffer in TxHiResTexture::get */ + uint8 *texture = info->data; + uint8 *tmptex = (texture == _tex1) ? _tex2 : _tex1; + + /* use palette and convert to 16bit format */ + _txQuantize->P8_16BPP((uint32*)texture, (uint32*)tmptex, info->width, info->height, (uint32*)palette); + texture = tmptex; + format = GR_TEXFMT_ARGB_1555; + +#if 1 + /* XXX: compressed if memory cache compression is ON */ + if (_options & COMPRESSION_MASK) { + tmptex = (texture == _tex1) ? _tex2 : _tex1; + if (_txQuantize->quantize(texture, tmptex, info->width, info->height, format, GR_TEXFMT_ARGB_8888)) { + texture = tmptex; + format = GR_TEXFMT_ARGB_8888; + } + if (format == GR_TEXFMT_ARGB_8888) { + tmptex = (texture == _tex1) ? _tex2 : _tex1; + if (_txQuantize->compress(texture, tmptex, + info->width, info->height, GR_TEXFMT_ARGB_1555, + &width, &height, &format, + _options & COMPRESSION_MASK)) { + texture = tmptex; + } else { + /*if (!_txQuantize->quantize(texture, tmptex, info->width, info->height, GR_TEXFMT_ARGB_8888, GR_TEXFMT_ARGB_1555)) { + DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", format); + return 0; + }*/ + texture = tmptex; + format = GR_TEXFMT_ARGB_1555; + } + } + } +#endif + + /* fill in the required info to return */ + info->data = texture; + info->width = width; + info->height = height; + info->format = format; + info->smallLodLog2 = _txUtil->grLodLog2(width, height); + info->largeLodLog2 = info->smallLodLog2; + info->aspectRatioLog2 = _txUtil->grAspectRatioLog2(width, height); + info->is_hires_tex = 1; + + /* XXX: add to hires texture cache!!! */ + _txHiResCache->add(r_crc64, info); + + DBG_INFO(80, L"GR_TEXFMT_P_8 loaded as gfmt:%x!\n", format); + } + + return 1; + } + } +#endif + + /* check if we have it in memory cache */ + if (_cacheSize && g64crc) { + if (_txTexCache->get(g64crc, info)) { + DBG_INFO(80, L"cache hit: %d x %d gfmt:%x\n", info->width, info->height, info->format); + return 1; /* yep, we've got it */ + } + } + + DBG_INFO(80, L"no cache hits.\n"); + + return 0; +} + +uint64 +TxFilter::checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette) +{ + if (_options & (HIRESTEXTURES_MASK|DUMP_TEX)) + return _txUtil->checksum64(src, width, height, size, rowStride, palette); + + return 0; +} + +boolean +TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64) +{ + if (!_initialized) + return 0; + + if (!(_options & DUMP_TEX)) + return 0; + + DBG_INFO(80, L"gfmt = %02x n64fmt = %02x\n", gfmt, n64fmt); + DBG_INFO(80, L"hirestex: r_crc64:%08X %08X\n", + (uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff)); + + if (!_txQuantize->quantize(src, _tex1, rowStridePixel, height, (gfmt & 0x00ff), GR_TEXFMT_ARGB_8888)) + return 0; + + src = _tex1; + + if (!_path.empty() && !_ident.empty()) { + /* dump it to disk */ + FILE *fp = NULL; + std::wstring tmpbuf; + + /* create directories */ + tmpbuf.assign(_path + L"/texture_dump"); + if (!boost::filesystem::exists(tmpbuf) && + !boost::filesystem::create_directory(tmpbuf)) + return 0; + + tmpbuf.append(L"/" + _ident); + if (!boost::filesystem::exists(tmpbuf) && + !boost::filesystem::create_directory(tmpbuf)) + return 0; + + tmpbuf.append(L"/GlideHQ"); + if (!boost::filesystem::exists(tmpbuf) && + !boost::filesystem::create_directory(tmpbuf)) + return 0; + + if ((n64fmt >> 8) == 0x2) { + tmpbuf.append(boost::str(boost::wformat(L"/%ls#%08X#%01X#%01X#%08X_ciByRGBA.png") + % _ident.c_str() % (uint32)(r_crc64 & 0xffffffff) % (n64fmt >> 8) % (n64fmt & 0xf) % (uint32)(r_crc64 >> 32))); + } else { + tmpbuf.append(boost::str(boost::wformat(L"/%ls#%08X#%01X#%01X_all.png") + % _ident.c_str() % (uint32)(r_crc64 & 0xffffffff) % (n64fmt >> 8) % (n64fmt & 0xf))); + } + +#ifdef WIN32 + if ((fp = _wfopen(tmpbuf.c_str(), L"wb")) != NULL) { +#else + char cbuf[MAX_PATH]; + wcstombs(cbuf, tmpbuf.c_str(), MAX_PATH); + if ((fp = fopen(cbuf, "wb")) != NULL) { +#endif + _txImage->writePNG(src, fp, width, height, (rowStridePixel << 2), 0x0003, 0); + fclose(fp); + return 1; + } + } + + return 0; +} + +boolean +TxFilter::reloadhirestex() +{ + DBG_INFO(80, L"Reload hires textures from texture pack.\n"); + + if (_txHiResCache->load(0)) { + if (_txHiResCache->empty()) _options &= ~HIRESTEXTURES_MASK; + else _options |= HIRESTEXTURES_MASK; + + return 1; + } + + return 0; +} diff --git a/GLideNHQ/TxFilter.h b/GLideNHQ/TxFilter.h new file mode 100644 index 00000000..fdbd0268 --- /dev/null +++ b/GLideNHQ/TxFilter.h @@ -0,0 +1,81 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TXFILTER_H__ +#define __TXFILTER_H__ + +#include "TxInternal.h" +#include "TxQuantize.h" +#include "TxHiResCache.h" +#include "TxTexCache.h" +#include "TxUtil.h" +#include "TxImage.h" +#include + +class TxFilter +{ +private: + int _numcore; + + uint8 *_tex1; + uint8 *_tex2; + int _maxwidth; + int _maxheight; + int _maxbpp; + int _options; + int _cacheSize; + std::wstring _ident; + std::wstring _path; + TxQuantize *_txQuantize; + TxTexCache *_txTexCache; + TxHiResCache *_txHiResCache; + TxUtil *_txUtil; + TxImage *_txImage; + boolean _initialized; + void clear(); +public: + ~TxFilter(); + TxFilter(int maxwidth, + int maxheight, + int maxbpp, + int options, + int cachesize, + wchar_t *path, + wchar_t *ident, + dispInfoFuncExt callback); + boolean filter(uint8 *src, + int srcwidth, + int srcheight, + uint16 srcformat, + uint64 g64crc, /* glide64 crc, 64bit for future use */ + GHQTexInfo *info); + boolean hirestex(uint64 g64crc, /* glide64 crc, 64bit for future use */ + uint64 r_crc64, /* checksum hi:palette low:texture */ + uint16 *palette, + GHQTexInfo *info); + uint64 checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette); + boolean dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64); + boolean reloadhirestex(); +}; + +#endif /* __TXFILTER_H__ */ diff --git a/GLideNHQ/TxFilterExport.cpp b/GLideNHQ/TxFilterExport.cpp new file mode 100644 index 00000000..e9b30f84 --- /dev/null +++ b/GLideNHQ/TxFilterExport.cpp @@ -0,0 +1,106 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __MSC__ +#pragma warning(disable: 4786) +#endif + +#include "TxFilter.h" + +TxFilter *txFilter = NULL; + +#ifdef __cplusplus +extern "C"{ +#endif + +TAPI boolean TAPIENTRY +txfilter_init(int maxwidth, int maxheight, int maxbpp, int options, int cachesize, + wchar_t *path, wchar_t*ident, + dispInfoFuncExt callback) +{ + if (txFilter) return 0; + + txFilter = new TxFilter(maxwidth, maxheight, maxbpp, options, cachesize, + path, ident, callback); + + return (txFilter ? 1 : 0); +} + +TAPI void TAPIENTRY +txfilter_shutdown(void) +{ + if (txFilter) delete txFilter; + + txFilter = NULL; +} + +TAPI boolean TAPIENTRY +txfilter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, + uint64 g64crc, GHQTexInfo *info) +{ + if (txFilter) + return txFilter->filter(src, srcwidth, srcheight, srcformat, + g64crc, info); + + return 0; +} + +TAPI boolean TAPIENTRY +txfilter_hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info) +{ + if (txFilter) + return txFilter->hirestex(g64crc, r_crc64, palette, info); + + return 0; +} + +TAPI uint64 TAPIENTRY +txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette) +{ + if (txFilter) + return txFilter->checksum64(src, width, height, size, rowStride, palette); + + return 0; +} + +TAPI boolean TAPIENTRY +txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64) +{ + if (txFilter) + return txFilter->dmptx(src, width, height, rowStridePixel, gfmt, n64fmt, r_crc64); + + return 0; +} + +TAPI boolean TAPIENTRY +txfilter_reloadhirestex() +{ + if (txFilter) + return txFilter->reloadhirestex(); + + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/GLideNHQ/TxHiResCache.cpp b/GLideNHQ/TxHiResCache.cpp new file mode 100644 index 00000000..a23a7254 --- /dev/null +++ b/GLideNHQ/TxHiResCache.cpp @@ -0,0 +1,1080 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* 2007 Gonetz + * Added callback to display hires texture info. */ + +#ifdef __MSC__ +#pragma warning(disable: 4786) +#endif + +/* dump processed hirestextures to disk + * (0:disable, 1:enable) */ +#define DUMP_CACHE 1 + +/* handle oversized textures by + * 0: minification + * 1: Glide64 style tiling + */ +#define TEXTURE_TILING 1 + +/* use power of 2 texture size + * (0:disable, 1:enable, 2:3dfx) */ +#define POW2_TEXTURES 2 + +#if TEXTURE_TILING +#undef POW2_TEXTURES +#define POW2_TEXTURES 2 +#endif + +/* hack to reduce texture footprint to achieve + * better performace on midrange gfx cards. + * (0:disable, 1:enable) */ +#define REDUCE_TEXTURE_FOOTPRINT 0 + +/* use aggressive format assumption for quantization + * (0:disable, 1:enable, 2:extreme) */ +#define AGGRESSIVE_QUANTIZATION 1 + +#include "TxHiResCache.h" +#include "TxDbg.h" +#include +#include + +TxHiResCache::~TxHiResCache() +{ +#if DUMP_CACHE + if ((_options & DUMP_HIRESTEXCACHE) && !_haveCache && !_abortLoad) { + /* dump cache to disk */ + std::wstring filename = _ident + L"_HIRESTEXTURES.dat"; + boost::filesystem::wpath cachepath(_path); + cachepath /= boost::filesystem::wpath(L"cache"); + int config = _options & (HIRESTEXTURES_MASK|COMPRESS_HIRESTEX|COMPRESSION_MASK|TILE_HIRESTEX|FORCE16BPP_HIRESTEX|GZ_HIRESTEXCACHE|LET_TEXARTISTS_FLY); + + TxCache::save(cachepath.wstring().c_str(), filename.c_str(), config); + } +#endif + + delete _txImage; + delete _txQuantize; + delete _txReSample; +} + +TxHiResCache::TxHiResCache(int maxwidth, int maxheight, int maxbpp, int options, + const wchar_t *path, const wchar_t *ident, + dispInfoFuncExt callback + ) : TxCache((options & ~GZ_TEXCACHE), 0, path, ident, callback) +{ + _txImage = new TxImage(); + _txQuantize = new TxQuantize(); + _txReSample = new TxReSample(); + + _maxwidth = maxwidth; + _maxheight = maxheight; + _maxbpp = maxbpp; + _abortLoad = 0; + _haveCache = 0; + + /* assert local options */ + if (!(_options & COMPRESS_HIRESTEX)) + _options &= ~COMPRESSION_MASK; + + if (_path.empty() || _ident.empty()) { + _options &= ~DUMP_HIRESTEXCACHE; + return; + } + +#if DUMP_CACHE + /* read in hires texture cache */ + if (_options & DUMP_HIRESTEXCACHE) { + /* find it on disk */ + std::wstring filename = _ident + L"_HIRESTEXTURES.dat"; + boost::filesystem::wpath cachepath(_path); + cachepath /= boost::filesystem::wpath(L"cache"); + int config = _options & (HIRESTEXTURES_MASK|COMPRESS_HIRESTEX|COMPRESSION_MASK|TILE_HIRESTEX|FORCE16BPP_HIRESTEX|GZ_HIRESTEXCACHE|LET_TEXARTISTS_FLY); + + _haveCache = TxCache::load(cachepath.wstring().c_str(), filename.c_str(), config); + } +#endif + + /* read in hires textures */ + if (!_haveCache) TxHiResCache::load(0); +} + +boolean +TxHiResCache::empty() +{ + return _cache.empty(); +} + +boolean +TxHiResCache::load(boolean replace) /* 0 : reload, 1 : replace partial */ +{ + if (!_path.empty() && !_ident.empty()) { + + if (!replace) TxCache::clear(); + + boost::filesystem::wpath dir_path(_path); + + switch (_options & HIRESTEXTURES_MASK) { + case GHQ_HIRESTEXTURES: + break; + case RICE_HIRESTEXTURES: + INFO(80, L"-----\n"); + INFO(80, L"using Rice hires texture format...\n"); + INFO(80, L" must be one of the following;\n"); + INFO(80, L" 1) *_rgb.png + *_a.png\n"); + INFO(80, L" 2) *_all.png\n"); + INFO(80, L" 3) *_ciByRGBA.png\n"); + INFO(80, L" 4) *_allciByRGBA.png\n"); + INFO(80, L" 5) *_ci.bmp\n"); + INFO(80, L" usage of only 2) and 3) highly recommended!\n"); + INFO(80, L" folder names must be in US-ASCII characters!\n"); + + dir_path /= boost::filesystem::wpath(L"hires_texture"); + dir_path /= boost::filesystem::wpath(_ident); + loadHiResTextures(dir_path, replace); + break; + case JABO_HIRESTEXTURES: + ; + } + + return 1; + } + + return 0; +} + +boolean +TxHiResCache::loadHiResTextures(boost::filesystem::wpath dir_path, boolean replace) +{ + DBG_INFO(80, L"-----\n"); + DBG_INFO(80, L"path: %ls\n", dir_path.string().c_str()); + + /* find it on disk */ + if (!boost::filesystem::exists(dir_path)) { + INFO(80, L"Error: path not found!\n"); + return 0; + } + + /* XXX: deal with UNICODE fiasco! + * stupidity flows forth beneath this... + * + * I opted to use chdir in order to use fopen() for windows 9x. + */ +#ifdef WIN32 + wchar_t curpath[MAX_PATH]; + GETCWD(MAX_PATH, curpath); + CHDIR(dir_path.wstring().c_str()); +#else + char curpath[MAX_PATH]; + char cbuf[MAX_PATH]; + wcstombs(cbuf, dir_path.string().c_str(), MAX_PATH); + GETCWD(MAX_PATH, curpath); + CHDIR(cbuf); +#endif + + /* NOTE: I could use the boost::wdirectory_iterator and boost::wpath + * to resolve UNICODE file names and paths. But then, _wfopen() is + * required to get the file descriptor for MS Windows to pass into + * libpng, which is incompatible with Win9x. Win9x's fopen() cannot + * handle UNICODE names. UNICODE capable boost::filesystem is available + * with Boost1.34.1 built with VC8.0 (bjam --toolset=msvc-8.0 stage). + * + * RULE OF THUMB: NEVER save texture packs in NON-ASCII names!! + */ + boost::filesystem::directory_iterator it(dir_path); + boost::filesystem::directory_iterator end_it; /* default construction yields past-the-end */ + + for (; it != end_it; ++it) { + + if (KBHIT(0x1B)) { + _abortLoad = 1; + if (_callback) (*_callback)(L"Aborted loading hiresolution texture!\n"); + INFO(80, L"Error: aborted loading hiresolution texture!\n"); + } + if (_abortLoad) break; + + /* recursive read into sub-directory */ + if (boost::filesystem::is_directory(it->status())) { + loadHiResTextures(it->path(), replace); + continue; + } + + DBG_INFO(80, L"-----\n"); + DBG_INFO(80, L"file: %ls\n", it->path().leaf().c_str()); + + int width = 0, height = 0; + uint16 format = 0; + uint8 *tex = NULL; + int tmpwidth = 0, tmpheight = 0; + uint16 tmpformat = 0; + uint8 *tmptex= NULL; + int untiled_width = 0, untiled_height = 0; + uint16 destformat = 0; + + /* Rice hi-res textures: begin + */ + uint32 chksum = 0, fmt = 0, siz = 0, palchksum = 0; + char *pfname = NULL, fname[MAX_PATH]; + std::string ident; + FILE *fp = NULL; + + wcstombs(fname, _ident.c_str(), MAX_PATH); + /* XXX case sensitivity fiasco! + * files must use _a, _rgb, _all, _allciByRGBA, _ciByRGBA, _ci + * and file extensions must be in lower case letters! */ +#ifdef WIN32 + { + unsigned int i; + for (i = 0; i < strlen(fname); i++) fname[i] = tolower(fname[i]); + } +#endif + ident.assign(fname); + + /* read in Rice's file naming convention */ +#define CRCFMTSIZ_LEN 13 +#define PALCRC_LEN 9 + wcstombs(fname, it->path().leaf().c_str(), MAX_PATH); + /* XXX case sensitivity fiasco! + * files must use _a, _rgb, _all, _allciByRGBA, _ciByRGBA, _ci + * and file extensions must be in lower case letters! */ +#ifdef WIN32 + { + unsigned int i; + for (i = 0; i < strlen(fname); i++) fname[i] = tolower(fname[i]); + } +#endif + pfname = fname + strlen(fname) - 4; + if (!(pfname == strstr(fname, ".png") || + pfname == strstr(fname, ".bmp") || + pfname == strstr(fname, ".dds"))) { +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Error: not png or bmp or dds!\n"); + continue; + } + pfname = strstr(fname, ident.c_str()); + if (pfname != fname) pfname = 0; + if (pfname) { + if (sscanf(pfname + ident.size(), "#%08X#%01X#%01X#%08X", &chksum, &fmt, &siz, &palchksum) == 4) + pfname += (ident.size() + CRCFMTSIZ_LEN + PALCRC_LEN); + else if (sscanf(pfname + ident.size(), "#%08X#%01X#%01X", &chksum, &fmt, &siz) == 3) + pfname += (ident.size() + CRCFMTSIZ_LEN); + else + pfname = 0; + } + if (!pfname) { +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Error: not Rice texture naming convention!\n"); + continue; + } + if (!chksum) { +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Error: crc32 = 0!\n"); + continue; + } + + /* check if we already have it in hires texture cache */ + if (!replace) { + uint64 chksum64 = (uint64)palchksum; + chksum64 <<= 32; + chksum64 |= (uint64)chksum; + if (TxCache::is_cached(chksum64)) { +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Error: already cached! duplicate texture!\n"); + continue; + } + } + + DBG_INFO(80, L"rom: %ls chksum:%08X %08X fmt:%x size:%x\n", _ident.c_str(), chksum, palchksum, fmt, siz); + + /* Deal with the wackiness some texture packs utilize Rice format. + * Read in the following order: _a.* + _rgb.*, _all.png _ciByRGBA.png, + * _allciByRGBA.png, and _ci.bmp. PNG are prefered over BMP. + * + * For some reason there are texture packs that include them all. Some + * even have RGB textures named as _all.* and ARGB textures named as + * _rgb.*... Someone pleeeez write a GOOD guideline for the texture + * designers!!! + * + * We allow hires textures to have higher bpp than the N64 originals. + */ + /* N64 formats + * Format: 0 - RGBA, 1 - YUV, 2 - CI, 3 - IA, 4 - I + * Size: 0 - 4bit, 1 - 8bit, 2 - 16bit, 3 - 32 bit + */ + + /* + * read in _rgb.* and _a.* + */ + if (pfname == strstr(fname, "_rgb.") || pfname == strstr(fname, "_a.")) { + strcpy(pfname, "_rgb.png"); + if (!boost::filesystem::exists(fname)) { + strcpy(pfname, "_rgb.bmp"); + if (!boost::filesystem::exists(fname)) { +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Error: missing _rgb.*! _a.* must be paired with _rgb.*!\n"); + continue; + } + } + /* _a.png */ + strcpy(pfname, "_a.png"); + if ((fp = fopen(fname, "rb")) != NULL) { + tmptex = _txImage->readPNG(fp, &tmpwidth, &tmpheight, &tmpformat); + fclose(fp); + } + if (!tmptex) { + /* _a.bmp */ + strcpy(pfname, "_a.bmp"); + if ((fp = fopen(fname, "rb")) != NULL) { + tmptex = _txImage->readBMP(fp, &tmpwidth, &tmpheight, &tmpformat); + fclose(fp); + } + } + /* _rgb.png */ + strcpy(pfname, "_rgb.png"); + if ((fp = fopen(fname, "rb")) != NULL) { + tex = _txImage->readPNG(fp, &width, &height, &format); + fclose(fp); + } + if (!tex) { + /* _rgb.bmp */ + strcpy(pfname, "_rgb.bmp"); + if ((fp = fopen(fname, "rb")) != NULL) { + tex = _txImage->readBMP(fp, &width, &height, &format); + fclose(fp); + } + } + if (tmptex) { + /* check if _rgb.* and _a.* have matching size and format. */ + if (!tex || width != tmpwidth || height != tmpheight || + format != GR_TEXFMT_ARGB_8888 || tmpformat != GR_TEXFMT_ARGB_8888) { +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + if (!tex) { + INFO(80, L"Error: missing _rgb.*!\n"); + } else if (width != tmpwidth || height != tmpheight) { + INFO(80, L"Error: _rgb.* and _a.* have mismatched width or height!\n"); + } else if (format != GR_TEXFMT_ARGB_8888 || tmpformat != GR_TEXFMT_ARGB_8888) { + INFO(80, L"Error: _rgb.* or _a.* not in 32bit color!\n"); + } + if (tex) free(tex); + if (tmptex) free(tmptex); + tex = NULL; + tmptex = NULL; + continue; + } + } + /* make adjustments */ + if (tex) { + if (tmptex) { + /* merge (A)RGB and A comp */ + DBG_INFO(80, L"merge (A)RGB and A comp\n"); + int i; + for (i = 0; i < height * width; i++) { +#if 1 + /* use R comp for alpha. this is what Rice uses. sigh... */ + ((uint32*)tex)[i] &= 0x00ffffff; + ((uint32*)tex)[i] |= ((((uint32*)tmptex)[i] & 0x00ff0000) << 8); +#endif +#if 0 + /* use libpng style grayscale conversion */ + uint32 texel = ((uint32*)tmptex)[i]; + uint32 acomp = (((texel >> 16) & 0xff) * 6969 + + ((texel >> 8) & 0xff) * 23434 + + ((texel ) & 0xff) * 2365) / 32768; + ((uint32*)tex)[i] = (acomp << 24) | (((uint32*)tex)[i] & 0x00ffffff); +#endif +#if 0 + /* use the standard NTSC gray scale conversion */ + uint32 texel = ((uint32*)tmptex)[i]; + uint32 acomp = (((texel >> 16) & 0xff) * 299 + + ((texel >> 8) & 0xff) * 587 + + ((texel ) & 0xff) * 114) / 1000; + ((uint32*)tex)[i] = (acomp << 24) | (((uint32*)tex)[i] & 0x00ffffff); +#endif + } + free(tmptex); + tmptex = NULL; + } else { + /* clobber A comp. never a question of alpha. only RGB used. */ +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Warning: missing _a.*! only using _rgb.*. treat as opaque texture.\n"); + int i; + for (i = 0; i < height * width; i++) { + ((uint32*)tex)[i] |= 0xff000000; + } + } + } + } else + + /* + * read in _all.png, _all.dds, _allciByRGBA.png, _allciByRGBA.dds + * _ciByRGBA.png, _ciByRGBA.dds, _ci.bmp + */ + if (pfname == strstr(fname, "_all.png") || + pfname == strstr(fname, "_all.dds") || +#ifdef WIN32 + pfname == strstr(fname, "_allcibyrgba.png") || + pfname == strstr(fname, "_allcibyrgba.dds") || + pfname == strstr(fname, "_cibyrgba.png") || + pfname == strstr(fname, "_cibyrgba.dds") || +#else + pfname == strstr(fname, "_allciByRGBA.png") || + pfname == strstr(fname, "_allciByRGBA.dds") || + pfname == strstr(fname, "_ciByRGBA.png") || + pfname == strstr(fname, "_ciByRGBA.dds") || +#endif + pfname == strstr(fname, "_ci.bmp")) { + if ((fp = fopen(fname, "rb")) != NULL) { + if (strstr(fname, ".png")) tex = _txImage->readPNG(fp, &width, &height, &format); + else if (strstr(fname, ".dds")) tex = _txImage->readDDS(fp, &width, &height, &format); + else tex = _txImage->readBMP(fp, &width, &height, &format); + fclose(fp); + } + /* XXX: auto-adjustment of dxt dds textures unsupported for now */ + if (tex && strstr(fname, ".dds")) { + const float aspectratio = (width > height) ? (float)width/(float)height : (float)height/(float)width; + if (!(aspectratio == 1.0 || + aspectratio == 2.0 || + aspectratio == 4.0 || + aspectratio == 8.0)) { + free(tex); + tex = NULL; +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Error: W:H aspect ratio range not 8:1 - 1:8!\n"); + continue; + } + if (width != _txReSample->nextPow2(width) || + height != _txReSample->nextPow2(height)) { + free(tex); + tex = NULL; +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Error: not power of 2 size!\n"); + continue; + } + } + } + + /* if we do not have a texture at this point we are screwed */ + if (!tex) { +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Error: load failed!\n"); + continue; + } + DBG_INFO(80, L"read in as %d x %d gfmt:%x\n", tmpwidth, tmpheight, tmpformat); + + /* check if size and format are OK */ + if (!(format == GR_TEXFMT_ARGB_8888 || + format == GR_TEXFMT_P_8 || + format == GR_TEXFMT_ARGB_CMP_DXT1 || + format == GR_TEXFMT_ARGB_CMP_DXT3 || + format == GR_TEXFMT_ARGB_CMP_DXT5) || + (width * height) < 4) { /* TxQuantize requirement: width * height must be 4 or larger. */ + free(tex); + tex = NULL; +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + INFO(80, L"Error: not width * height > 4 or 8bit palette color or 32bpp or dxt1 or dxt3 or dxt5!\n"); + continue; + } + + /* analyze and determine best format to quantize */ + if (format == GR_TEXFMT_ARGB_8888) { + int i; + int alphabits = 0; + int fullalpha = 0; + boolean intensity = 1; + + if (!(_options & LET_TEXARTISTS_FLY)) { + /* HACK ALERT! */ + /* Account for Rice's weirdness with fmt:0 siz:2 textures. + * Although the conditions are relaxed with other formats, + * the D3D RGBA5551 surface is used for this format in certain + * cases. See Nintemod's SuperMario64 life gauge and power + * meter. The same goes for fmt:2 textures. See Mollymutt's + * PaperMario text. */ + if ((fmt == 0 && siz == 2) || fmt == 2) { + DBG_INFO(80, L"Remove black, white, etc borders along the alpha edges.\n"); + /* round A comp */ + for (i = 0; i < height * width; i++) { + uint32 texel = ((uint32*)tex)[i]; + ((uint32*)tex)[i] = ((texel & 0xff000000) == 0xff000000 ? 0xff000000 : 0) | + (texel & 0x00ffffff); + } + /* Substitute texel color with the average of the surrounding + * opaque texels. This removes borders regardless of hardware + * texture filtering (bilinear, etc). */ + int j; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + uint32 texel = ((uint32*)tex)[i * width + j]; + if ((texel & 0xff000000) != 0xff000000) { + uint32 tmptexel[8]; + uint32 k, numtexel, r, g, b; + numtexel = r = g = b = 0; + memset(&tmptexel, 0, sizeof(tmptexel)); + if (i > 0) { + tmptexel[0] = ((uint32*)tex)[(i - 1) * width + j]; /* north */ + if (j > 0) tmptexel[1] = ((uint32*)tex)[(i - 1) * width + j - 1]; /* north-west */ + if (j < width - 1) tmptexel[2] = ((uint32*)tex)[(i - 1) * width + j + 1]; /* north-east */ + } + if (i < height - 1) { + tmptexel[3] = ((uint32*)tex)[(i + 1) * width + j]; /* south */ + if (j > 0) tmptexel[4] = ((uint32*)tex)[(i + 1) * width + j - 1]; /* south-west */ + if (j < width - 1) tmptexel[5] = ((uint32*)tex)[(i + 1) * width + j + 1]; /* south-east */ + } + if (j > 0) tmptexel[6] = ((uint32*)tex)[i * width + j - 1]; /* west */ + if (j < width - 1) tmptexel[7] = ((uint32*)tex)[i * width + j + 1]; /* east */ + for (k = 0; k < 8; k++) { + if ((tmptexel[k] & 0xff000000) == 0xff000000) { + r += ((tmptexel[k] & 0x00ff0000) >> 16); + g += ((tmptexel[k] & 0x0000ff00) >> 8); + b += ((tmptexel[k] & 0x000000ff) ); + numtexel++; + } + } + if (numtexel) { + ((uint32*)tex)[i * width + j] = ((r / numtexel) << 16) | + ((g / numtexel) << 8) | + ((b / numtexel) ); + } else { + ((uint32*)tex)[i * width + j] = texel & 0x00ffffff; + } + } + } + } + } + } + + /* simple analysis of texture */ + for (i = 0; i < height * width; i++) { + uint32 texel = ((uint32*)tex)[i]; + if (alphabits != 8) { +#if AGGRESSIVE_QUANTIZATION + if ((texel & 0xff000000) < 0x00000003) { + alphabits = 1; + fullalpha++; + } else if ((texel & 0xff000000) < 0xfe000000) { + alphabits = 8; + } +#else + if ((texel & 0xff000000) == 0x00000000) { + alphabits = 1; + fullalpha++; + } else if ((texel & 0xff000000) != 0xff000000) { + alphabits = 8; + } +#endif + } + if (intensity) { + int rcomp = (texel >> 16) & 0xff; + int gcomp = (texel >> 8) & 0xff; + int bcomp = (texel ) & 0xff; +#if AGGRESSIVE_QUANTIZATION + if (abs(rcomp - gcomp) > 8 || abs(rcomp - bcomp) > 8 || abs(gcomp - bcomp) > 8) intensity = 0; +#else + if (rcomp != gcomp || rcomp != bcomp || gcomp != bcomp) intensity = 0; +#endif + } + if (!intensity && alphabits == 8) break; + } + DBG_INFO(80, L"required alpha bits:%d zero acomp texels:%d rgb as intensity:%d\n", alphabits, fullalpha, intensity); + + /* preparations based on above analysis */ +#if !REDUCE_TEXTURE_FOOTPRINT + if (_maxbpp < 32 || _options & (FORCE16BPP_HIRESTEX|COMPRESSION_MASK)) { +#endif + if (alphabits == 0) destformat = GR_TEXFMT_RGB_565; + else if (alphabits == 1) destformat = GR_TEXFMT_ARGB_1555; + else destformat = GR_TEXFMT_ARGB_8888; +#if !REDUCE_TEXTURE_FOOTPRINT + } else { + destformat = GR_TEXFMT_ARGB_8888; + } +#endif + if (fmt == 4 && alphabits == 0) { + destformat = GR_TEXFMT_ARGB_8888; + /* Rice I format; I = (R + G + B) / 3 */ + for (i = 0; i < height * width; i++) { + uint32 texel = ((uint32*)tex)[i]; + uint32 icomp = (((texel >> 16) & 0xff) + + ((texel >> 8) & 0xff) + + ((texel ) & 0xff)) / 3; + ((uint32*)tex)[i] = (icomp << 24) | (texel & 0x00ffffff); + } + } + if (intensity) { + if (alphabits == 0) { + if (fmt == 4) destformat = GR_TEXFMT_ALPHA_8; + else destformat = GR_TEXFMT_INTENSITY_8; + } else { + destformat = GR_TEXFMT_ALPHA_INTENSITY_88; + } + } + + DBG_INFO(80, L"best gfmt:%x\n", destformat); + } + /* + * Rice hi-res textures: end */ + + + /* XXX: only ARGB8888 for now. comeback to this later... */ + if (format == GR_TEXFMT_ARGB_8888) { + +#if TEXTURE_TILING + + /* Glide64 style texture tiling */ + /* NOTE: narrow wide textures can be tiled into 256x256 size textures */ + + /* adjust texture size to allow tiling for V1, Rush, V2, Banshee, V3 */ + /* NOTE: we skip this for palette textures that need minification + * becasue it will look ugly. */ + + /* minification */ + { + int ratio = 1; + + /* minification to enable glide64 style texture tiling */ + /* determine the minification ratio to tile the texture into 256x256 size */ + if ((_options & TILE_HIRESTEX) && _maxwidth >= 256 && _maxheight >= 256) { + DBG_INFO(80, L"determine minification ratio to tile\n"); + tmpwidth = width; + tmpheight = height; + if (height > 256) { + ratio = ((height - 1) >> 8) + 1; + tmpwidth = width / ratio; + tmpheight = height / ratio; + DBG_INFO(80, L"height > 256, minification ratio:%d %d x %d -> %d x %d\n", + ratio, width, height, tmpwidth, tmpheight); + } + if (tmpwidth > 256 && (((tmpwidth - 1) >> 8) + 1) * tmpheight > 256) { + ratio *= ((((((tmpwidth - 1) >> 8) + 1) * tmpheight) - 1) >> 8) + 1; + DBG_INFO(80, L"width > 256, minification ratio:%d %d x %d -> %d x %d\n", + ratio, width, height, width / ratio, height / ratio); + } + } else { + /* normal minification to fit max texture size */ + if (width > _maxwidth || height > _maxheight) { + DBG_INFO(80, L"determine minification ratio to fit max texture size\n"); + tmpwidth = width; + tmpheight = height; + while (tmpwidth > _maxwidth) { + tmpheight >>= 1; + tmpwidth >>= 1; + ratio <<= 1; + } + while (tmpheight > _maxheight) { + tmpheight >>= 1; + tmpwidth >>= 1; + ratio <<= 1; + } + DBG_INFO(80, L"minification ratio:%d %d x %d -> %d x %d\n", + ratio, width, height, tmpwidth, tmpheight); + } + } + + if (ratio > 1) { + if (!_txReSample->minify(&tex, &width, &height, ratio)) { + free(tex); + tex = NULL; + DBG_INFO(80, L"Error: minification failed!\n"); + continue; + } + } + } + + /* tiling */ + if ((_options & TILE_HIRESTEX) && _maxwidth >= 256 && _maxheight >= 256) { + boolean usetile = 0; + + /* to tile or not to tile, that is the question */ + if (width > 256 && height <= 128 && (((width - 1) >> 8) + 1) * height <= 256) { + + if (width > _maxwidth) usetile = 1; + else { + /* tile if the tiled texture memory footprint is smaller */ + int tilewidth = 256; + int tileheight = _txReSample->nextPow2((((width - 1) >> 8) + 1) * height); + tmpwidth = width; + tmpheight = height; + + /* 3dfx Glide3 tmpheight, W:H aspect ratio range (8:1 - 1:8) */ + if (tilewidth > (tileheight << 3)) tileheight = tilewidth >> 3; + + /* HACKALERT: see TxReSample::pow2(); */ + if (tmpwidth > 64) tmpwidth -= 4; + else if (tmpwidth > 16) tmpwidth -= 2; + else if (tmpwidth > 4) tmpwidth -= 1; + + if (tmpheight > 64) tmpheight -= 4; + else if (tmpheight > 16) tmpheight -= 2; + else if (tmpheight > 4) tmpheight -= 1; + + tmpwidth = _txReSample->nextPow2(tmpwidth); + tmpheight = _txReSample->nextPow2(tmpheight); + + /* 3dfx Glide3 tmpheight, W:H aspect ratio range (8:1 - 1:8) */ + if (tmpwidth > tmpheight) { + if (tmpwidth > (tmpheight << 3)) tmpheight = tmpwidth >> 3; + } else { + if (tmpheight > (tmpwidth << 3)) tmpwidth = tmpheight >> 3; + } + + usetile = (tilewidth * tileheight < tmpwidth * tmpheight); + } + + } + + /* tile it! do the actual tiling into 256x256 size */ + if (usetile) { + DBG_INFO(80, L"Glide64 style texture tiling\n"); + + int x, y, z, ratio, offset; + offset = 0; + ratio = ((width - 1) >> 8) + 1; + tmptex = (uint8 *)malloc(_txUtil->sizeofTx(256, height * ratio, format)); + if (tmptex) { + for (x = 0; x < ratio; x++) { + for (y = 0; y < height; y++) { + if (x < ratio - 1) { + memcpy(&tmptex[offset << 2], &tex[(x * 256 + y * width) << 2], 256 << 2); + } else { + for (z = 0; z < width - 256 * (ratio - 1); z++) { + ((uint32*)tmptex)[offset + z] = ((uint32*)tex)[x * 256 + y * width + z]; + } + for (; z < 256; z++) { + ((uint32*)tmptex)[offset + z] = ((uint32*)tmptex)[offset + z - 1]; + } + } + offset += 256; + } + } + free(tex); + tex = tmptex; + untiled_width = width; + untiled_height = height; + width = 256; + height *= ratio; + DBG_INFO(80, L"Tiled: %d x %d -> %d x %d\n", untiled_width, untiled_height, width, height); + } + } + } + +#else /* TEXTURE_TILING */ + + /* minification */ + if (width > _maxwidth || height > _maxheight) { + int ratio = 1; + if (width / _maxwidth > height / _maxheight) { + ratio = (int)ceil((double)width / _maxwidth); + } else { + ratio = (int)ceil((double)height / _maxheight); + } + if (!_txReSample->minify(&tex, &width, &height, ratio)) { + free(tex); + tex = NULL; + DBG_INFO(80, L"Error: minification failed!\n"); + continue; + } + } + +#endif /* TEXTURE_TILING */ + + /* texture compression */ + if ((_options & COMPRESSION_MASK) && + (width >= 64 && height >= 64) /* Texture compression is not suitable for low pixel coarse detail + * textures. The assumption here is that textures larger than 64x64 + * have enough detail to produce decent quality when compressed. The + * down side is that narrow stripped textures that the N64 often use + * for large background textures are also ignored. It would be more + * reasonable if decisions are made based on fourier-transform + * spectrum or RMS error. + * + * NOTE: texture size must be checked before expanding to pow2 size. + */ + ) { + uint32 alpha = 0; + int dataSize = 0; + int compressionType = _options & COMPRESSION_MASK; + +#if POW2_TEXTURES +#if (POW2_TEXTURES == 2) + /* 3dfx Glide3x aspect ratio (8:1 - 1:8) */ + if (!_txReSample->nextPow2(&tex, &width , &height, 32, 1)) { +#else + /* normal pow2 expansion */ + if (!_txReSample->nextPow2(&tex, &width , &height, 32, 0)) { +#endif + free(tex); + tex = NULL; + DBG_INFO(80, L"Error: aspect ratio adjustment failed!\n"); + continue; + } +#endif + + switch (_options & COMPRESSION_MASK) { + case S3TC_COMPRESSION: + switch (destformat) { + case GR_TEXFMT_ARGB_8888: +#if GLIDE64_DXTN + case GR_TEXFMT_ARGB_1555: /* for ARGB1555 use DXT5 instead of DXT1 */ +#endif + case GR_TEXFMT_ALPHA_INTENSITY_88: + dataSize = width * height; + break; +#if !GLIDE64_DXTN + case GR_TEXFMT_ARGB_1555: +#endif + case GR_TEXFMT_RGB_565: + case GR_TEXFMT_INTENSITY_8: + dataSize = (width * height) >> 1; + break; + case GR_TEXFMT_ALPHA_8: /* no size benefit with dxtn */ + ; + } + break; + case FXT1_COMPRESSION: + switch (destformat) { + case GR_TEXFMT_ARGB_1555: + case GR_TEXFMT_RGB_565: + case GR_TEXFMT_INTENSITY_8: + dataSize = (width * height) >> 1; + break; + /* XXX: textures that use 8bit alpha channel look bad with the current + * fxt1 library, so we substitute it with dxtn for now. afaik all gfx + * cards that support fxt1 also support dxtn. (3dfx and Intel) */ + case GR_TEXFMT_ALPHA_INTENSITY_88: + case GR_TEXFMT_ARGB_8888: + compressionType = S3TC_COMPRESSION; + dataSize = width * height; + break; + case GR_TEXFMT_ALPHA_8: /* no size benefit with dxtn */ + ; + } + } + /* compress it! */ + if (dataSize) { +#if 0 /* TEST: dither before compression for better results with gradients */ + tmptex = (uint8 *)malloc(_txUtil->sizeofTx(width, height, destformat)); + if (tmptex) { + if (_txQuantize->quantize(tex, tmptex, width, height, GR_TEXFMT_ARGB_8888, destformat, 0)) + _txQuantize->quantize(tmptex, tex, width, height, destformat, GR_TEXFMT_ARGB_8888, 0); + free(tmptex); + } +#endif + tmptex = (uint8 *)malloc(dataSize); + if (tmptex) { + if (_txQuantize->compress(tex, tmptex, + width, height, destformat, + &tmpwidth, &tmpheight, &tmpformat, + compressionType)) { + free(tex); + tex = tmptex; + width = tmpwidth; + height = tmpheight; + format = destformat = tmpformat; + } else { + free(tmptex); + } + } + } + + } else { + +#if POW2_TEXTURES +#if (POW2_TEXTURES == 2) + /* 3dfx Glide3x aspect ratio (8:1 - 1:8) */ + if (!_txReSample->nextPow2(&tex, &width , &height, 32, 1)) { +#else + /* normal pow2 expansion */ + if (!_txReSample->nextPow2(&tex, &width , &height, 32, 0)) { +#endif + free(tex); + tex = NULL; + DBG_INFO(80, L"Error: aspect ratio adjustment failed!\n"); + continue; + } +#endif + } + + /* quantize */ + { + tmptex = (uint8 *)malloc(_txUtil->sizeofTx(width, height, destformat)); + if (tmptex) { + switch (destformat) { + case GR_TEXFMT_ARGB_8888: + case GR_TEXFMT_ARGB_4444: +#if !REDUCE_TEXTURE_FOOTPRINT + if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX) +#endif + destformat = GR_TEXFMT_ARGB_4444; + break; + case GR_TEXFMT_ARGB_1555: +#if !REDUCE_TEXTURE_FOOTPRINT + if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX) +#endif + destformat = GR_TEXFMT_ARGB_1555; + break; + case GR_TEXFMT_RGB_565: +#if !REDUCE_TEXTURE_FOOTPRINT + if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX) +#endif + destformat = GR_TEXFMT_RGB_565; + break; + case GR_TEXFMT_ALPHA_INTENSITY_88: + case GR_TEXFMT_ALPHA_INTENSITY_44: +#if !REDUCE_TEXTURE_FOOTPRINT + destformat = GR_TEXFMT_ALPHA_INTENSITY_88; +#else + destformat = GR_TEXFMT_ALPHA_INTENSITY_44; +#endif + break; + case GR_TEXFMT_ALPHA_8: + destformat = GR_TEXFMT_ALPHA_8; /* yes, this is correct. ALPHA_8 instead of INTENSITY_8 */ + break; + case GR_TEXFMT_INTENSITY_8: + destformat = GR_TEXFMT_INTENSITY_8; + } + if (_txQuantize->quantize(tex, tmptex, width, height, GR_TEXFMT_ARGB_8888, destformat, 0)) { + format = destformat; + free(tex); + tex = tmptex; + } + } + } + + } + + + /* last minute validations */ + if (!tex || !chksum || !width || !height || !format || width > _maxwidth || height > _maxheight) { +#if !DEBUG + INFO(80, L"-----\n"); + INFO(80, L"path: %ls\n", dir_path.string().c_str()); + INFO(80, L"file: %ls\n", it->path().leaf().c_str()); +#endif + if (tex) { + free(tex); + tex = NULL; + INFO(80, L"Error: bad format or size! %d x %d gfmt:%x\n", width, height, format); + } else { + INFO(80, L"Error: load failed!!\n"); + } + continue; + } + + /* load it into hires texture cache. */ + { + uint64 chksum64 = (uint64)palchksum; + chksum64 <<= 32; + chksum64 |= (uint64)chksum; + + GHQTexInfo tmpInfo; + memset(&tmpInfo, 0, sizeof(GHQTexInfo)); + + tmpInfo.data = tex; + tmpInfo.width = width; + tmpInfo.height = height; + tmpInfo.format = format; + tmpInfo.largeLodLog2 = _txUtil->grLodLog2(width, height); + tmpInfo.smallLodLog2 = tmpInfo.largeLodLog2; + tmpInfo.aspectRatioLog2 = _txUtil->grAspectRatioLog2(width, height); + tmpInfo.is_hires_tex = 1; + +#if TEXTURE_TILING + /* Glide64 style texture tiling. */ + if (untiled_width && untiled_height) { + tmpInfo.tiles = ((untiled_width - 1) >> 8) + 1; + tmpInfo.untiled_width = untiled_width; + tmpInfo.untiled_height = untiled_height; + } +#endif + + /* remove redundant in cache */ + if (replace && TxCache::del(chksum64)) { + DBG_INFO(80, L"removed duplicate old cache.\n"); + } + + /* add to cache */ + if (TxCache::add(chksum64, &tmpInfo)) { + /* Callback to display hires texture info. + * Gonetz */ + if (_callback) { + wchar_t tmpbuf[MAX_PATH]; + mbstowcs(tmpbuf, fname, MAX_PATH); + (*_callback)(L"[%d] total mem:%.2fmb - %ls\n", _cache.size(), (float)_totalSize/1000000, tmpbuf); + } + DBG_INFO(80, L"texture loaded!\n"); + } + free(tex); + } + + } + + CHDIR(curpath); + + return 1; +} diff --git a/GLideNHQ/TxHiResCache.h b/GLideNHQ/TxHiResCache.h new file mode 100644 index 00000000..9da88c7c --- /dev/null +++ b/GLideNHQ/TxHiResCache.h @@ -0,0 +1,60 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TXHIRESCACHE_H__ +#define __TXHIRESCACHE_H__ + +/* support hires textures + * 0: disable + * 1: enable + */ +#define HIRES_TEXTURE 1 + +#include "TxCache.h" +#include "TxQuantize.h" +#include "TxImage.h" +#include "TxReSample.h" +#include + +class TxHiResCache : public TxCache +{ +private: + int _maxwidth; + int _maxheight; + int _maxbpp; + boolean _haveCache; + boolean _abortLoad; + TxImage *_txImage; + TxQuantize *_txQuantize; + TxReSample *_txReSample; + boolean loadHiResTextures(boost::filesystem::wpath dir_path, boolean replace); +public: + ~TxHiResCache(); + TxHiResCache(int maxwidth, int maxheight, int maxbpp, int options, + const wchar_t *path, const wchar_t *ident, + dispInfoFuncExt callback); + boolean empty(); + boolean load(boolean replace); +}; + +#endif /* __TXHIRESCACHE_H__ */ diff --git a/GLideNHQ/TxImage.cpp b/GLideNHQ/TxImage.cpp new file mode 100644 index 00000000..871a004c --- /dev/null +++ b/GLideNHQ/TxImage.cpp @@ -0,0 +1,799 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* use power of 2 texture size + * (0:disable, 1:enable, 2:3dfx) */ +#define POW2_TEXTURES 0 + +/* check 8 bytes. use a larger value if needed. */ +#define PNG_CHK_BYTES 8 + +#include "TxImage.h" +#include "TxReSample.h" +#include "TxDbg.h" +#include + +boolean +TxImage::getPNGInfo(FILE *fp, png_structp *png_ptr, png_infop *info_ptr) +{ + unsigned char sig[PNG_CHK_BYTES]; + + /* check for valid file pointer */ + if (!fp) + return 0; + + /* check if file is PNG */ + if (fread(sig, 1, PNG_CHK_BYTES, fp) != PNG_CHK_BYTES) + return 0; + + if (png_sig_cmp(sig, 0, PNG_CHK_BYTES) != 0) + return 0; + + /* get PNG file info */ + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!*png_ptr) + return 0; + + *info_ptr = png_create_info_struct(*png_ptr); + if (!*info_ptr) { + png_destroy_read_struct(png_ptr, NULL, NULL); + return 0; + } + + if (setjmp(png_jmpbuf(*png_ptr))) { + DBG_INFO(80, L"error reading png!\n"); + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return 0; + } + + png_init_io(*png_ptr, fp); + png_set_sig_bytes(*png_ptr, PNG_CHK_BYTES); + png_read_info(*png_ptr, *info_ptr); + + return 1; +} + +uint8* +TxImage::readPNG(FILE* fp, int* width, int* height, uint16* format) +{ + /* NOTE: returned image format is GR_TEXFMT_ARGB_8888 */ + + png_structp png_ptr; + png_infop info_ptr; + uint8 *image = NULL; + int bit_depth, color_type, interlace_type, compression_type, filter_type, + row_bytes, o_width, o_height, num_pas; + + /* initialize */ + *width = 0; + *height = 0; + *format = 0; + + /* check if we have a valid png file */ + if (!fp) + return NULL; + + if (!getPNGInfo(fp, &png_ptr, &info_ptr)) { + INFO(80, L"error reading png file! png image is corrupt.\n"); + return NULL; + } + + png_get_IHDR(png_ptr, info_ptr, + (png_uint_32*)&o_width, (png_uint_32*)&o_height, &bit_depth, &color_type, + &interlace_type, &compression_type, &filter_type); + + DBG_INFO(80, L"png format %d x %d bitdepth:%d color:%x interlace:%x compression:%x filter:%x\n", + o_width, o_height, bit_depth, color_type, + interlace_type, compression_type, filter_type); + + /* transformations */ + + /* Rice hi-res textures + * _all.png + * _rgb.png, _a.png + * _ciByRGBA.png + * _allciByRGBA.png + */ + + /* strip if color channel is larger than 8 bits */ + if (bit_depth > 8) { + png_set_strip_16(png_ptr); + bit_depth = 8; + } + +#if 1 + /* These are not really required per Rice format spec, + * but is done just in case someone uses them. + */ + /* convert palette color to rgb color */ + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + color_type = PNG_COLOR_TYPE_RGB; + } + + /* expand 1,2,4 bit gray scale to 8 bit gray scale */ + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand_gray_1_2_4_to_8(png_ptr); + + /* convert gray scale or gray scale + alpha to rgb color */ + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + color_type = PNG_COLOR_TYPE_RGB; + } +#endif + + /* add alpha channel if any */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png_ptr); + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + + /* convert rgb to rgba */ + if (color_type == PNG_COLOR_TYPE_RGB) { + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + + /* punt invalid formats */ + if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + DBG_INFO(80, L"Error: not PNG_COLOR_TYPE_RGB_ALPHA format!\n"); + return NULL; + } + + /*png_color_8p sig_bit; + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit);*/ + + /* convert rgba to bgra */ + png_set_bgr(png_ptr); + + /* turn on interlace handling to cope with the weirdness + * of texture authors using interlaced format */ + num_pas = png_set_interlace_handling(png_ptr); + + /* update info structure */ + png_read_update_info(png_ptr, info_ptr); + + /* we only get here if ARGB8888 */ + row_bytes = png_get_rowbytes(png_ptr, info_ptr); + + /* allocate memory to read in image */ + image = (uint8*)malloc(row_bytes * o_height); + + /* read in image */ + if (image) { + int pas, i; + uint8* tmpimage; + + for (pas = 0; pas < num_pas; pas++) { /* deal with interlacing */ + tmpimage = image; + + for (i = 0; i < o_height; i++) { + /* copy row */ + png_read_rows(png_ptr, &tmpimage, NULL, 1); + tmpimage += row_bytes; + } + } + + /* read rest of the info structure */ + png_read_end(png_ptr, info_ptr); + + *width = (row_bytes >> 2); + *height = o_height; + *format = GR_TEXFMT_ARGB_8888; + +#if POW2_TEXTURES + /* next power of 2 size conversions */ + /* NOTE: I can do this in the above loop for faster operations, but some + * texture packs require a workaround. see HACKALERT in nextPow2(). + */ + + TxReSample txReSample = new TxReSample; // XXX: temporary. move to a better place. + +#if (POW2_TEXTURES == 2) + if (!txReSample->nextPow2(&image, width, height, 32, 1)) { +#else + if (!txReSample->nextPow2(&image, width, height, 32, 0)) { +#endif + if (image) { + free(image); + image = NULL; + } + *width = 0; + *height = 0; + *format = 0; + } + + delete txReSample; + +#endif /* POW2_TEXTURES */ + } + + /* clean up */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + +#ifdef DEBUG + if (!image) { + DBG_INFO(80, L"Error: failed to load png image!\n"); + } +#endif + + return image; +} + +boolean +TxImage::writePNG(uint8* src, FILE* fp, int width, int height, int rowStride, uint16 format, uint8 *palette) +{ + png_structp png_ptr; + png_infop info_ptr; + png_color_8 sig_bit; + png_colorp palette_ptr; + png_bytep trans_ptr;//, tex_ptr; + int bit_depth, color_type, row_bytes, num_palette; + int i; + //uint16 srcfmt, destfmt; + + if (!src || !fp) + return 0; + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) + return 0; + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, NULL); + return 0; + } + + if (setjmp(png_ptr->jmpbuf)) { + png_destroy_write_struct(&png_ptr, &info_ptr); + return 0; + } + + png_init_io(png_ptr, fp); + + /* TODO: images must be converted to RGBA8888 or CI8, + * palettes need to be separated to A and RGB. */ + + /* N64 formats + * Format: 0 - RGBA, 1 - YUV, 2 - CI, 3 - IA, 4 - I + * Size: 0 - 4bit, 1 - 8bit, 2 - 16bit, 3 - 32 bit + * format = (Format << 8 | Size); + */ + + /* each channel is saved in 8bits for consistency */ + switch (format) { + case 0x0002:/* RGBA5551 */ + bit_depth = 8; + sig_bit.red = 5; + sig_bit.green = 5; + sig_bit.blue = 5; + sig_bit.alpha = 1; + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + break; + case 0x0003:/* RGBA8888 */ + case 0x0302:/* IA88 */ + bit_depth = 8; + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = 8; + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + break; + case 0x0300:/* IA31 */ + bit_depth = 8; + sig_bit.red = 3; + sig_bit.green = 3; + sig_bit.blue = 3; + sig_bit.alpha = 1; + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + break; + case 0x0301:/* IA44 */ + bit_depth = 8; + sig_bit.red = 4; + sig_bit.green = 4; + sig_bit.blue = 4; + sig_bit.alpha = 4; + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + break; + case 0x0400:/* I4 */ + bit_depth = 8; + sig_bit.red = 4; + sig_bit.green = 4; + sig_bit.blue = 4; + color_type = PNG_COLOR_TYPE_RGB; + break; + case 0x0401:/* I8 */ + case 0x0402:/* I16 */ + bit_depth = 8; + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + color_type = PNG_COLOR_TYPE_RGB; + break; + case 0x0200:/* CI4 */ + bit_depth = 8; + num_palette = 16; + color_type = PNG_COLOR_TYPE_PALETTE; + break; + case 0x0201:/* CI8 */ + bit_depth = 8; + num_palette = 256; + color_type = PNG_COLOR_TYPE_PALETTE; + break; + case 0x0102:/* YUV ? */ + case 0x0103: + default: + /* unsupported format */ + png_destroy_write_struct(&png_ptr, &info_ptr); + return 0; + } + + switch (color_type) { + case PNG_COLOR_TYPE_RGB_ALPHA: + case PNG_COLOR_TYPE_RGB: + //row_bytes = (bit_depth * width) >> 1; + row_bytes = rowStride; + png_set_bgr(png_ptr); + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + break; + case PNG_COLOR_TYPE_PALETTE: + //row_bytes = (bit_depth * width) >> 3; + row_bytes = rowStride; + png_set_PLTE(png_ptr, info_ptr, palette_ptr, num_palette); + png_set_tRNS(png_ptr, info_ptr, trans_ptr, num_palette, 0); + } + + //png_set_filter(png_ptr, 0, PNG_ALL_FILTERS); + + //if (bit_depth == 16) + // png_set_swap(png_ptr); + + //if (bit_depth < 8) + // png_set_packswap(png_ptr); + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + //png_set_gAMA(png_ptr, info_ptr, 1.0); + + png_write_info(png_ptr, info_ptr); + for (i = 0; i < height; i++) { + png_write_row(png_ptr, (png_bytep)src); + src += row_bytes; + } + png_write_end(png_ptr, info_ptr); + + png_destroy_write_struct(&png_ptr, &info_ptr); + + //if (tex_ptr) delete [] tex_ptr; + + return 1; +} + +boolean +TxImage::getBMPInfo(FILE* fp, BITMAPFILEHEADER* bmp_fhdr, BITMAPINFOHEADER* bmp_ihdr) +{ + /* + * read in BITMAPFILEHEADER + */ + + /* is this a BMP file? */ + if (fread(&bmp_fhdr->bfType, 2, 1, fp) != 1) + return 0; + + if (memcmp(&bmp_fhdr->bfType, "BM", 2) != 0) + return 0; + + /* get file size */ + if (fread(&bmp_fhdr->bfSize, 4, 1, fp) != 1) + return 0; + + /* reserved 1 */ + if (fread(&bmp_fhdr->bfReserved1, 2, 1, fp) != 1) + return 0; + + /* reserved 2 */ + if (fread(&bmp_fhdr->bfReserved2, 2, 1, fp) != 1) + return 0; + + /* offset to the image data */ + if (fread(&bmp_fhdr->bfOffBits, 4, 1, fp) != 1) + return 0; + + /* + * read in BITMAPINFOHEADER + */ + + /* size of BITMAPINFOHEADER */ + if (fread(&bmp_ihdr->biSize, 4, 1, fp) != 1) + return 0; + + /* is this a Windows BMP? */ + if (bmp_ihdr->biSize != 40) + return 0; + + /* width of the bitmap in pixels */ + if (fread(&bmp_ihdr->biWidth, 4, 1, fp) != 1) + return 0; + + /* height of the bitmap in pixels */ + if (fread(&bmp_ihdr->biHeight, 4, 1, fp) != 1) + return 0; + + /* number of planes (always 1) */ + if (fread(&bmp_ihdr->biPlanes, 2, 1, fp) != 1) + return 0; + + /* number of bits-per-pixel. (1, 4, 8, 16, 24, 32) */ + if (fread(&bmp_ihdr->biBitCount, 2, 1, fp) != 1) + return 0; + + /* compression for a compressed bottom-up bitmap + * 0 : uncompressed format + * 1 : run-length encoded 4 bpp format + * 2 : run-length encoded 8 bpp format + * 3 : bitfield + */ + if (fread(&bmp_ihdr->biCompression, 4, 1, fp) != 1) + return 0; + + /* size of the image in bytes */ + if (fread(&bmp_ihdr->biSizeImage, 4, 1, fp) != 1) + return 0; + + /* horizontal resolution in pixels-per-meter */ + if (fread(&bmp_ihdr->biXPelsPerMeter, 4, 1, fp) != 1) + return 0; + + /* vertical resolution in pixels-per-meter */ + if (fread(&bmp_ihdr->biYPelsPerMeter, 4, 1, fp) != 1) + return 0; + + /* number of color indexes in the color table that are actually used */ + if (fread(&bmp_ihdr->biClrUsed, 4, 1, fp) != 1) + return 0; + + /* the number of color indexes that are required for displaying */ + if (fread(&bmp_ihdr->biClrImportant, 4, 1, fp) != 1) + return 0; + + return 1; +} + +uint8* +TxImage::readBMP(FILE* fp, int* width, int* height, uint16* format) +{ + /* NOTE: returned image format; + * 4, 8bit palette bmp -> GR_TEXFMT_P_8 + * 24, 32bit bmp -> GR_TEXFMT_ARGB_8888 + */ + + uint8 *image = NULL; + uint8 *image_row = NULL; + uint8 *tmpimage = NULL; + int row_bytes, pos, i, j; + /* Windows Bitmap */ + BITMAPFILEHEADER bmp_fhdr; + BITMAPINFOHEADER bmp_ihdr; + + /* initialize */ + *width = 0; + *height = 0; + *format = 0; + + /* check if we have a valid bmp file */ + if (!fp) + return NULL; + + if (!getBMPInfo(fp, &bmp_fhdr, &bmp_ihdr)) { + INFO(80, L"error reading bitmap file! bitmap image is corrupt.\n"); + return NULL; + } + + DBG_INFO(80, L"bmp format %d x %d bitdepth:%d compression:%x offset:%d\n", + bmp_ihdr.biWidth, bmp_ihdr.biHeight, bmp_ihdr.biBitCount, + bmp_ihdr.biCompression, bmp_fhdr.bfOffBits); + + /* rowStride in bytes */ + row_bytes = (bmp_ihdr.biWidth * bmp_ihdr.biBitCount) >> 3; + /* align to 4bytes boundary */ + row_bytes = (row_bytes + 3) & ~3; + + /* Rice hi-res textures */ + if (!(bmp_ihdr.biBitCount == 8 || bmp_ihdr.biBitCount == 4 || bmp_ihdr.biBitCount == 32 || bmp_ihdr.biBitCount == 24) || + bmp_ihdr.biCompression != 0) { + DBG_INFO(80, L"Error: incompatible bitmap format!\n"); + return NULL; + } + + switch (bmp_ihdr.biBitCount) { + case 8: + case 32: + /* 8 bit, 32 bit bitmap */ + image = (uint8*)malloc(row_bytes * bmp_ihdr.biHeight); + if (image) { + tmpimage = image; + pos = bmp_fhdr.bfOffBits + row_bytes * (bmp_ihdr.biHeight - 1); + for (i = 0; i < bmp_ihdr.biHeight; i++) { + /* read in image */ + fseek(fp, pos, SEEK_SET); + fread(tmpimage, row_bytes, 1, fp); + tmpimage += row_bytes; + pos -= row_bytes; + } + } + break; + case 4: + /* 4bit bitmap */ + image = (uint8*)malloc((row_bytes * bmp_ihdr.biHeight) << 1); + image_row = (uint8*)malloc(row_bytes); + if (image && image_row) { + tmpimage = image; + pos = bmp_fhdr.bfOffBits + row_bytes * (bmp_ihdr.biHeight - 1); + for (i = 0; i < bmp_ihdr.biHeight; i++) { + /* read in image */ + fseek(fp, pos, SEEK_SET); + fread(image_row, row_bytes, 1, fp); + /* expand 4bpp to 8bpp. stuff 4bit values into 8bit comps. */ + for (j = 0; j < row_bytes; j++) { + tmpimage[j << 1] = image_row[j] & 0x0f; + tmpimage[(j << 1) + 1] = (image_row[j] & 0xf0) >> 4; + } + tmpimage += (row_bytes << 1); + pos -= row_bytes; + } + free(image_row); + } else { + if (image_row) free(image_row); + if (image) free(image); + image = NULL; + } + break; + case 24: + /* 24 bit bitmap */ + image = (uint8*)malloc((bmp_ihdr.biWidth * bmp_ihdr.biHeight) << 2); + image_row = (uint8*)malloc(row_bytes); + if (image && image_row) { + tmpimage = image; + pos = bmp_fhdr.bfOffBits + row_bytes * (bmp_ihdr.biHeight - 1); + for (i = 0; i < bmp_ihdr.biHeight; i++) { + /* read in image */ + fseek(fp, pos, SEEK_SET); + fread(image_row, row_bytes, 1, fp); + /* convert 24bpp to 32bpp. */ + for (j = 0; j < bmp_ihdr.biWidth; j++) { + tmpimage[(j << 2)] = image_row[j * 3]; + tmpimage[(j << 2) + 1] = image_row[j * 3 + 1]; + tmpimage[(j << 2) + 2] = image_row[j * 3 + 2]; + tmpimage[(j << 2) + 3] = 0xFF; + } + tmpimage += (bmp_ihdr.biWidth << 2); + pos -= row_bytes; + } + free(image_row); + } else { + if (image_row) free(image_row); + if (image) free(image); + image = NULL; + } + } + + if (image) { + *width = (row_bytes << 3) / bmp_ihdr.biBitCount; + *height = bmp_ihdr.biHeight; + + switch (bmp_ihdr.biBitCount) { + case 8: + case 4: + *format = GR_TEXFMT_P_8; + break; + case 32: + case 24: + *format = GR_TEXFMT_ARGB_8888; + } + +#if POW2_TEXTURES + /* next power of 2 size conversions */ + /* NOTE: I can do this in the above loop for faster operations, but some + * texture packs require a workaround. see HACKALERT in nextPow2(). + */ + + TxReSample txReSample = new TxReSample; // XXX: temporary. move to a better place. + +#if (POW2_TEXTURES == 2) + if (!txReSample->nextPow2(&image, width, height, 8, 1)) { +#else + if (!txReSample->nextPow2(&image, width, height, 8, 0)) { +#endif + if (image) { + free(image); + image = NULL; + } + *width = 0; + *height = 0; + *format = 0; + } + + delete txReSample; + +#endif /* POW2_TEXTURES */ + } + +#ifdef DEBUG + if (!image) { + DBG_INFO(80, L"Error: failed to load bmp image!\n"); + } +#endif + + return image; +} + +boolean +TxImage::getDDSInfo(FILE *fp, DDSFILEHEADER *dds_fhdr) +{ + /* + * read in DDSFILEHEADER + */ + + /* is this a DDS file? */ + if (fread(&dds_fhdr->dwMagic, 4, 1, fp) != 1) + return 0; + + if (memcmp(&dds_fhdr->dwMagic, "DDS ", 4) != 0) + return 0; + + if (fread(&dds_fhdr->dwSize, 4, 1, fp) != 1) + return 0; + + /* get file flags */ + if (fread(&dds_fhdr->dwFlags, 4, 1, fp) != 1) + return 0; + + /* height of dds in pixels */ + if (fread(&dds_fhdr->dwHeight, 4, 1, fp) != 1) + return 0; + + /* width of dds in pixels */ + if (fread(&dds_fhdr->dwWidth, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->dwLinearSize, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->dwDepth, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->dwMipMapCount, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->dwReserved1, 4 * 11, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->ddpf.dwSize, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->ddpf.dwFlags, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->ddpf.dwFourCC, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->ddpf.dwRGBBitCount, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->ddpf.dwRBitMask, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->ddpf.dwGBitMask, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->ddpf.dwBBitMask, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->ddpf.dwRGBAlphaBitMask, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->dwCaps1, 4, 1, fp) != 1) + return 0; + + if (fread(&dds_fhdr->dwCaps2, 4, 1, fp) != 1) + return 0; + + return 1; +} + +uint8* +TxImage::readDDS(FILE* fp, int* width, int* height, uint16* format) +{ + uint8 *image = NULL; + DDSFILEHEADER dds_fhdr; + uint16 tmpformat = 0; + + /* initialize */ + *width = 0; + *height = 0; + *format = 0; + + /* check if we have a valid dds file */ + if (!fp) + return NULL; + + if (!getDDSInfo(fp, &dds_fhdr)) { + INFO(80, L"error reading dds file! dds image is corrupt.\n"); + return NULL; + } + + DBG_INFO(80, L"dds format %d x %d HeaderSize %d LinearSize %d\n", + dds_fhdr.dwWidth, dds_fhdr.dwHeight, dds_fhdr.dwSize, dds_fhdr.dwLinearSize); + + if (!(dds_fhdr.dwFlags & (DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT|DDSD_LINEARSIZE))) { + DBG_INFO(80, L"Error: incompatible dds format!\n"); + return NULL; + } + + if ((dds_fhdr.dwFlags & DDSD_MIPMAPCOUNT) && dds_fhdr.dwMipMapCount != 1) { + DBG_INFO(80, L"Error: mipmapped dds not supported!\n"); + return NULL; + } + + if (!((dds_fhdr.ddpf.dwFlags & DDPF_FOURCC) && dds_fhdr.dwCaps2 == 0)) { + DBG_INFO(80, L"Error: not fourcc standard texture!\n"); + return NULL; + } + + if (memcmp(&dds_fhdr.ddpf.dwFourCC, "DXT1", 4) == 0) { + DBG_INFO(80, L"DXT1 format\n"); + /* compensate for missing LinearSize */ + dds_fhdr.dwLinearSize = (dds_fhdr.dwWidth * dds_fhdr.dwHeight) >> 1; + tmpformat = GR_TEXFMT_ARGB_CMP_DXT1; + } else if (memcmp(&dds_fhdr.ddpf.dwFourCC, "DXT3", 4) == 0) { + DBG_INFO(80, L"DXT3 format\n"); + dds_fhdr.dwLinearSize = dds_fhdr.dwWidth * dds_fhdr.dwHeight; + tmpformat = GR_TEXFMT_ARGB_CMP_DXT3; + } else if (memcmp(&dds_fhdr.ddpf.dwFourCC, "DXT5", 4) == 0) { + DBG_INFO(80, L"DXT5 format\n"); + dds_fhdr.dwLinearSize = dds_fhdr.dwWidth * dds_fhdr.dwHeight; + tmpformat = GR_TEXFMT_ARGB_CMP_DXT5; + } else { + DBG_INFO(80, L"Error: not DXT1 or DXT3 or DXT5 format!\n"); + return NULL; + } + + /* read in image */ + image = (uint8*)malloc(dds_fhdr.dwLinearSize); + if (image) { + *width = dds_fhdr.dwWidth; + *height = dds_fhdr.dwHeight; + *format = tmpformat; + + fseek(fp, 128, SEEK_SET); /* size of header is 128 bytes */ + fread(image, dds_fhdr.dwLinearSize, 1, fp); + } + + return image; +} diff --git a/GLideNHQ/TxImage.h b/GLideNHQ/TxImage.h new file mode 100644 index 00000000..bf69c31b --- /dev/null +++ b/GLideNHQ/TxImage.h @@ -0,0 +1,116 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TXIMAGE_H__ +#define __TXIMAGE_H__ + +#include +#include +#include "TxInternal.h" + +#ifndef WIN32 +typedef struct tagBITMAPFILEHEADER { + unsigned short bfType; + unsigned long bfSize; + unsigned short bfReserved1; + unsigned short bfReserved2; + unsigned long bfOffBits; +} BITMAPFILEHEADER; + +typedef struct tagBITMAPINFOHEADER { + unsigned long biSize; + long biWidth; + long biHeight; + unsigned short biPlanes; + unsigned short biBitCount; + unsigned long biCompression; + unsigned long biSizeImage; + long biXPelsPerMeter; + long biYPelsPerMeter; + unsigned long biClrUsed; + unsigned long biClrImportant; +} BITMAPINFOHEADER; +#else +typedef struct tagBITMAPFILEHEADER BITMAPFILEHEADER; +typedef struct tagBITMAPINFOHEADER BITMAPINFOHEADER; +#endif + +#define DDSD_CAPS 0x00000001 +#define DDSD_HEIGHT 0x00000002 +#define DDSD_WIDTH 0x00000004 +#define DDSD_PITCH 0x00000008 +#define DDSD_PIXELFORMAT 0x00001000 +#define DDSD_MIPMAPCOUNT 0x00020000 +#define DDSD_LINEARSIZE 0x00080000 +#define DDSD_DEPTH 0x00800000 + +#define DDPF_ALPHAPIXELS 0x00000001 +#define DDPF_FOURCC 0x00000004 +#define DDPF_RGB 0x00000040 + +#define DDSCAPS_COMPLEX 0x00000008 +#define DDSCAPS_TEXTURE 0x00001000 +#define DDSCAPS_MIPMAP 0x00400000 + +typedef struct tagDDSPIXELFORMAT { + unsigned long dwSize; + unsigned long dwFlags; + unsigned long dwFourCC; + unsigned long dwRGBBitCount; + unsigned long dwRBitMask; + unsigned long dwGBitMask; + unsigned long dwBBitMask; + unsigned long dwRGBAlphaBitMask; +} DDSPIXELFORMAT; + +typedef struct tagDDSFILEHEADER { + unsigned long dwMagic; + unsigned long dwSize; + unsigned long dwFlags; + unsigned long dwHeight; + unsigned long dwWidth; + unsigned long dwLinearSize; + unsigned long dwDepth; + unsigned long dwMipMapCount; + unsigned long dwReserved1[11]; + DDSPIXELFORMAT ddpf; + unsigned long dwCaps1; + unsigned long dwCaps2; +} DDSFILEHEADER; + +class TxImage +{ +private: + boolean getPNGInfo(FILE *fp, png_structp *png_ptr, png_infop *info_ptr); + boolean getBMPInfo(FILE *fp, BITMAPFILEHEADER *bmp_fhdr, BITMAPINFOHEADER *bmp_ihdr); + boolean getDDSInfo(FILE *fp, DDSFILEHEADER *dds_fhdr); +public: + TxImage() {} + ~TxImage() {} + uint8* readPNG(FILE* fp, int* width, int* height, uint16* format); + boolean writePNG(uint8* src, FILE* fp, int width, int height, int rowStride, uint16 format, uint8 *palette); + uint8* readBMP(FILE* fp, int* width, int* height, uint16* format); + uint8* readDDS(FILE* fp, int* width, int* height, uint16* format); +}; + +#endif /* __TXIMAGE_H__ */ diff --git a/GLideNHQ/TxInternal.h b/GLideNHQ/TxInternal.h new file mode 100644 index 00000000..3f0be6d9 --- /dev/null +++ b/GLideNHQ/TxInternal.h @@ -0,0 +1,100 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __INTERNAL_H__ +#define __INTERNAL_H__ + +#include "Ext_TxFilter.h" + +/* dll exports */ +#ifdef TXFILTER_DLL +#define TAPI __declspec(dllexport) +#define TAPIENTRY +#else +#define TAPI +#define TAPIENTRY +#endif + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned long uint32; + +#ifdef WIN32 +#define KBHIT(key) ((GetAsyncKeyState(key) & 0x8001) == 0x8001) +#else +#define KBHIT(key) (0) +#endif + +/* from OpenGL glext.h */ +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +/* for explicit fxt1 compression */ +#define CC_CHROMA 0x0 +#define CC_HI 0x1 +#define CC_ALPHA 0x2 + +/* in-memory zlib texture compression */ +#define GR_TEXFMT_GZ 0x8000 + +#if 0 /* this is here to remind me of other formats */ +/* from 3Dfx Interactive Inc. glide.h */ +#define GR_TEXFMT_8BIT 0x0 +#define GR_TEXFMT_RGB_332 GR_TEXFMT_8BIT +#define GR_TEXFMT_YIQ_422 0x1 +#define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */ +#define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */ +#define GR_TEXFMT_ALPHA_INTENSITY_44 0x4 +#define GR_TEXFMT_P_8 0x5 /* 8-bit palette */ +#define GR_TEXFMT_RSVD0 0x6 /* GR_TEXFMT_P_8_RGBA */ +#define GR_TEXFMT_P_8_6666 GR_TEXFMT_RSVD0 +#define GR_TEXFMT_P_8_6666_EXT GR_TEXFMT_RSVD0 +#define GR_TEXFMT_RSVD1 0x7 +#define GR_TEXFMT_16BIT 0x8 +#define GR_TEXFMT_ARGB_8332 GR_TEXFMT_16BIT +#define GR_TEXFMT_AYIQ_8422 0x9 +#define GR_TEXFMT_RGB_565 0xa +#define GR_TEXFMT_ARGB_1555 0xb +#define GR_TEXFMT_ARGB_4444 0xc +#define GR_TEXFMT_ALPHA_INTENSITY_88 0xd +#define GR_TEXFMT_AP_88 0xe /* 8-bit alpha 8-bit palette */ +#define GR_TEXFMT_RSVD2 0xf +#define GR_TEXFMT_RSVD4 GR_TEXFMT_RSVD2 + +/* from 3Dfx Interactive Inc. g3ext.h */ +#define GR_TEXFMT_ARGB_CMP_FXT1 0x11 +#define GR_TEXFMT_ARGB_8888 0x12 +#define GR_TEXFMT_YUYV_422 0x13 +#define GR_TEXFMT_UYVY_422 0x14 +#define GR_TEXFMT_AYUV_444 0x15 +#define GR_TEXFMT_ARGB_CMP_DXT1 0x16 +#define GR_TEXFMT_ARGB_CMP_DXT2 0x17 +#define GR_TEXFMT_ARGB_CMP_DXT3 0x18 +#define GR_TEXFMT_ARGB_CMP_DXT4 0x19 +#define GR_TEXFMT_ARGB_CMP_DXT5 0x1A +#define GR_TEXTFMT_RGB_888 0xFF +#endif + +#endif /* __INTERNAL_H__ */ diff --git a/GLideNHQ/TxQuantize.cpp b/GLideNHQ/TxQuantize.cpp new file mode 100644 index 00000000..30959192 --- /dev/null +++ b/GLideNHQ/TxQuantize.cpp @@ -0,0 +1,2394 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __MSC__ +#pragma warning(disable: 4786) +#endif + +/* NOTE: The codes are not optimized. They can be made faster. */ + +#include "TxQuantize.h" +#include +#include + +TxQuantize::TxQuantize() +{ + _txUtil = new TxUtil(); + + /* get number of CPU cores. */ + _numcore = _txUtil->getNumberofProcessors(); + + /* get dxtn extensions */ + _tx_compress_fxt1 = TxLoadLib::getInstance()->getfxtCompressTexFuncExt(); + _tx_compress_dxtn = TxLoadLib::getInstance()->getdxtCompressTexFuncExt(); +} + + +TxQuantize::~TxQuantize() +{ + delete _txUtil; +} + +void +TxQuantize::ARGB1555_ARGB8888(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 1; + int i; + for (i = 0; i < siz; i++) { + *dest = (((*src & 0x00008000) ? 0xff000000 : 0x00000000) | + ((*src & 0x00007c00) << 9) | ((*src & 0x00007000) << 4) | + ((*src & 0x000003e0) << 6) | ((*src & 0x00000380) << 1) | + ((*src & 0x0000001f) << 3) | ((*src & 0x0000001c) >> 2)); + dest++; + *dest = (((*src & 0x80000000) ? 0xff000000 : 0x00000000) | + ((*src & 0x7c000000) >> 7) | ((*src & 0x70000000) >> 12) | + ((*src & 0x03e00000) >> 10) | ((*src & 0x03800000) >> 15) | + ((*src & 0x001f0000) >> 13) | ((*src & 0x001c0000) >> 18)); + dest++; + src++; + } +#else + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // arrr rrgg gggb bbbb + // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + mov edx, eax; // edx = arrrrrgg gggbbbbb arrrrrgg gggbbbbb + mov ebx, 0x00000000; + and eax, 0x00008000; // eax = 00000000 00000000 a0000000 00000000 + jz transparent1; + mov ebx, 0xff000000; // ebx = aaaaaaaa 00000000 00000000 00000000 + + transparent1: + mov eax, edx; // eax = arrrrrgg gggbbbbb arrrrrgg gggbbbbb + and edx, 0x00007c00; // edx = 00000000 00000000 0rrrrr00 00000000 + shl edx, 4; // edx = 00000000 00000rrr rr000000 00000000 + or ebx, edx; // ebx = aaaaaaaa 00000rrr rr000000 00000000 + shl edx, 5; // edx = 00000000 rrrrr000 00000000 00000000 + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr rr000000 00000000 + and ebx, 0xffff0000; // ebx = aaaaaaaa rrrrrrrr 00000000 00000000 + mov edx, eax; + and edx, 0x000003e0; // edx = 00000000 00000000 000000gg ggg00000 + shl edx, 1; // edx = 00000000 00000000 00000ggg gg000000 + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr 00000ggg gg000000 + shl edx, 5; // edx = 00000000 00000000 ggggg000 00000000 + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr gggggggg gg000000 + and ebx, 0xffffff00; // ebx = aaaaaaaa rrrrrrrr gggggggg 00000000 + mov edx, eax; + and edx, 0x0000001f; // edx = 00000000 00000000 00000000 000bbbbb + shl edx, 3; // edx = 00000000 00000000 00000000 bbbbb000 + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr gggggggg bbbbb000 + shr edx, 5; // edx = 00000000 00000000 00000000 00000bbb + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], ebx; + add edi, 4; + + shr eax, 16; // eax = 00000000 00000000 arrrrrgg gggbbbbb + mov edx, eax; // edx = 00000000 00000000 arrrrrgg gggbbbbb + mov ebx, 0x00000000; + and eax, 0x00008000; // eax = 00000000 00000000 a0000000 00000000 + jz transparent2; + mov ebx, 0xff000000; // ebx = aaaaaaaa 00000000 00000000 00000000 + + transparent2: + mov eax, edx; // eax = 00000000 00000000 arrrrrgg gggbbbbb + and edx, 0x00007c00; // edx = 00000000 00000000 0rrrrr00 00000000 + shl edx, 4; // edx = 00000000 00000rrr rr000000 00000000 + or ebx, edx; // ebx = aaaaaaaa 00000rrr rr000000 00000000 + shl edx, 5; // edx = 00000000 rrrrr000 00000000 00000000 + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr rr000000 00000000 + and ebx, 0xffff0000; // ebx = aaaaaaaa rrrrrrrr 00000000 00000000 + mov edx, eax; + and edx, 0x000003e0; // edx = 00000000 00000000 000000gg ggg00000 + shl edx, 1; // edx = 00000000 00000000 00000ggg gg000000 + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr 00000ggg gg000000 + shl edx, 5; // edx = 00000000 00000000 ggggg000 00000000 + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr gggggggg gg000000 + and ebx, 0xffffff00; // ebx = aaaaaaaa rrrrrrrr gggggggg 00000000 + mov edx, eax; + and edx, 0x0000001f; // edx = 00000000 00000000 00000000 000bbbbb + shl edx, 3; // edx = 00000000 00000000 00000000 bbbbb000 + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr gggggggg bbbbb000 + shr edx, 5; // edx = 00000000 00000000 00000000 00000bbb + or ebx, edx; // ebx = aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], ebx; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::ARGB4444_ARGB8888(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 1; + int i; + for (i = 0; i < siz; i++) { + *dest = ((*src & 0x0000f000) << 12) | + ((*src & 0x00000f00) << 8) | + ((*src & 0x000000f0) << 4) | + (*src & 0x0000000f); + *dest |= (*dest << 4); + dest++; + *dest = ((*src & 0xf0000000) | + ((*src & 0x0f000000) >> 4) | + ((*src & 0x00f00000) >> 8) | + ((*src & 0x000f0000) >> 12)); + *dest |= (*dest >> 4); + dest++; + src++; + } +#else + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // aaaa rrrr gggg bbbb + // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + mov edx, eax; + and eax, 0x0000ffff; + mov ebx, eax; // 00000000 00000000 aaaarrrr ggggbbbb + and ebx, 0x0000f000; // 00000000 00000000 aaaa0000 00000000 + shl ebx, 12; // 0000aaaa 00000000 00000000 00000000 + or eax, ebx; // 0000aaaa 00000000 aaaarrrr ggggbbbb + mov ebx, eax; + and ebx, 0x00000f00; // 00000000 00000000 0000rrrr 00000000 + shl ebx, 8; // 00000000 0000rrrr 00000000 00000000 + or eax, ebx; // 0000aaaa 0000rrrr aaaarrrr ggggbbbb + mov ebx, eax; + and ebx, 0x000000f0; // 00000000 00000000 00000000 gggg0000 + shl ebx, 4; // 00000000 00000000 0000gggg 00000000 + and eax, 0x0f0f000f; // 0000aaaa 0000rrrr 00000000 0000bbbb + or eax, ebx; // 0000aaaa 0000rrrr 0000gggg 0000bbbb + mov ebx, eax; + shl ebx, 4; // aaaa0000 rrrr0000 gggg0000 bbbb0000 + or eax, ebx; // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], eax; + add edi, 4; + + shr edx, 16; + mov ebx, edx; // 00000000 00000000 aaaarrrr ggggbbbb + and ebx, 0x0000f000; // 00000000 00000000 aaaa0000 00000000 + shl ebx, 12; // 0000aaaa 00000000 00000000 00000000 + or edx, ebx; // 0000aaaa 00000000 aaaarrrr ggggbbbb + mov ebx, edx; + and ebx, 0x00000f00; // 00000000 00000000 0000rrrr 00000000 + shl ebx, 8; // 00000000 0000rrrr 00000000 00000000 + or edx, ebx; // 0000aaaa 0000rrrr aaaarrrr ggggbbbb + mov ebx, edx; + and ebx, 0x000000f0; // 00000000 00000000 00000000 gggg0000 + shl ebx, 4; // 00000000 00000000 0000gggg 00000000 + and edx, 0x0f0f000f; // 0000aaaa 0000rrrr 00000000 0000bbbb + or edx, ebx; // 0000aaaa 0000rrrr 0000gggg 0000bbbb + mov ebx, edx; + shl ebx, 4; // aaaa0000 rrrr0000 gggg0000 bbbb0000 + or edx, ebx; // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], edx; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::RGB565_ARGB8888(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 1; + int i; + for (i = 0; i < siz; i++) { + *dest = (0xff000000 | + ((*src & 0x0000f800) << 8) | ((*src & 0x0000e000) << 3) | + ((*src & 0x000007e0) << 5) | ((*src & 0x00000600) >> 1) | + ((*src & 0x0000001f) << 3) | ((*src & 0x0000001c) >> 2)); + dest++; + *dest = (0xff000000 | + ((*src & 0xf8000000) >> 8) | ((*src & 0xe0000000) >> 13) | + ((*src & 0x07e00000) >> 11) | ((*src & 0x06000000) >> 17) | + ((*src & 0x001f0000) >> 13) | ((*src & 0x001c0000) >> 18)); + dest++; + src++; + } +#else + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // rrrr rggg gggb bbbb + // 11111111 rrrrrrrr gggggggg bbbbbbbb + mov edx, eax; + and eax, 0x0000ffff; + mov ebx, eax; // 00000000 00000000 rrrrrggg gggbbbbb + and ebx, 0x0000f800; // 00000000 00000000 rrrrr000 00000000 + shl ebx, 5; // 00000000 000rrrrr 00000000 00000000 + or eax, ebx; // 00000000 000rrrrr rrrrrggg gggbbbbb + mov ebx, eax; + and ebx, 0x000007e0; // 00000000 00000000 00000ggg ggg00000 + shl ebx, 5; // 00000000 00000000 gggggg00 00000000 + and eax, 0x001F001F; // 00000000 000rrrrr 00000000 000bbbbb + shl eax, 3; // 00000000 rrrrr000 00000000 bbbbb000 + or eax, ebx; // 00000000 rrrrr000 gggggg00 bbbbb000 + mov ebx, eax; + shr ebx, 5; // 00000000 00000rrr rr000ggg ggg00bbb + and ebx, 0x00070007; // 00000000 00000rrr 00000000 00000bbb + or eax, ebx; // 00000000 rrrrrrrr gggggg00 bbbbbbbb + mov ebx, eax; + shr ebx, 6; + and ebx, 0x00000300; // 00000000 00000000 000000gg 00000000 + or eax, ebx // 00000000 rrrrrrrr gggggggg bbbbbbbb + or eax, 0xff000000; // 11111111 rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], eax; + add edi, 4; + + shr edx, 16; + mov eax, edx; // 00000000 00000000 rrrrrggg gggbbbbb + and eax, 0x0000ffff; + mov ebx, eax; // 00000000 00000000 rrrrrggg gggbbbbb + and ebx, 0x0000f800; // 00000000 00000000 rrrrr000 00000000 + shl ebx, 5; // 00000000 000rrrrr 00000000 00000000 + or eax, ebx; // 00000000 000rrrrr rrrrrggg gggbbbbb + mov ebx, eax; + and ebx, 0x000007e0; // 00000000 00000000 00000ggg ggg00000 + shl ebx, 5; // 00000000 00000000 gggggg00 00000000 + and eax, 0x001F001F; // 00000000 000rrrrr 00000000 000bbbbb + shl eax, 3; // 00000000 rrrrr000 00000000 bbbbb000 + or eax, ebx; // 00000000 rrrrr000 gggggg00 bbbbb000 + mov ebx, eax; + shr ebx, 5; // 00000000 00000rrr rr000ggg ggg00bbb + and ebx, 0x00070007; // 00000000 00000rrr 00000000 00000bbb + or eax, ebx; // 00000000 rrrrrrrr gggggg00 bbbbbbbb + mov ebx, eax; + shr ebx, 6; + and ebx, 0x00000300; // 00000000 00000000 000000gg 00000000 + or eax, ebx // 00000000 rrrrrrrr gggggggg bbbbbbbb + or eax, 0xff000000; // 11111111 rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], eax; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::A8_ARGB8888(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 2; + int i; + for (i = 0; i < siz; i++) { + *dest = (*src & 0x000000ff); + *dest |= (*dest << 8); + *dest |= (*dest << 16); + dest++; + *dest = (*src & 0x0000ff00); + *dest |= (*dest >> 8); + *dest |= (*dest << 16); + dest++; + *dest = (*src & 0x00ff0000); + *dest |= (*dest << 8); + *dest |= (*dest >> 16); + dest++; + *dest = (*src & 0xff000000); + *dest |= (*dest >> 8); + *dest |= (*dest >> 16); + dest++; + src++; + } +#else + int siz = (width * height) >> 2; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // aaaaaaaa + // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + mov edx, eax; + and eax, 0x000000ff; + mov ebx, eax; // 00000000 00000000 00000000 aaaaaaaa + shl ebx, 8; // 00000000 00000000 aaaaaaaa 00000000 + or eax, ebx; // 00000000 00000000 aaaaaaaa aaaaaaaa + mov ebx, eax; + shl ebx, 16; // aaaaaaaa aaaaaaaa 00000000 00000000 + or eax, ebx; // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0x0000ff00; + mov ebx, eax; // 00000000 00000000 aaaaaaaa 00000000 + shr ebx, 8; // 00000000 00000000 00000000 aaaaaaaa + or eax, ebx; // 00000000 00000000 aaaaaaaa aaaaaaaa + mov ebx, eax; + shl ebx, 16; // aaaaaaaa aaaaaaaa 00000000 00000000 + or eax, ebx; // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0x00ff0000; + mov ebx, eax; // 00000000 aaaaaaaa 00000000 00000000 + shl ebx, 8; // aaaaaaaa 00000000 00000000 00000000 + or eax, ebx; // aaaaaaaa aaaaaaaa 00000000 00000000 + mov ebx, eax; + shr ebx, 16; // 00000000 00000000 aaaaaaaa aaaaaaaa + or eax, ebx; // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0xff000000; + mov ebx, eax; // aaaaaaaa 00000000 00000000 00000000 + shr ebx, 8; // 00000000 aaaaaaaa 00000000 00000000 + or eax, ebx; // aaaaaaaa aaaaaaaa 00000000 00000000 + mov ebx, eax; + shr ebx, 16; // 00000000 00000000 aaaaaaaa aaaaaaaa + or eax, ebx; // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb + + mov dword ptr [edi], eax; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::AI44_ARGB8888(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 2; + int i; + for (i = 0; i < siz; i++) { + *dest = (*src & 0x0000000f); + *dest |= ((*dest << 8) | (*dest << 16)); + *dest |= ((*src & 0x000000f0) << 20); + *dest |= (*dest << 4); + dest++; + *dest = (*src & 0x00000f00); + *dest |= ((*dest << 8) | (*dest >> 8)); + *dest |= ((*src & 0x0000f000) << 12); + *dest |= (*dest << 4); + dest++; + *dest = (*src & 0x000f0000); + *dest |= ((*dest >> 8) | (*dest >> 16)); + *dest |= ((*src & 0x00f00000) << 4); + *dest |= (*dest << 4); + dest++; + *dest = ((*src & 0x0f000000) >> 4); + *dest |= ((*dest >> 8) | (*dest >> 16)); + *dest |= (*src & 0xf0000000); + *dest |= (*dest >> 4); + dest++; + src++; + } +#else + int siz = (width * height) >> 2; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // aaaaiiii + // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii + mov edx, eax; + and eax, 0x000000f0; // 00000000 00000000 00000000 aaaa0000 + mov ebx, edx; + shl eax, 20; // 0000aaaa 00000000 00000000 00000000 + and ebx, 0x0000000f; // 00000000 00000000 00000000 0000iiii + or eax, ebx; // 0000aaaa 00000000 00000000 0000iiii + shl ebx, 8; // 00000000 00000000 0000iiii 00000000 + or eax, ebx; // 0000aaaa 00000000 0000iiii 0000iiii + shl ebx, 8; // 00000000 0000iiii 00000000 00000000 + or eax, ebx; // 0000aaaa 0000iiii 0000iiii 0000iiii + mov ebx, eax; + shl ebx, 4; // aaaa0000 iiii0000 iiii0000 iiii0000 + or eax, ebx; // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0x0000f000; // 00000000 00000000 aaaa0000 00000000 + mov ebx, edx; + shl eax, 12; // 0000aaaa 00000000 00000000 00000000 + and ebx, 0x00000f00; // 00000000 00000000 0000iiii 00000000 + or eax, ebx; // 0000aaaa 00000000 0000iiii 00000000 + shr ebx, 8; // 00000000 00000000 00000000 0000iiii + or eax, ebx; // 0000aaaa 00000000 0000iiii 0000iiii + shl ebx, 16; // 00000000 0000iiii 00000000 00000000 + or eax, ebx; // 0000aaaa 0000iiii 0000iiii 0000iiii + mov ebx, eax; + shl ebx, 4; // aaaa0000 iiii0000 iiii0000 iiii0000 + or eax, ebx; // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0x00f00000; // 00000000 aaaa0000 00000000 00000000 + mov ebx, edx; + shl eax, 4; // 0000aaaa 00000000 00000000 00000000 + and ebx, 0x000f0000; // 00000000 0000iiii 00000000 00000000 + or eax, ebx; // 0000aaaa 0000iiii 00000000 00000000 + shr ebx, 8; // 00000000 00000000 0000iiii 00000000 + or eax, ebx; // 0000aaaa 0000iiii 0000iiii 00000000 + shr ebx, 8; // 00000000 00000000 00000000 0000iiii + or eax, ebx; // 0000aaaa 0000iiii 0000iiii 0000iiii + mov ebx, eax; + shl ebx, 4; // aaaa0000 iiii0000 iiii0000 iiii0000 + or eax, ebx; // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0xf0000000; // aaaa0000 00000000 00000000 00000000 + mov ebx, edx; + and ebx, 0x0f000000; // 0000iiii 00000000 00000000 00000000 + shr ebx, 4; // 00000000 iiii0000 00000000 00000000 + or eax, ebx; // aaaa0000 iiii0000 00000000 00000000 + shr ebx, 8; // 00000000 00000000 iiii0000 00000000 + or eax, ebx; // aaaa0000 iiii0000 iiii0000 00000000 + shr ebx, 8; // 00000000 00000000 00000000 iiii0000 + or eax, ebx; // aaaa0000 iiii0000 iiii0000 iiii0000 + mov ebx, eax; + shr ebx, 4; // 0000aaaa 0000iiii 0000iiii 0000iiii + or eax, ebx; // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii + + mov dword ptr [edi], eax; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::AI88_ARGB8888(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 1; + int i; + for (i = 0; i < siz; i++) { + *dest = (*src & 0x000000ff); + *dest |= ((*dest << 8) | (*dest << 16)); + *dest |= ((*src & 0x0000ff00) << 16); + dest++; + *dest = (*src & 0x00ff0000); + *dest |= ((*dest >> 8) | (*dest >> 16)); + *dest |= (*src & 0xff000000); + dest++; + src++; + } +#else + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // aaaaaaaa iiiiiiii + // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii + mov edx, eax; + and eax, 0x0000ffff; // 00000000 00000000 aaaaaaaa iiiiiiii + mov ebx, eax; // 00000000 00000000 aaaaaaaa iiiiiiii + shl eax, 16; // aaaaaaaa iiiiiiii 00000000 00000000 + and ebx, 0x000000ff; // 00000000 00000000 00000000 iiiiiiii + or eax, ebx; // aaaaaaaa iiiiiiii 00000000 iiiiiiii + shl ebx, 8; // 00000000 00000000 iiiiiiii 00000000 + or eax, ebx; // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0xffff0000; // aaaaaaaa iiiiiiii 00000000 00000000 + mov ebx, eax; // aaaaaaaa iiiiiiii 00000000 00000000 + and ebx, 0x00ff0000; // 00000000 iiiiiiii 00000000 00000000 + shr ebx, 8; // 00000000 00000000 iiiiiiii 00000000 + or eax, ebx; // aaaaaaaa iiiiiiii iiiiiiii 00000000 + shr ebx, 8; // 00000000 00000000 00000000 iiiiiiii + or eax, ebx; // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii + + mov dword ptr [edi], eax; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::ARGB8888_ARGB1555(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 1; + int i; + for (i = 0; i < siz; i++) { + *dest = ((*src & 0xff000000) ? 0x00008000 : 0x00000000); + *dest |= (((*src & 0x00f80000) >> 9) | + ((*src & 0x0000f800) >> 6) | + ((*src & 0x000000f8) >> 3)); + src++; + *dest |= ((*src & 0xff000000) ? 0x80000000 : 0x00000000); + *dest |= (((*src & 0x00f80000) << 7) | + ((*src & 0x0000f800) << 10) | + ((*src & 0x000000f8) << 13)); + src++; + dest++; + } +#else + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + +#if 1 + mov edx, eax; + and eax, 0xff000000; // aaaa0000 00000000 00000000 00000000 + jz transparent1; + mov eax, 0x00008000; // 00000000 00000000 a0000000 00000000 + + transparent1: + mov ebx, edx; + and ebx, 0x00f80000; // 00000000 rrrrr000 00000000 00000000 + shr ebx, 9; // 00000000 00000000 0rrrrr00 00000000 + or eax, ebx; // 00000000 00000000 arrrrr00 00000000 + mov ebx, edx; + and ebx, 0x0000f800; // 00000000 00000000 ggggg000 00000000 + shr ebx, 6; // 00000000 00000000 000000gg ggg00000 + or eax, ebx; // 00000000 00000000 arrrrrgg ggg00000 + and edx, 0x000000f8; // 00000000 00000000 00000000 bbbbb000 + shr edx, 3; // 00000000 00000000 00000000 000bbbbb + or edx, eax; // 00000000 00000000 arrrrrgg gggbbbbb + + mov eax, dword ptr [esi]; + add esi, 4; + + mov ebx, eax; + and eax, 0xff000000; // aaaa0000 00000000 00000000 00000000 + jz transparent2; + or edx, 0x80000000; // a0000000 00000000 arrrrrgg gggbbbbb + + transparent2: + mov eax, ebx; + and ebx, 0x00f80000; // 00000000 rrrrr000 00000000 00000000 + shl ebx, 7; // 0rrrrr00 00000000 00000000 00000000 + or edx, ebx; // arrrrr00 00000000 arrrrrgg gggbbbbb + mov ebx, eax; + and ebx, 0x0000f800; // 00000000 00000000 ggggg000 00000000 + shl ebx, 10; // 000000gg ggg00000 00000000 00000000 + or edx, ebx; // arrrrrgg ggg00000 arrrrrgg gggbbbbb + and eax, 0x000000f8; // 00000000 00000000 00000000 bbbbb000 + shl eax, 13; // 00000000 000bbbbb 00000000 00000000 + or edx, eax; // arrrrrgg gggbbbbb arrrrrgg gggbbbbb + + mov dword ptr [edi], edx; + add edi, 4; +#else + mov edx, eax; + and edx, 0x01000000; // 0000000a 00000000 00000000 00000000 + shr edx, 9; // 00000000 00000000 a0000000 00000000 + mov ebx, eax; + and ebx, 0x00f80000; // 00000000 rrrrr000 00000000 00000000 + shr ebx, 9; // 00000000 00000000 0rrrrr00 00000000 + or edx, ebx; // 00000000 00000000 arrrrr00 00000000 + mov ebx, eax; + and ebx, 0x0000f800; // 00000000 00000000 ggggg000 00000000 + shr ebx, 6; // 00000000 00000000 000000gg ggg00000 + or edx, ebx; // 00000000 00000000 arrrrrgg ggg00000 + and eax, 0x000000f8; // 00000000 00000000 00000000 bbbbb000 + shr eax, 3; // 00000000 00000000 00000000 000bbbbb + or edx, eax; // 00000000 00000000 arrrrrgg gggbbbbb + + mov eax, dword ptr [esi]; + add esi, 4; + + mov ebx, eax; + and ebx, 0x80000000; // a0000000 00000000 00000000 00000000 + or edx, ebx; // a0000000 00000000 arrrrrgg gggbbbbb + mov ebx, eax; + and ebx, 0x00f80000; // 00000000 rrrrr000 00000000 00000000 + shl ebx, 7; // 0rrrrr00 00000000 00000000 00000000 + or edx, ebx; // arrrrr00 00000000 arrrrrgg gggbbbbb + mov ebx, eax; + and ebx, 0x0000f800; // 00000000 00000000 ggggg000 00000000 + shl ebx, 10; // 000000gg ggg00000 00000000 00000000 + or edx, ebx; // arrrrrgg ggg00000 arrrrrgg gggbbbbb + and eax, 0x000000f8; // 00000000 00000000 00000000 bbbbb000 + shl eax, 13; // 00000000 000bbbbb 00000000 00000000 + or edx, eax; // arrrrrgg gggbbbbb arrrrrgg gggbbbbb + + mov dword ptr [edi], edx; + add edi, 4; +#endif + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::ARGB8888_ARGB4444(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 1; + int i; + for (i = 0; i < siz; i++) { + *dest = (((*src & 0xf0000000) >> 16) | + ((*src & 0x00f00000) >> 12) | + ((*src & 0x0000f000) >> 8) | + ((*src & 0x000000f0) >> 4)); + src++; + *dest |= ((*src & 0xf0000000) | + ((*src & 0x00f00000) << 4) | + ((*src & 0x0000f000) << 8) | + ((*src & 0x000000f0) << 12)); + src++; + dest++; + } +#else + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + mov edx, eax; + and edx, 0xf0000000; // aaaa0000 00000000 00000000 00000000 + shr edx, 16; // 00000000 00000000 aaaa0000 00000000 + mov ebx, eax; + and ebx, 0x00f00000; // 00000000 rrrr0000 00000000 00000000 + shr ebx, 12; // 00000000 00000000 0000rrrr 00000000 + or edx, ebx; // 00000000 00000000 aaaarrrr 00000000 + mov ebx, eax; + and ebx, 0x0000f000; // 00000000 00000000 gggg0000 00000000 + shr ebx, 8; // 00000000 00000000 00000000 gggg0000 + or edx, ebx; // 00000000 00000000 aaaarrrr gggg0000 + and eax, 0x000000f0; // 00000000 00000000 00000000 bbbb0000 + shr eax, 4; // 00000000 00000000 00000000 0000bbbb + or edx, eax; // 00000000 00000000 aaaarrrr ggggbbbb + + mov eax, dword ptr [esi]; + add esi, 4; + + mov ebx, eax; + and ebx, 0xf0000000; // aaaa0000 00000000 00000000 00000000 + or edx, ebx; // aaaa0000 00000000 aaaarrrr ggggbbbb + mov ebx, eax; + and ebx, 0x00f00000; // 00000000 rrrr0000 00000000 00000000 + shl ebx, 4; // 0000rrrr 00000000 00000000 00000000 + or edx, ebx; // aaaarrrr 00000000 aaaarrrr ggggbbbb + mov ebx, eax; + and ebx, 0x0000f000; // 00000000 00000000 gggg0000 00000000 + shl ebx, 8; // 00000000 gggg0000 00000000 00000000 + or edx, ebx; // aaaarrrr gggg0000 aaaarrrr ggggbbbb + and eax, 0x000000f0; // 00000000 00000000 00000000 bbbb0000 + shl eax, 12; // 00000000 0000bbbb 00000000 00000000 + or edx, eax; // arrrrrgg ggggbbbb aaaarrrr ggggbbbb + + mov dword ptr [edi], edx; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::ARGB8888_RGB565(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 1; + int i; + for (i = 0; i < siz; i++) { + *dest = (((*src & 0x000000f8) >> 3) | + ((*src & 0x0000fc00) >> 5) | + ((*src & 0x00f80000) >> 8)); + src++; + *dest |= (((*src & 0x000000f8) << 13) | + ((*src & 0x0000fc00) << 11) | + ((*src & 0x00f80000) << 8)); + src++; + dest++; + } +#else + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + mov edx, eax; + and edx, 0x000000F8; // 00000000 00000000 00000000 bbbbb000 + shr edx, 3; // 00000000 00000000 00000000 000bbbbb + mov ebx, eax; + and ebx, 0x0000FC00; // 00000000 00000000 gggggg00 00000000 + shr ebx, 5; // 00000000 00000000 00000ggg ggg00000 + or edx, ebx; // 00000000 00000000 00000ggg gggbbbbb + mov ebx, eax; + and ebx, 0x00F80000; // 00000000 rrrrr000 00000000 00000000 + shr ebx, 8; // 00000000 00000000 rrrrr000 00000000 + or edx, ebx; // 00000000 00000000 rrrrrggg gggbbbbb + + mov eax, dword ptr [esi]; + add esi, 4; + + mov ebx, eax; + and ebx, 0x000000F8; // 00000000 00000000 00000000 bbbbb000 + shl ebx, 13; // 00000000 000bbbbb 00000000 00000000 + or edx, ebx; // 00000000 000bbbbb rrrrrggg gggbbbbb + mov ebx, eax; + and ebx, 0x0000FC00; // 00000000 00000000 gggggg00 00000000 + shl ebx, 11; // 00000ggg ggg00000 00000000 00000000 + or edx, ebx; // 00000ggg gggbbbbb rrrrrggg gggbbbbb + mov ebx, eax; + and ebx, 0x00F80000; // 00000000 rrrrr000 00000000 00000000 + shl ebx, 8; // rrrrr000 00000000 00000000 00000000 + or edx, ebx; // rrrrrggg gggbbbbb rrrrrggg gggbbbbb + + mov dword ptr [edi], edx; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::ARGB8888_A8(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 2; + int i; + for (i = 0; i < siz; i++) { + *dest = (*src & 0x0000ff00) >> 8; + src++; + *dest |= (*src & 0x0000ff00); + src++; + *dest |= ((*src & 0x0000ff00) << 8); + src++; + *dest |= ((*src & 0x0000ff00) << 16); + src++; + dest++; + } +#else + int siz = (width * height) >> 2; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + +#if 0 + mov edx, eax; // we'll use A comp for every pixel + and edx, 0xFF000000; // aaaaaaaa 00000000 00000000 00000000 + shr edx, 24; // 00000000 00000000 00000000 aaaaaaaa + + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0xFF000000; // aaaaaaaa 00000000 00000000 00000000 + shr eax, 16; // 00000000 00000000 aaaaaaaa 00000000 + or edx, eax; // 00000000 00000000 aaaaaaaa aaaaaaaa + + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0xFF000000; // aaaaaaaa 00000000 00000000 00000000 + shr eax, 8; // 00000000 aaaaaaaa 00000000 00000000 + or edx, eax; // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa + + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0xFF000000; // aaaaaaaa 00000000 00000000 00000000 + or edx, eax; // aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa +#endif + +#if 1 + mov edx, eax; // we'll use G comp for every pixel + and edx, 0x0000FF00; // 00000000 00000000 aaaaaaaa 00000000 + shr edx, 8; // 00000000 00000000 00000000 aaaaaaaa + + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0x0000FF00; // 00000000 00000000 aaaaaaaa 00000000 + or edx, eax; // 00000000 00000000 aaaaaaaa aaaaaaaa + + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0x0000FF00; // 00000000 00000000 aaaaaaaa 00000000 + shl eax, 8; // 00000000 aaaaaaaa 00000000 00000000 + or edx, eax; // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa + + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0x0000FF00; // 00000000 00000000 aaaaaaaa 00000000 + shl eax, 16; // aaaaaaaa 00000000 00000000 00000000 + or edx, eax; // aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa +#endif + +#if 0 + mov edx, eax; + and edx, 0x000000FF; // 00000000 00000000 00000000 aaaaaaaa + + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0x0000FF00; // 00000000 00000000 aaaaaaaa 00000000 + or edx, eax; // 00000000 00000000 aaaaaaaa aaaaaaaa + + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0x00FF0000; // 00000000 aaaaaaaa 00000000 00000000 + or edx, eax; // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa + + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0xFF000000; // aaaaaaaa 00000000 00000000 00000000 + or edx, eax; // aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa +#endif + mov dword ptr [edi], edx; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::ARGB8888_AI44(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 2; + int i; + for (i = 0; i < siz; i++) { + *dest = (((*src & 0xf0000000) >> 24) | ((*src & 0x0000f000) >> 12)); + src++; + *dest |= (((*src & 0xf0000000) >> 16) | ((*src & 0x0000f000) >> 4)); + src++; + *dest |= (((*src & 0xf0000000) >> 8) | ((*src & 0x0000f000) << 4)); + src++; + *dest |= ((*src & 0xf0000000) | ((*src & 0x0000f000) << 12)); + src++; + dest++; + } +#else + int siz = (width * height) >> 2; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + mov edx, eax; // use A and G comps MSB + and edx, 0xF0000000; // aaaa0000 00000000 00000000 00000000 + mov ebx, eax; + shr edx, 24; // 00000000 00000000 00000000 aaaa0000 + and ebx, 0x0000F000; // 00000000 00000000 iiii0000 00000000 + shr ebx, 12; // 00000000 00000000 00000000 0000iiii + or edx, ebx; // 00000000 00000000 00000000 aaaaiiii + + mov eax, dword ptr [esi]; + add esi, 4; + + mov ebx, eax; + and eax, 0xF0000000; // aaaa0000 00000000 00000000 00000000 + shr eax, 16; // 00000000 00000000 aaaa0000 00000000 + and ebx, 0x0000F000; // 00000000 00000000 iiii0000 00000000 + shr ebx, 4; // 00000000 00000000 0000iiii 00000000 + or eax, ebx; // 00000000 00000000 aaaaiiii 00000000 + or edx, eax; // 00000000 00000000 aaaaiiii aaaaiiii + + mov eax, dword ptr [esi]; + add esi, 4; + + mov ebx, eax; + and eax, 0xF0000000; // aaaa0000 00000000 00000000 00000000 + shr eax, 8; // 00000000 aaaa0000 00000000 00000000 + and ebx, 0x0000F000; // 00000000 00000000 iiii0000 00000000 + shl ebx, 4; // 00000000 0000iiii 00000000 00000000 + or eax, ebx; // 00000000 aaaaiiii 00000000 00000000 + or edx, eax; // 00000000 aaaaiiii aaaaiiii aaaaiiii + + mov eax, dword ptr [esi]; + add esi, 4; + + mov ebx, eax; + and eax, 0xF0000000; // aaaa0000 00000000 00000000 00000000 + and ebx, 0x0000F000; // 00000000 00000000 iiii0000 00000000 + shl ebx, 12; // 0000iiii 00000000 00000000 00000000 + or eax, ebx; // aaaaiiii 00000000 00000000 00000000 + or edx, eax; // aaaaiiii aaaaiiii aaaaiiii aaaaiiii + + mov dword ptr [edi], edx; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +void +TxQuantize::ARGB8888_AI88(uint32* src, uint32* dest, int width, int height) +{ +#if 1 + int siz = (width * height) >> 1; + int i; + for (i = 0; i < siz; i++) { + *dest = (((*src & 0xff000000) >> 16) | ((*src & 0x0000ff00) >> 8)); + src++; + *dest |= ((*src & 0xff000000) | ((*src & 0x0000ff00) << 8)); + src++; + dest++; + } +#else + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + mov edx, eax; + and edx, 0xFF000000; // aaaaaaaa 00000000 00000000 00000000 + mov ebx, eax; + shr edx, 16; // 00000000 00000000 aaaaaaaa 00000000 + and ebx, 0x0000FF00; // 00000000 00000000 iiiiiiii 00000000 + shr ebx, 8; // 00000000 00000000 00000000 iiiiiiii + or edx, ebx; // 00000000 00000000 aaaaaaaa iiiiiiii + + mov eax, dword ptr [esi]; + add esi, 4; + + mov ebx, eax; + and eax, 0xFF000000; // aaaaaaaa 00000000 00000000 00000000 + and ebx, 0x0000FF00; // 00000000 00000000 iiiiiiii 00000000 + shl ebx, 8; // 00000000 iiiiiiii 00000000 00000000 + or eax, ebx; // aaaaaaaa iiiiiiii 00000000 00000000 + or edx, eax; // aaaaaaaa iiiiiiii aaaaaaaa iiiiiiii + + mov dword ptr [edi], edx; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +/* R.W. Floyd and L. Steinberg, An adaptive algorithm + * for spatial grey scale, Proceedings of the Society + * of Information Display 17, pp75-77, 1976 + */ +void +TxQuantize::ARGB8888_RGB565_ErrD(uint32* src, uint32* dst, int width, int height) +{ + /* Floyd-Steinberg error-diffusion halftoning */ + + int i, x, y; + int qr, qg, qb; /* quantized incoming values */ + int ir, ig, ib; /* incoming values */ + int t; + int *errR = new int[width]; + int *errG = new int[width]; + int *errB = new int[width]; + + uint16 *dest = (uint16 *)dst; + + for (i = 0; i < width; i++) errR[i] = errG[i] = errB[i] = 0; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + /* incoming pixel values */ + ir = ((*src >> 16) & 0xFF) * 10000; + ig = ((*src >> 8) & 0xFF) * 10000; + ib = ((*src ) & 0xFF) * 10000; + + if (x == 0) qr = qg = qb = 0; + + /* quantize pixel values. + * qr * 0.4375 is the error from the pixel to the left, + * errR is the error from the pixel to the top, top left, and top right */ + /* qr * 0.4375 is the error distribution to the EAST in + * the previous loop */ + ir += errR[x] + qr * 4375 / 10000; + ig += errG[x] + qg * 4375 / 10000; + ib += errB[x] + qb * 4375 / 10000; + + /* error distribution to the SOUTH-EAST in the previous loop + * can't calculate in the previous loop because it steps on + * the above quantization */ + errR[x] = qr * 625 / 10000; + errG[x] = qg * 625 / 10000; + errB[x] = qb * 625 / 10000; + + qr = ir; + qg = ig; + qb = ib; + + /* clamp */ + if (qr < 0) qr = 0; else if (qr > 2550000) qr = 2550000; + if (qg < 0) qg = 0; else if (qg > 2550000) qg = 2550000; + if (qb < 0) qb = 0; else if (qb > 2550000) qb = 2550000; + + /* convert to RGB565 */ + qr = qr * 0x1F / 2550000; + qg = qg * 0x3F / 2550000; + qb = qb * 0x1F / 2550000; + + /* this is the dithered pixel */ + t = (qr << 11) | (qg << 5) | qb; + + /* compute the errors */ + qr = ((qr << 3) | (qr >> 2)) * 10000; + qg = ((qg << 2) | (qg >> 4)) * 10000; + qb = ((qb << 3) | (qb >> 2)) * 10000; + qr = ir - qr; + qg = ig - qg; + qb = ib - qb; + + /* compute the error distributions */ + /* Floyd-Steinberg filter + * 7/16 (=0.4375) to the EAST + * 5/16 (=0.3125) to the SOUTH + * 1/16 (=0.0625) to the SOUTH-EAST + * 3/16 (=0.1875) to the SOUTH-WEST + * + * x 7/16 + * 3/16 5/16 1/16 + */ + /* SOUTH-WEST */ + if (x > 1) { + errR[x - 1] += qr * 1875 / 10000; + errG[x - 1] += qg * 1875 / 10000; + errB[x - 1] += qb * 1875 / 10000; + } + + /* SOUTH */ + errR[x] += qr * 3125 / 10000; + errG[x] += qg * 3125 / 10000; + errB[x] += qb * 3125 / 10000; + + *dest = (t & 0xFFFF); + + dest++; + src++; + } + } + + delete [] errR; + delete [] errG; + delete [] errB; +} + + +void +TxQuantize::ARGB8888_ARGB1555_ErrD(uint32* src, uint32* dst, int width, int height) +{ + /* Floyd-Steinberg error-diffusion halftoning */ + + int i, x, y; + int qr, qg, qb; /* quantized incoming values */ + int ir, ig, ib; /* incoming values */ + int t; + int *errR = new int[width]; + int *errG = new int[width]; + int *errB = new int[width]; + + uint16 *dest = (uint16 *)dst; + + for (i = 0; i < width; i++) errR[i] = errG[i] = errB[i] = 0; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + /* incoming pixel values */ + ir = ((*src >> 16) & 0xFF) * 10000; + ig = ((*src >> 8) & 0xFF) * 10000; + ib = ((*src ) & 0xFF) * 10000; + + if (x == 0) qr = qg = qb = 0; + + /* quantize pixel values. + * qr * 0.4375 is the error from the pixel to the left, + * errR is the error from the pixel to the top, top left, and top right */ + /* qr * 0.4375 is the error distribution to the EAST in + * the previous loop */ + ir += errR[x] + qr * 4375 / 10000; + ig += errG[x] + qg * 4375 / 10000; + ib += errB[x] + qb * 4375 / 10000; + + /* error distribution to the SOUTH-EAST of the previous loop. + * cannot calculate in the previous loop because it steps on + * the above quantization */ + errR[x] = qr * 625 / 10000; + errG[x] = qg * 625 / 10000; + errB[x] = qb * 625 / 10000; + + qr = ir; + qg = ig; + qb = ib; + + /* clamp */ + if (qr < 0) qr = 0; else if (qr > 2550000) qr = 2550000; + if (qg < 0) qg = 0; else if (qg > 2550000) qg = 2550000; + if (qb < 0) qb = 0; else if (qb > 2550000) qb = 2550000; + + /* convert to RGB555 */ + qr = qr * 0x1F / 2550000; + qg = qg * 0x1F / 2550000; + qb = qb * 0x1F / 2550000; + + /* this is the dithered pixel */ + t = (qr << 10) | (qg << 5) | qb; + t |= ((*src >> 24) ? 0x8000 : 0); + + /* compute the errors */ + qr = ((qr << 3) | (qr >> 2)) * 10000; + qg = ((qg << 3) | (qg >> 2)) * 10000; + qb = ((qb << 3) | (qb >> 2)) * 10000; + qr = ir - qr; + qg = ig - qg; + qb = ib - qb; + + /* compute the error distributions */ + /* Floyd-Steinberg filter + * 7/16 (=0.4375) to the EAST + * 5/16 (=0.3125) to the SOUTH + * 1/16 (=0.0625) to the SOUTH-EAST + * 3/16 (=0.1875) to the SOUTH-WEST + * + * x 7/16 + * 3/16 5/16 1/16 + */ + /* SOUTH-WEST */ + if (x > 1) { + errR[x - 1] += qr * 1875 / 10000; + errG[x - 1] += qg * 1875 / 10000; + errB[x - 1] += qb * 1875 / 10000; + } + + /* SOUTH */ + errR[x] += qr * 3125 / 10000; + errG[x] += qg * 3125 / 10000; + errB[x] += qb * 3125 / 10000; + + *dest = (t & 0xFFFF); + + dest++; + src++; + } + } + + delete [] errR; + delete [] errG; + delete [] errB; +} + +void +TxQuantize::ARGB8888_ARGB4444_ErrD(uint32* src, uint32* dst, int width, int height) +{ + /* Floyd-Steinberg error-diffusion halftoning */ + + /* NOTE: alpha dithering looks better for alpha gradients, but are prone + * to producing noisy speckles for constant or step level alpha. Output + * results should always be checked. + */ + boolean ditherAlpha = 0; + + int i, x, y; + int qr, qg, qb, qa; /* quantized incoming values */ + int ir, ig, ib, ia; /* incoming values */ + int t; + int *errR = new int[width]; + int *errG = new int[width]; + int *errB = new int[width]; + int *errA = new int[width]; + + uint16 *dest = (uint16 *)dst; + + for (i = 0; i < width; i++) errR[i] = errG[i] = errB[i] = errA[i] = 0; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + /* incoming pixel values */ + ir = ((*src >> 16) & 0xFF) * 10000; + ig = ((*src >> 8) & 0xFF) * 10000; + ib = ((*src ) & 0xFF) * 10000; + ia = ((*src >> 24) & 0xFF) * 10000; + + if (x == 0) qr = qg = qb = qa = 0; + + /* quantize pixel values. + * qr * 0.4375 is the error from the pixel to the left, + * errR is the error from the pixel to the top, top left, and top right */ + /* qr * 0.4375 is the error distribution to the EAST in + * the previous loop */ + ir += errR[x] + qr * 4375 / 10000; + ig += errG[x] + qg * 4375 / 10000; + ib += errB[x] + qb * 4375 / 10000; + ia += errA[x] + qa * 4375 / 10000; + + /* error distribution to the SOUTH-EAST of the previous loop. + * cannot calculate in the previous loop because it steps on + * the above quantization */ + errR[x] = qr * 625 / 10000; + errG[x] = qg * 625 / 10000; + errB[x] = qb * 625 / 10000; + errA[x] = qa * 625 / 10000; + + qr = ir; + qg = ig; + qb = ib; + qa = ia; + + /* clamp */ + if (qr < 0) qr = 0; else if (qr > 2550000) qr = 2550000; + if (qg < 0) qg = 0; else if (qg > 2550000) qg = 2550000; + if (qb < 0) qb = 0; else if (qb > 2550000) qb = 2550000; + if (qa < 0) qa = 0; else if (qa > 2550000) qa = 2550000; + + /* convert to RGB444 */ + qr = qr * 0xF / 2550000; + qg = qg * 0xF / 2550000; + qb = qb * 0xF / 2550000; + qa = qa * 0xF / 2550000; + + /* this is the value to be returned */ + if (ditherAlpha) { + t = (qa << 12) | (qr << 8) | (qg << 4) | qb; + } else { + t = (qr << 8) | (qg << 4) | qb; + t |= (*src >> 16) & 0xF000; + } + + /* compute the errors */ + qr = ((qr << 4) | qr) * 10000; + qg = ((qg << 4) | qg) * 10000; + qb = ((qb << 4) | qb) * 10000; + qa = ((qa << 4) | qa) * 10000; + qr = ir - qr; + qg = ig - qg; + qb = ib - qb; + qa = ia - qa; + + /* compute the error distributions */ + /* Floyd-Steinberg filter + * 7/16 (=0.4375) to the EAST + * 5/16 (=0.3125) to the SOUTH + * 1/16 (=0.0625) to the SOUTH-EAST + * 3/16 (=0.1875) to the SOUTH-WEST + * + * x 7/16 + * 3/16 5/16 1/16 + */ + /* SOUTH-WEST */ + if (x > 1) { + errR[x - 1] += qr * 1875 / 10000; + errG[x - 1] += qg * 1875 / 10000; + errB[x - 1] += qb * 1875 / 10000; + errA[x - 1] += qa * 1875 / 10000; + } + + /* SOUTH */ + errR[x] += qr * 3125 / 10000; + errG[x] += qg * 3125 / 10000; + errB[x] += qb * 3125 / 10000; + errA[x] += qa * 3125 / 10000; + + *dest = (t & 0xFFFF); + + dest++; + src++; + } + } + + delete [] errR; + delete [] errG; + delete [] errB; + delete [] errA; +} + +void +TxQuantize::ARGB8888_AI44_ErrD(uint32* src, uint32* dst, int width, int height) +{ + /* Floyd-Steinberg error-diffusion halftoning */ + + /* NOTE: alpha dithering looks better for alpha gradients, but are prone + * to producing noisy speckles for constant or step level alpha. Output + * results should always be checked. + */ + boolean ditherAlpha = 0; + + int i, x, y; + int qi, qa; /* quantized incoming values */ + int ii, ia; /* incoming values */ + int t; + int *errI = new int[width]; + int *errA = new int[width]; + + uint8 *dest = (uint8 *)dst; + + for (i = 0; i < width; i++) errI[i] = errA[i] = 0; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + /* 3dfx style Intensity = R * 0.299 + G * 0.587 + B * 0.114 */ + ii = ((*src >> 16) & 0xFF) * 2990 + + ((*src >> 8) & 0xFF) * 5870 + + ((*src ) & 0xFF) * 1140; + ia = ((*src >> 24) & 0xFF) * 10000; + + if (x == 0) qi = qa = 0; + + /* quantize pixel values. + * qi * 0.4375 is the error from the pixel to the left, + * errI is the error from the pixel to the top, top left, and top right */ + /* qi * 0.4375 is the error distrtibution to the EAST in + * the previous loop */ + ii += errI[x] + qi * 4375 / 10000; + ia += errA[x] + qa * 4375 / 10000; + + /* error distribution to the SOUTH-EAST in the previous loop. + * cannot calculate in the previous loop because it steps on + * the above quantization */ + errI[x] = qi * 625 / 10000; + errA[x] = qa * 625 / 10000; + + qi = ii; + qa = ia; + + /* clamp */ + if (qi < 0) qi = 0; else if (qi > 2550000) qi = 2550000; + if (qa < 0) qa = 0; else if (qa > 2550000) qa = 2550000; + + /* convert to I4 */ + qi = qi * 0xF / 2550000; + qa = qa * 0xF / 2550000; + + /* this is the value to be returned */ + if (ditherAlpha) { + t = (qa << 4) | qi; + } else { + t = qi; + t |= ((*src >> 24) & 0xF0); + } + + /* compute the errors */ + qi = ((qi << 4) | qi) * 10000; + qa = ((qa << 4) | qa) * 10000; + qi = ii - qi; + qa = ia - qa; + + /* compute the error distributions */ + /* Floyd-Steinberg filter + * 7/16 (=0.4375) to the EAST + * 5/16 (=0.3125) to the SOUTH + * 1/16 (=0.0625) to the SOUTH-EAST + * 3/16 (=0.1875) to the SOUTH-WEST + * + * x 7/16 + * 3/16 5/16 1/16 + */ + /* SOUTH-WEST */ + if (x > 1) { + errI[x - 1] += qi * 1875 / 10000; + errA[x - 1] += qa * 1875 / 10000; + } + + /* SOUTH */ + errI[x] += qi * 3125 / 10000; + errA[x] += qa * 3125 / 10000; + + *dest = t & 0xFF; + + dest++; + src++; + } + } + + delete [] errI; + delete [] errA; +} + +void +TxQuantize::ARGB8888_AI88_Slow(uint32* src, uint32* dst, int width, int height) +{ + int x, y; + uint16 *dest = (uint16 *)dst; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { +#if 1 + /* libpng style grayscale conversion. + * Reduce RGB files to grayscale with or without alpha + * using the equation given in Poynton's ColorFAQ at + * + * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + */ + *dest = (((int)((((*src >> 16) & 0xFF) * 6969 + + ((*src >> 8) & 0xFF) * 23434 + + ((*src ) & 0xFF) * 2365) / 32768) & 0xFF) | + (uint16)((*src >> 16) & 0xFF00)); +#else + /* 3dfx style Intensity = R * 0.299 + G * 0.587 + B * 0.114 + * this is same as the standard NTSC gray scale conversion. */ + *dest = (((int)((((*src >> 16) & 0xFF) * 299 + + ((*src >> 8) & 0xFF) * 587 + + ((*src ) & 0xFF) * 114) / 1000) & 0xFF) | + (uint16)((*src >> 16) & 0xFF00)); +#endif + dest++; + src++; + } + } +} + +void +TxQuantize::ARGB8888_I8_Slow(uint32* src, uint32* dst, int width, int height) +{ + int x, y; + uint8 *dest = (uint8 *)dst; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { +#if 1 + /* libpng style Intensity = (6969 * R + 23434 * G + 2365 * B)/32768 */ + *dest = (int)((((*src >> 16) & 0xFF) * 6969 + + ((*src >> 8) & 0xFF) * 23434 + + ((*src ) & 0xFF) * 2365) / 32768) & 0xFF; +#else + /* 3dfx style Intensity = R * 0.299 + G * 0.587 + B * 0.114 + * this is same as the standard NTSC gray scale conversion. */ + *dest = (int)((((*src >>16) & 0xFF) * 299 + + ((*src >> 8) & 0xFF) * 587 + + ((*src ) & 0xFF) * 114) / 1000) & 0xFF; +#endif + dest++; + src++; + } + } +} + +void +TxQuantize::P8_16BPP(uint32* src, uint32* dest, int width, int height, uint32* palette) +{ + /* passed in palette is RGBA5551 format */ +#if 1 + int i; + int size = width * height; + for (i = 0; i < size; i++) { + ((uint16*)dest)[i] = ((uint16*)palette)[(int)(((uint8*)src)[i])]; + ((uint16*)dest)[i] = ((((uint16*)dest)[i] << 15) | (((uint16*)dest)[i] >> 1)); + } +#else + + /* not finished yet... */ + + int siz = (width * height) >> 2; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + mov edx, dword ptr [palette]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +#endif +} + +boolean +TxQuantize::quantize(uint8* src, uint8* dest, int width, int height, uint16 srcformat, uint16 destformat, boolean fastQuantizer) +{ + typedef void (TxQuantize::*quantizerFunc)(uint32* src, uint32* dest, int width, int height); + quantizerFunc quantizer; + int bpp_shift = 0; + + if (destformat == GR_TEXFMT_ARGB_8888) { + switch (srcformat) { + case GR_TEXFMT_ARGB_1555: + quantizer = &TxQuantize::ARGB1555_ARGB8888; + bpp_shift = 1; + break; + case GR_TEXFMT_ARGB_4444: + quantizer = &TxQuantize::ARGB4444_ARGB8888; + bpp_shift = 1; + break; + case GR_TEXFMT_RGB_565: + quantizer = &TxQuantize::RGB565_ARGB8888; + bpp_shift = 1; + break; + case GR_TEXFMT_ALPHA_8: + quantizer = &TxQuantize::A8_ARGB8888; + bpp_shift = 2; + break; + case GR_TEXFMT_ALPHA_INTENSITY_44: + quantizer = &TxQuantize::AI44_ARGB8888; + bpp_shift = 2; + break; + case GR_TEXFMT_ALPHA_INTENSITY_88: + quantizer = &TxQuantize::AI88_ARGB8888; + bpp_shift = 1; + break; + default: + return 0; + } + + unsigned int numcore = _numcore; + unsigned int blkrow = 0; + while (numcore > 1 && blkrow == 0) { + blkrow = (height >> 2) / numcore; + numcore--; + } + if (blkrow > 0 && numcore > 1) { + boost::thread *thrd[MAX_NUMCORE]; + unsigned int i; + int blkheight = blkrow << 2; + unsigned int srcStride = (width * blkheight) << (2 - bpp_shift); + unsigned int destStride = srcStride << bpp_shift; + for (i = 0; i < numcore - 1; i++) { + thrd[i] = new boost::thread(boost::bind(quantizer, + this, + (uint32*)src, + (uint32*)dest, + width, + blkheight)); + src += srcStride; + dest += destStride; + } + thrd[i] = new boost::thread(boost::bind(quantizer, + this, + (uint32*)src, + (uint32*)dest, + width, + height - blkheight * i)); + for (i = 0; i < numcore; i++) { + thrd[i]->join(); + delete thrd[i]; + } + } else { + (*this.*quantizer)((uint32*)src, (uint32*)dest, width, height); + } + + } else if (srcformat == GR_TEXFMT_ARGB_8888) { + switch (destformat) { + case GR_TEXFMT_ARGB_1555: + quantizer = fastQuantizer ? &TxQuantize::ARGB8888_ARGB1555 : &TxQuantize::ARGB8888_ARGB1555_ErrD; + bpp_shift = 1; + break; + case GR_TEXFMT_ARGB_4444: + quantizer = fastQuantizer ? &TxQuantize::ARGB8888_ARGB4444 : &TxQuantize::ARGB8888_ARGB4444_ErrD; + bpp_shift = 1; + break; + case GR_TEXFMT_RGB_565: + quantizer = fastQuantizer ? &TxQuantize::ARGB8888_RGB565 : &TxQuantize::ARGB8888_RGB565_ErrD; + bpp_shift = 1; + break; + case GR_TEXFMT_ALPHA_8: + case GR_TEXFMT_INTENSITY_8: + quantizer = fastQuantizer ? &TxQuantize::ARGB8888_A8 : &TxQuantize::ARGB8888_I8_Slow; + bpp_shift = 2; + break; + case GR_TEXFMT_ALPHA_INTENSITY_44: + quantizer = fastQuantizer ? &TxQuantize::ARGB8888_AI44 : &TxQuantize::ARGB8888_AI44_ErrD; + bpp_shift = 2; + break; + case GR_TEXFMT_ALPHA_INTENSITY_88: + quantizer = fastQuantizer ? &TxQuantize::ARGB8888_AI88 : &TxQuantize::ARGB8888_AI88_Slow; + bpp_shift = 1; + break; + default: + return 0; + } + + unsigned int numcore = _numcore; + unsigned int blkrow = 0; + while (numcore > 1 && blkrow == 0) { + blkrow = (height >> 2) / numcore; + numcore--; + } + if (blkrow > 0 && numcore > 1) { + boost::thread *thrd[MAX_NUMCORE]; + unsigned int i; + int blkheight = blkrow << 2; + unsigned int srcStride = (width * blkheight) << 2; + unsigned int destStride = srcStride >> bpp_shift; + for (i = 0; i < numcore - 1; i++) { + thrd[i] = new boost::thread(boost::bind(quantizer, + this, + (uint32*)src, + (uint32*)dest, + width, + blkheight)); + src += srcStride; + dest += destStride; + } + thrd[i] = new boost::thread(boost::bind(quantizer, + this, + (uint32*)src, + (uint32*)dest, + width, + height - blkheight * i)); + for (i = 0; i < numcore; i++) { + thrd[i]->join(); + delete thrd[i]; + } + } else { + (*this.*quantizer)((uint32*)src, (uint32*)dest, width, height); + } + + } else { + return 0; + } + + return 1; +} + +boolean +TxQuantize::FXT1(uint8 *src, uint8 *dest, + int srcwidth, int srcheight, uint16 srcformat, + int *destwidth, int *destheight, uint16 *destformat) +{ + /* + * NOTE: src must be in ARGB8888 format, srcformat describes + * the closest 16bbp representation of src. + * + * NOTE: I have modified the dxtn library to use ARGB format + * which originaly was ABGR format. + */ + + boolean bRet = 0; + + if (_tx_compress_fxt1 && + srcwidth >= 8 && srcheight >= 4) { + /* compress to fxt1 + * width and height must be larger than 8 and 4 respectively + */ + int dstRowStride = ((srcwidth + 7) & ~7) << 1; + int srcRowStride = (srcwidth << 2); + + unsigned int numcore = _numcore; + unsigned int blkrow = 0; + while (numcore > 1 && blkrow == 0) { + blkrow = (srcheight >> 2) / numcore; + numcore--; + } + if (blkrow > 0 && numcore > 1) { + boost::thread *thrd[MAX_NUMCORE]; + unsigned int i; + int blkheight = blkrow << 2; + unsigned int srcStride = (srcwidth * blkheight) << 2; + unsigned int destStride = dstRowStride * blkrow; + for (i = 0; i < numcore - 1; i++) { + thrd[i] = new boost::thread(boost::bind(_tx_compress_fxt1, + srcwidth, + blkheight, + 4, + src, + srcRowStride, + dest, + dstRowStride)); + src += srcStride; + dest += destStride; + } + thrd[i] = new boost::thread(boost::bind(_tx_compress_fxt1, + srcwidth, + srcheight - blkheight * i, + 4, + src, + srcRowStride, + dest, + dstRowStride)); + for (i = 0; i < numcore; i++) { + thrd[i]->join(); + delete thrd[i]; + } + } else { + (*_tx_compress_fxt1)(srcwidth, /* width */ + srcheight, /* height */ + 4, /* comps: ARGB8888=4, RGB888=3 */ + src, /* source */ + srcRowStride, /* width*comps */ + dest, /* destination */ + dstRowStride); /* 16 bytes per 8x4 texel */ + } + + /* dxtn adjusts width and height to M8 and M4 respectively by replication */ + *destwidth = (srcwidth + 7) & ~7; + *destheight = (srcheight + 3) & ~3; + *destformat = GR_TEXFMT_ARGB_CMP_FXT1; + + bRet = 1; + } + + return bRet; +} + +boolean +TxQuantize::DXTn(uint8 *src, uint8 *dest, + int srcwidth, int srcheight, uint16 srcformat, + int *destwidth, int *destheight, uint16 *destformat) +{ + /* + * NOTE: src must be in ARGB8888 format, srcformat describes + * the closest 16bbp representation of src. + * + * NOTE: I have modified the dxtn library to use ARGB format + * which originaly was ABGR format. + */ + + boolean bRet = 0; + + if (_tx_compress_dxtn && + srcwidth >= 4 && srcheight >= 4) { + /* compress to dxtn + * width and height must be larger than 4 + */ + + /* skip formats that DXTn won't help in size. */ + if (srcformat == GR_TEXFMT_ALPHA_8 || + srcformat == GR_TEXFMT_ALPHA_INTENSITY_44) { + ; /* shutup compiler */ + } else { + int dstRowStride = ((srcwidth + 3) & ~3) << 2; + int compression = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + + *destformat = GR_TEXFMT_ARGB_CMP_DXT5; + +#if !GLIDE64_DXTN + /* okay... we are going to disable DXT1 with 1bit alpha + * for Glide64. some textures have all 0 alpha values. + * see "N64 Kobe Bryant in NBA Courtside" + */ + if (srcformat == GR_TEXFMT_ARGB_1555) { + dstRowStride >>= 1; + compression = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + *destformat = GR_TEXFMT_ARGB_CMP_DXT1; + } else +#endif + if (srcformat == GR_TEXFMT_RGB_565 || + srcformat == GR_TEXFMT_INTENSITY_8) { + dstRowStride >>= 1; + compression = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + *destformat = GR_TEXFMT_ARGB_CMP_DXT1; + } + + unsigned int numcore = _numcore; + unsigned int blkrow = 0; + while (numcore > 1 && blkrow == 0) { + blkrow = (srcheight >> 2) / numcore; + numcore--; + } + if (blkrow > 0 && numcore > 1) { + boost::thread *thrd[MAX_NUMCORE]; + unsigned int i; + int blkheight = blkrow << 2; + unsigned int srcStride = (srcwidth * blkheight) << 2; + unsigned int destStride = dstRowStride * blkrow; + for (i = 0; i < numcore - 1; i++) { + thrd[i] = new boost::thread(boost::bind(_tx_compress_dxtn, + 4, + srcwidth, + blkheight, + src, + compression, + dest, + dstRowStride)); + src += srcStride; + dest += destStride; + } + thrd[i] = new boost::thread(boost::bind(_tx_compress_dxtn, + 4, + srcwidth, + srcheight - blkheight * i, + src, + compression, + dest, + dstRowStride)); + for (i = 0; i < numcore; i++) { + thrd[i]->join(); + delete thrd[i]; + } + } else { + (*_tx_compress_dxtn)(4, /* comps: ARGB8888=4, RGB888=3 */ + srcwidth, /* width */ + srcheight, /* height */ + src, /* source */ + compression, /* format */ + dest, /* destination */ + dstRowStride); /* DXT1 = 8 bytes per 4x4 texel + * others = 16 bytes per 4x4 texel */ + } + + /* dxtn adjusts width and height to M4 by replication */ + *destwidth = (srcwidth + 3) & ~3; + *destheight = (srcheight + 3) & ~3; + + bRet = 1; + } + } + + return bRet; +} + +boolean +TxQuantize::compress(uint8 *src, uint8 *dest, + int srcwidth, int srcheight, uint16 srcformat, + int *destwidth, int *destheight, uint16 *destformat, + int compressionType) +{ + boolean bRet = 0; + + switch (compressionType) { + case FXT1_COMPRESSION: + bRet = FXT1(src, dest, + srcwidth, srcheight, srcformat, + destwidth, destheight, destformat); + break; + case S3TC_COMPRESSION: + bRet = DXTn(src, dest, + srcwidth, srcheight, srcformat, + destwidth, destheight, destformat); + break; + case NCC_COMPRESSION: + /* TODO: narrow channel compression */ + ; + } + + return bRet; +} + +#if 0 /* unused */ +void +TxQuantize::I8_ARGB8888(uint32* src, uint32* dest, int width, int height) +{ + int siz = (width * height) >> 2; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // aaaaaaaa + // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa + mov edx, eax; + and eax, 0x000000ff; + mov ebx, eax; // 00000000 00000000 00000000 aaaaaaaa + shl ebx, 8; // 00000000 00000000 aaaaaaaa 00000000 + or eax, ebx; // 00000000 00000000 aaaaaaaa aaaaaaaa + shl ebx, 8; // 00000000 aaaaaaaa 00000000 00000000 + or eax, ebx; // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa + or eax, 0xff000000; // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0x0000ff00; + mov ebx, eax; // 00000000 00000000 aaaaaaaa 00000000 + shr ebx, 8; // 00000000 00000000 00000000 aaaaaaaa + or eax, ebx; // 00000000 00000000 aaaaaaaa aaaaaaaa + shl ebx, 16; // 00000000 aaaaaaaa 00000000 00000000 + or eax, ebx; // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa + or eax, 0xff000000; // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0x00ff0000; + mov ebx, eax; // 00000000 aaaaaaaa 00000000 00000000 + shr ebx, 8; // 00000000 00000000 aaaaaaaa 00000000 + or eax, ebx; // 00000000 aaaaaaaa aaaaaaaa 00000000 + shr ebx, 8; // 00000000 00000000 00000000 aaaaaaaa + or eax, ebx; // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa + or eax, 0xff000000; // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa + + mov dword ptr [edi], eax; + add edi, 4; + + mov eax, edx; + and eax, 0xff000000; + mov ebx, eax; // aaaaaaaa 00000000 00000000 00000000 + shr ebx, 8; // 00000000 aaaaaaaa 00000000 00000000 + or eax, ebx; // aaaaaaaa aaaaaaaa 00000000 00000000 + shr ebx, 8; // 00000000 00000000 aaaaaaaa 00000000 + or eax, ebx; // aaaaaaaa aaaaaaaa aaaaaaaa 00000000 + shr eax, 8; // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa + or eax, 0xff000000; // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa + + mov dword ptr [edi], eax; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +} + +void +TxQuantize::ARGB8888_I8(uint32* src, uint32* dest, int width, int height) +{ + ARGB8888_A8(src, dest, width, height); +} + +void +TxQuantize::ARGB1555_ABGR8888(uint32* src, uint32* dest, int width, int height) +{ + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // arrr rrgg gggb bbbb + // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr + mov edx, eax; // edx = arrrrrgg gggbbbbb arrrrrgg gggbbbbb + and ebx, 0x00000000; + and eax, 0x00008000; // eax = 00000000 00000000 a0000000 00000000 + jz transparent1; + or ebx, 0xff000000; // ebx = aaaaaaaa 00000000 00000000 00000000 + + transparent1: + mov eax, edx; // eax = arrrrrgg gggbbbbb arrrrrgg gggbbbbb + and edx, 0x0000001f; // edx = 00000000 00000000 00000000 000bbbbb + shl edx, 14; // edx = 00000000 00000bbb bb000000 00000000 + or ebx, edx; // ebx = aaaaaaaa 00000bbb bb000000 00000000 + shl edx, 5; // edx = 00000000 bbbbb000 00000000 00000000 + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb bb000000 00000000 + and ebx, 0xffff0000; // ebx = aaaaaaaa bbbbbbbb 00000000 00000000 + mov edx, eax; + and edx, 0x000003e0; // edx = 00000000 00000000 000000gg ggg00000 + shl edx, 1; // edx = 00000000 00000000 00000ggg gg000000 + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb 00000ggg gg000000 + shl edx, 5; // edx = 00000000 00000000 ggggg000 00000000 + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb gggggggg gg000000 + and ebx, 0xffffff00; // ebx = aaaaaaaa bbbbbbbb gggggggg 00000000 + mov edx, eax; + and edx, 0x00007c00; // edx = 00000000 00000000 0rrrrr00 00000000 + shr edx, 7; // edx = 00000000 00000000 00000000 rrrrr000 + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb gggggggg rrrrr000 + shr edx, 5; // edx = 00000000 00000000 00000000 00000rrr + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb gggggggg rrrrrrrr + + mov dword ptr [edi], ebx; + add edi, 4; + + shr eax, 16; // eax = 00000000 00000000 arrrrrgg gggbbbbb + mov edx, eax; // edx = 00000000 00000000 arrrrrgg gggbbbbb + and ebx, 0x00000000; + and eax, 0x00008000; // eax = 00000000 00000000 a0000000 00000000 + jz transparent2; + or ebx, 0xff000000; // ebx = aaaaaaaa 00000000 00000000 00000000 + + transparent2: + mov eax, edx; // eax = arrrrrgg gggbbbbb arrrrrgg gggbbbbb + and edx, 0x0000001f; // edx = 00000000 00000000 00000000 000bbbbb + shl edx, 14; // edx = 00000000 00000bbb bb000000 00000000 + or ebx, edx; // ebx = aaaaaaaa 00000bbb bb000000 00000000 + shl edx, 5; // edx = 00000000 bbbbb000 00000000 00000000 + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb bb000000 00000000 + and ebx, 0xffff0000; // ebx = aaaaaaaa bbbbbbbb 00000000 00000000 + mov edx, eax; + and edx, 0x000003e0; // edx = 00000000 00000000 000000gg ggg00000 + shl edx, 1; // edx = 00000000 00000000 00000ggg gg000000 + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb 00000ggg gg000000 + shl edx, 5; // edx = 00000000 00000000 ggggg000 00000000 + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb gggggggg gg000000 + and ebx, 0xffffff00; // ebx = aaaaaaaa bbbbbbbb gggggggg 00000000 + mov edx, eax; + and edx, 0x00007c00; // edx = 00000000 00000000 0rrrrr00 00000000 + shr edx, 7; // edx = 00000000 00000000 00000000 rrrrr000 + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb gggggggg rrrrr000 + shr edx, 5; // edx = 00000000 00000000 00000000 00000rrr + or ebx, edx; // ebx = aaaaaaaa bbbbbbbb gggggggg rrrrrrrr + + mov dword ptr [edi], ebx; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +} + +void +TxQuantize::ARGB4444_ABGR8888(uint32* src, uint32* dest, int width, int height) +{ + int siz = (width * height) >> 1; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // aaaa rrrr gggg bbbb + // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr + mov edx, eax; + and eax, 0x0000ffff; + mov ebx, eax; // 00000000 00000000 aaaarrrr ggggbbbb + and ebx, 0x0000f000; // 00000000 00000000 aaaa0000 00000000 + shl ebx, 12; // 0000aaaa 00000000 00000000 00000000 + or eax, ebx; // 0000aaaa 00000000 aaaarrrr ggggbbbb + mov ebx, eax; + and ebx, 0x0000000f; // 00000000 00000000 00000000 0000bbbb + shl ebx, 16; // 00000000 0000bbbb 00000000 00000000 + or eax, ebx; // 0000aaaa 0000bbbb aaaarrrr ggggbbbb + mov ebx, eax; + and ebx, 0x00000f00; // 00000000 00000000 0000rrrr 00000000 + shr ebx, 8; // 00000000 00000000 00000000 0000rrrr + and eax, 0xfffffff0; + or eax, ebx; // 0000aaaa 0000bbbb aaaarrrr ggggrrrr + mov ebx, eax; + and ebx, 0x000000f0; // 00000000 00000000 00000000 gggg0000 + shl ebx, 4; // 00000000 00000000 0000gggg 00000000 + and eax, 0x0f0f000f; // 0000aaaa 0000bbbb 00000000 0000rrrr + or eax, ebx; // 0000aaaa 0000bbbb 0000gggg 0000rrrr + mov ebx, eax; + shl ebx, 4; // aaaa0000 bbbb0000 gggg0000 rrrr0000 + or eax, ebx; // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr + + mov dword ptr [edi], eax; + + add edi, 4; + + shr edx, 16; + mov ebx, edx; // 00000000 00000000 aaaarrrr ggggbbbb + and ebx, 0x0000f000; // 00000000 00000000 aaaa0000 00000000 + shl ebx, 12; // 0000aaaa 00000000 00000000 00000000 + or edx, ebx; // 0000aaaa 00000000 aaaarrrr ggggbbbb + mov ebx, edx; + and ebx, 0x0000000f; // 00000000 00000000 00000000 0000bbbb + shl ebx, 16; // 00000000 0000bbbb 00000000 00000000 + or edx, ebx; // 0000aaaa 0000bbbb aaaarrrr ggggbbbb + mov ebx, edx; + and ebx, 0x00000f00; // 00000000 00000000 0000rrrr 00000000 + shr ebx, 8; // 00000000 00000000 00000000 0000rrrr + and edx, 0xfffffff0; + or edx, ebx; // 0000aaaa 0000bbbb aaaarrrr ggggrrrr + mov ebx, edx; + and ebx, 0x000000f0; // 00000000 00000000 00000000 gggg0000 + shl ebx, 4; // 00000000 00000000 0000gggg 00000000 + and edx, 0x0f0f000f; // 0000aaaa 0000bbbb 00000000 0000rrrr + or edx, ebx; // 0000aaaa 0000bbbb 0000gggg 0000rrrr + mov ebx, edx; + shl ebx, 4; // aaaa0000 bbbb0000 gggg0000 rrrr0000 + or edx, ebx; // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr + + mov dword ptr [edi], edx; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +} + +void +TxQuantize::ARGB8888_ABGR8888(uint32* src, uint32* dest, int width, int height) +{ + int siz = width * height; + + __asm { + push ebx; + push esi; + push edi; + + mov esi, dword ptr [src]; + mov edi, dword ptr [dest]; + mov ecx, dword ptr [siz]; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr + mov edx, eax; + bswap edx; + shr edx, 8; + and eax, 0xff000000; + + or eax, edx; + + mov dword ptr [edi], eax; + add edi, 4; + + dec ecx; + jnz tc1_loop; + + pop edi; + pop esi; + pop ebx; + } +} +#endif diff --git a/GLideNHQ/TxQuantize.h b/GLideNHQ/TxQuantize.h new file mode 100644 index 00000000..d3c6ae6d --- /dev/null +++ b/GLideNHQ/TxQuantize.h @@ -0,0 +1,99 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TXQUANTIZE_H__ +#define __TXQUANTIZE_H__ + +/* Glide64 DXTn workaround + * (0:disable, 1:enable) */ +#define GLIDE64_DXTN 1 + +#include "TxInternal.h" +#include "TxUtil.h" + +class TxQuantize +{ +private: + TxUtil *_txUtil; + int _numcore; + + fxtCompressTexFuncExt _tx_compress_fxt1; + dxtCompressTexFuncExt _tx_compress_dxtn; + + /* fast optimized... well, sort of. */ + void ARGB1555_ARGB8888(uint32* src, uint32* dst, int width, int height); + void ARGB4444_ARGB8888(uint32* src, uint32* dst, int width, int height); + void RGB565_ARGB8888(uint32* src, uint32* dst, int width, int height); + void A8_ARGB8888(uint32* src, uint32* dst, int width, int height); + void AI44_ARGB8888(uint32* src, uint32* dst, int width, int height); + void AI88_ARGB8888(uint32* src, uint32* dst, int width, int height); + + void ARGB8888_ARGB1555(uint32* src, uint32* dst, int width, int height); + void ARGB8888_ARGB4444(uint32* src, uint32* dst, int width, int height); + void ARGB8888_RGB565(uint32* src, uint32* dst, int width, int height); + void ARGB8888_A8(uint32* src, uint32* dst, int width, int height); + void ARGB8888_AI44(uint32* src, uint32* dst, int width, int height); + void ARGB8888_AI88(uint32* src, uint32* dst, int width, int height); + + /* quality */ + void ARGB8888_RGB565_ErrD(uint32* src, uint32* dst, int width, int height); + void ARGB8888_ARGB1555_ErrD(uint32* src, uint32* dst, int width, int height); + void ARGB8888_ARGB4444_ErrD(uint32* src, uint32* dst, int width, int height); + void ARGB8888_AI44_ErrD(uint32* src, uint32* dst, int width, int height); + void ARGB8888_AI88_Slow(uint32* src, uint32* dst, int width, int height); + void ARGB8888_I8_Slow(uint32* src, uint32* dst, int width, int height); + + /* compressors */ + boolean FXT1(uint8 *src, uint8 *dest, + int srcwidth, int srcheight, uint16 srcformat, + int *destwidth, int *destheight, uint16 *destformat); + boolean DXTn(uint8 *src, uint8 *dest, + int srcwidth, int srcheight, uint16 srcformat, + int *destwidth, int *destheight, uint16 *destformat); + +public: + TxQuantize(); + ~TxQuantize(); + + /* others */ + void P8_16BPP(uint32* src, uint32* dst, int width, int height, uint32* palette); + + boolean quantize(uint8* src, uint8* dest, int width, int height, uint16 srcformat, uint16 destformat, boolean fastQuantizer = 1); + + boolean compress(uint8 *src, uint8 *dest, + int srcwidth, int srcheight, uint16 srcformat, + int *destwidth, int *destheight, uint16 *destformat, + int compressionType); + + +#if 0 /* unused */ + void ARGB8888_I8(uint32* src, uint32* dst, int width, int height); + void I8_ARGB8888(uint32* src, uint32* dst, int width, int height); + + void ARGB1555_ABGR8888(uint32* src, uint32* dst, int width, int height); + void ARGB4444_ABGR8888(uint32* src, uint32* dst, int width, int height); + void ARGB8888_ABGR8888(uint32* src, uint32* dst, int width, int height); +#endif +}; + +#endif /* __TXQUANTIZE_H__ */ diff --git a/GLideNHQ/TxReSample.cpp b/GLideNHQ/TxReSample.cpp new file mode 100644 index 00000000..138428b7 --- /dev/null +++ b/GLideNHQ/TxReSample.cpp @@ -0,0 +1,417 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "TxReSample.h" +#include "TxDbg.h" +#include +#include + +#define _USE_MATH_DEFINES +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +int +TxReSample::nextPow2(int num) +{ + num = num - 1; + num = num | (num >> 1); + num = num | (num >> 2); + num = num | (num >> 4); + num = num | (num >> 8); + num = num | (num >> 16); + /*num = num | (num >> 32);*//* for 64bit architecture */ + num = num + 1; + + return num; +} + +boolean +TxReSample::nextPow2(uint8** image, int* width, int* height, int bpp, boolean use_3dfx = 0) +{ + /* NOTE: bpp must be one of the follwing: 8, 16, 24, 32 bits per pixel */ + + if (!*image || !*width || !*height || !bpp) + return 0; + + int row_bytes = ((*width * bpp) >> 3); + int o_row_bytes = row_bytes; + int o_width = *width; + int n_width = *width; + int o_height = *height; + int n_height = *height; + + /* HACKALERT: I have explicitly subtracted (n) from width/height to + * adjust textures that have (n) pixel larger width/height than + * power of 2 size. This is a dirty hack for textures that have + * munged aspect ratio by (n) pixel to the original. + */ + if (n_width > 64) n_width -= 4; + else if (n_width > 16) n_width -= 2; + else if (n_width > 4) n_width -= 1; + + if (n_height > 64) n_height -= 4; + else if (n_height > 16) n_height -= 2; + else if (n_height > 4) n_height -= 1; + + n_width = nextPow2(n_width); + n_height = nextPow2(n_height); + row_bytes = (n_width * bpp) >> 3; + + /* 3dfx Glide3 format, W:H aspect ratio range (8:1 - 1:8) */ + if (use_3dfx) { + if (n_width > n_height) { + if (n_width > (n_height << 3)) + n_height = n_width >> 3; + } else { + if (n_height > (n_width << 3)) { + n_width = n_height >> 3; + row_bytes = (n_width * bpp) >> 3; + } + } + DBG_INFO(80, L"using 3dfx W:H aspect ratio range (8:1 - 1:8).\n"); + } + + /* do we really need to do this ? */ + if (o_width == n_width && o_height == n_height) + return 1; /* nope */ + + DBG_INFO(80, L"expand image to next power of 2 dimensions. %d x %d -> %d x %d\n", + o_width, o_height, n_width, n_height); + + if (o_width > n_width) + o_width = n_width; + + if (o_height > n_height) + o_height = n_height; + + /* allocate memory to read in image */ + uint8 *pow2image = (uint8*)malloc(row_bytes * n_height); + + /* read in image */ + if (pow2image) { + int i, j; + uint8 *tmpimage = *image, *tmppow2image = pow2image; + + for (i = 0; i < o_height; i++) { + /* copy row */ + memcpy(tmppow2image, tmpimage, ((o_width * bpp) >> 3)); + + /* expand to pow2 size by replication */ + for(j = ((o_width * bpp) >> 3); j < row_bytes; j++) + tmppow2image[j] = tmppow2image[j - (bpp >> 3)]; + + tmppow2image += row_bytes; + tmpimage += o_row_bytes; + } + /* expand to pow2 size by replication */ + for (i = o_height; i < n_height; i++) + memcpy(&pow2image[row_bytes * i], &pow2image[row_bytes * (i - 1)], row_bytes); + + free(*image); + + *image = pow2image; + *height = n_height; + *width = n_width; + + return 1; + } + + return 0; +} + +/* Ken Turkowski + * Filters for Common Resampling Tasks + * Apple Computer 1990 + */ +double +TxReSample::tent(double x) +{ + if (x < 0.0) x = -x; + if (x < 1.0) return (1.0 - x); + return 0.0; +} + +double +TxReSample::gaussian(double x) +{ + if (x < 0) x = -x; + if (x < 2.0) return pow(2.0, -2.0 * x * x); + return 0.0; +} + +double +TxReSample::sinc(double x) +{ + if (x == 0) return 1.0; + x *= M_PI; + return (sin(x) / x); +} + +double +TxReSample::lanczos3(double x) +{ + if (x < 0) x = -x; + if (x < 3.0) return (sinc(x) * sinc(x/3.0)); + return 0.0; +} + +/* Don P. Mitchell and Arun N. Netravali + * Reconstruction Filters in Computer Graphics + * SIGGRAPH '88 + * Proceedings of the 15th annual conference on Computer + * graphics and interactive techniques, pp221-228, 1988 + */ +double +TxReSample::mitchell(double x) +{ + if (x < 0) x = -x; + if (x < 2.0) { + const double B = 1.0 / 3.0; + const double C = 1.0 / 3.0; + if (x < 1.0) { + x = (((12.0 - 9.0 * B - 6.0 * C) * (x * x * x)) + + ((-18.0 + 12.0 * B + 6.0 * C) * (x * x)) + + (6.0 - 2.0 * B)); + } else { + x = (((-1.0 * B - 6.0 * C) * (x * x * x)) + + ((6.0 * B + 30.0 * C) * (x * x)) + + ((-12.0 * B - 48.0 * C) * x) + + (8.0 * B + 24.0 * C)); + } + return (x / 6.0); + } + return 0.0; +} + +/* J. F. Kaiser and W. A. Reed + * Data smoothing using low-pass digital filters + * Rev. Sci. instrum. 48 (11), pp1447-1457, 1977 + */ +double +TxReSample::besselI0(double x) +{ + /* zero-order modified bessel function of the first kind */ + const double eps_coeff = 1E-16; /* small enough */ + double xh, sum, pow, ds; + xh = 0.5 * x; + sum = 1.0; + pow = 1.0; + ds = 1.0; + int k = 0; + while (ds > sum * eps_coeff) { + k++; + pow *= (xh / k); + ds = pow * pow; + sum = sum + ds; + } + return sum; +} + +double +TxReSample::kaiser(double x) +{ + const double alpha = 4.0; + const double half_window = 5.0; + const double ratio = x / half_window; + return sinc(x) * besselI0(alpha * sqrt(1 - ratio * ratio)) / besselI0(alpha); +} + +boolean +TxReSample::minify(uint8 **src, int *width, int *height, int ratio) +{ + /* NOTE: src must be ARGB8888, ratio is the inverse representation */ + +#if 0 + if (!*src || ratio < 2) return 0; + + /* Box filtering. + * It would be nice to do Kaiser filtering. + * N64 uses narrow strip textures which makes it hard to filter effectively. + */ + + int x, y, x2, y2, offset, numtexel; + uint32 A, R, G, B, texel; + + int tmpwidth = *width / ratio; + int tmpheight = *height / ratio; + + uint8 *tmptex = (uint8*)malloc((tmpwidth * tmpheight) << 2); + + if (tmptex) { + numtexel = ratio * ratio; + for (y = 0; y < tmpheight; y++) { + offset = ratio * y * *width; + for (x = 0; x < tmpwidth; x++) { + A = R = G = B = 0; + for (y2 = 0; y2 < ratio; y2++) { + for (x2 = 0; x2 < ratio; x2++) { + texel = ((uint32*)*src)[offset + *width * y2 + x2]; + A += (texel >> 24); + R += ((texel >> 16) & 0x000000ff); + G += ((texel >> 8) & 0x000000ff); + B += (texel & 0x000000ff); + } + } + A = (A + ratio) / numtexel; + R = (R + ratio) / numtexel; + G = (G + ratio) / numtexel; + B = (B + ratio) / numtexel; + ((uint32*)tmptex)[y * tmpwidth + x] = ((A << 24) | (R << 16) | (G << 8) | B); + offset += ratio; + } + } + free(*src); + *src = tmptex; + *width = tmpwidth; + *height = tmpheight; + + DBG_INFO(80, L"minification ratio:%d -> %d x %d\n", ratio, *width, *height); + + return 1; + } + + DBG_INFO(80, L"Error: failed minification!\n"); + + return 0; + +#else + + if (!*src || ratio < 2) return 0; + + /* Image Resampling */ + + /* half width of filter window. + * NOTE: must be 1.0 or larger. + * + * kaiser-bessel 5, lanczos3 3, mitchell 2, gaussian 1.5, tent 1 + */ + double half_window = 5.0; + + int x, y, x2, y2, z; + double A, R, G, B; + uint32 texel; + + int tmpwidth = *width / ratio; + int tmpheight = *height / ratio; + + /* resampled destination */ + uint8 *tmptex = (uint8*)malloc((tmpwidth * tmpheight) << 2); + if (!tmptex) return 0; + + /* work buffer. single row */ + uint8 *workbuf = (uint8*)malloc(*width << 2); + if (!workbuf) { + free(tmptex); + return 0; + } + + /* prepare filter lookup table. only half width required for symetric filters. */ + double *weight = (double*)malloc((int)((half_window * ratio) * sizeof(double))); + if (!weight) { + free(tmptex); + free(workbuf); + return 0; + } + for (x = 0; x < half_window * ratio; x++) { + //weight[x] = tent((double)x / ratio) / ratio; + //weight[x] = gaussian((double)x / ratio) / ratio; + //weight[x] = lanczos3((double)x / ratio) / ratio; + //weight[x] = mitchell((double)x / ratio) / ratio; + weight[x] = kaiser((double)x / ratio) / ratio; + } + + /* linear convolution */ + for (y = 0; y < tmpheight; y++) { + for (x = 0; x < *width; x++) { + texel = ((uint32*)*src)[y * ratio * *width + x]; + A = (double)(texel >> 24) * weight[0]; + R = (double)((texel >> 16) & 0xff) * weight[0]; + G = (double)((texel >> 8) & 0xff) * weight[0]; + B = (double)((texel ) & 0xff) * weight[0]; + for (y2 = 1; y2 < half_window * ratio; y2++) { + z = y * ratio + y2; + if (z >= *height) z = *height - 1; + texel = ((uint32*)*src)[z * *width + x]; + A += (double)(texel >> 24) * weight[y2]; + R += (double)((texel >> 16) & 0xff) * weight[y2]; + G += (double)((texel >> 8) & 0xff) * weight[y2]; + B += (double)((texel ) & 0xff) * weight[y2]; + z = y * ratio - y2; + if (z < 0) z = 0; + texel = ((uint32*)*src)[z * *width + x]; + A += (double)(texel >> 24) * weight[y2]; + R += (double)((texel >> 16) & 0xff) * weight[y2]; + G += (double)((texel >> 8) & 0xff) * weight[y2]; + B += (double)((texel ) & 0xff) * weight[y2]; + } + if (A < 0) A = 0; else if (A > 255) A = 255; + if (R < 0) R = 0; else if (R > 255) R = 255; + if (G < 0) G = 0; else if (G > 255) G = 255; + if (B < 0) B = 0; else if (B > 255) B = 255; + ((uint32*)workbuf)[x] = (((uint32)A << 24) | ((uint32)R << 16) | ((uint32)G << 8) | (uint32)B); + } + for (x = 0; x < tmpwidth; x++) { + texel = ((uint32*)workbuf)[x * ratio]; + A = (double)(texel >> 24) * weight[0]; + R = (double)((texel >> 16) & 0xff) * weight[0]; + G = (double)((texel >> 8) & 0xff) * weight[0]; + B = (double)((texel ) & 0xff) * weight[0]; + for (x2 = 1; x2 < half_window * ratio; x2++) { + z = x * ratio + x2; + if (z >= *width) z = *width - 1; + texel = ((uint32*)workbuf)[z]; + A += (double)(texel >> 24) * weight[x2]; + R += (double)((texel >> 16) & 0xff) * weight[x2]; + G += (double)((texel >> 8) & 0xff) * weight[x2]; + B += (double)((texel ) & 0xff) * weight[x2]; + z = x * ratio - x2; + if (z < 0) z = 0; + texel = ((uint32*)workbuf)[z]; + A += (double)(texel >> 24) * weight[x2]; + R += (double)((texel >> 16) & 0xff) * weight[x2]; + G += (double)((texel >> 8) & 0xff) * weight[x2]; + B += (double)((texel ) & 0xff) * weight[x2]; + } + if (A < 0) A = 0; else if (A > 255) A = 255; + if (R < 0) R = 0; else if (R > 255) R = 255; + if (G < 0) G = 0; else if (G > 255) G = 255; + if (B < 0) B = 0; else if (B > 255) B = 255; + ((uint32*)tmptex)[y * tmpwidth + x] = (((uint32)A << 24) | ((uint32)R << 16) | ((uint32)G << 8) | (uint32)B); + } + } + + free(*src); + *src = tmptex; + free(weight); + free(workbuf); + *width = tmpwidth; + *height = tmpheight; + + DBG_INFO(80, L"minification ratio:%d -> %d x %d\n", ratio, *width, *height); + + return 1; +#endif +} diff --git a/GLideNHQ/TxReSample.h b/GLideNHQ/TxReSample.h new file mode 100644 index 00000000..805647d2 --- /dev/null +++ b/GLideNHQ/TxReSample.h @@ -0,0 +1,45 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TXRESAMPLE_H__ +#define __TXRESAMPLE_H__ + +#include "TxInternal.h" + +class TxReSample +{ +private: + double tent(double x); + double gaussian(double x); + double sinc(double x); + double lanczos3(double x); + double mitchell(double x); + double besselI0(double x); + double kaiser(double x); +public: + boolean minify(uint8 **src, int *width, int *height, int ratio); + boolean nextPow2(uint8** image, int* width, int* height, int bpp, boolean use_3dfx); + int nextPow2(int num); +}; + +#endif /* __TXRESAMPLE_H__ */ diff --git a/GLideNHQ/TxTexCache.cpp b/GLideNHQ/TxTexCache.cpp new file mode 100644 index 00000000..c063c240 --- /dev/null +++ b/GLideNHQ/TxTexCache.cpp @@ -0,0 +1,79 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __MSC__ +#pragma warning(disable: 4786) +#endif + +/* dump cache to disk (0:disable, 1:enable) */ +#define DUMP_CACHE 1 + +#include "TxTexCache.h" +#include "TxDbg.h" +#include +#include +#include + +TxTexCache::~TxTexCache() +{ +#if DUMP_CACHE + if (_options & DUMP_TEXCACHE) { + /* dump cache to disk */ + std::wstring filename = _ident + L"_MEMORYCACHE.dat"; + boost::filesystem::wpath cachepath(_path); + cachepath /= boost::filesystem::wpath(L"cache"); + int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE); + + TxCache::save(cachepath.wstring().c_str(), filename.c_str(), config); + } +#endif +} + +TxTexCache::TxTexCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident, + dispInfoFuncExt callback + ) : TxCache((options & ~GZ_HIRESTEXCACHE), cachesize, path, ident, callback) +{ + /* assert local options */ + if (_path.empty() || _ident.empty() || !_cacheSize) + _options &= ~DUMP_TEXCACHE; + +#if DUMP_CACHE + if (_options & DUMP_TEXCACHE) { + /* find it on disk */ + std::wstring filename = _ident + L"_MEMORYCACHE.dat"; + boost::filesystem::wpath cachepath(_path); + cachepath /= boost::filesystem::wpath(L"cache"); + int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE); + + TxCache::load(cachepath.wstring().c_str(), filename.c_str(), config); + } +#endif +} + +boolean +TxTexCache::add(uint64 checksum, GHQTexInfo *info) +{ + if (_cacheSize <= 0) return 0; + + return TxCache::add(checksum, info); +} diff --git a/GLideNHQ/TxTexCache.h b/GLideNHQ/TxTexCache.h new file mode 100644 index 00000000..b8020953 --- /dev/null +++ b/GLideNHQ/TxTexCache.h @@ -0,0 +1,39 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TXTEXCACHE_H__ +#define __TXTEXCACHE_H__ + +#include "TxCache.h" + +class TxTexCache : public TxCache +{ +public: + ~TxTexCache(); + TxTexCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident, + dispInfoFuncExt callback); + boolean add(uint64 checksum, /* checksum hi:palette low:texture */ + GHQTexInfo *info); +}; + +#endif /* __TXTEXCACHE_H__ */ diff --git a/GLideNHQ/TxUtil.cpp b/GLideNHQ/TxUtil.cpp new file mode 100644 index 00000000..4972b8e6 --- /dev/null +++ b/GLideNHQ/TxUtil.cpp @@ -0,0 +1,1006 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "TxUtil.h" +#include "TxDbg.h" +#include +#include + +/* + * External libraries + ******************************************************************************/ +TxLoadLib::TxLoadLib() +{ +#ifdef DXTN_DLL + if (!_dxtnlib) + _dxtnlib = LoadLibrary("dxtn"); + + if (_dxtnlib) { + if (!_tx_compress_dxtn) + _tx_compress_dxtn = (dxtCompressTexFuncExt)DLSYM(_dxtnlib, "tx_compress_dxtn"); + + if (!_tx_compress_fxt1) + _tx_compress_fxt1 = (fxtCompressTexFuncExt)DLSYM(_dxtnlib, "fxt1_encode"); + } +#else + _tx_compress_dxtn = tx_compress_dxtn; + _tx_compress_fxt1 = fxt1_encode; + +#endif +} + +TxLoadLib::~TxLoadLib() +{ +#ifdef DXTN_DLL + /* free dynamic library */ + if (_dxtnlib) + FreeLibrary(_dxtnlib); +#endif + +} + +fxtCompressTexFuncExt +TxLoadLib::getfxtCompressTexFuncExt() +{ + return _tx_compress_fxt1; +} + +dxtCompressTexFuncExt +TxLoadLib::getdxtCompressTexFuncExt() +{ + return _tx_compress_dxtn; +} + + +/* + * Utilities + ******************************************************************************/ +uint32 +TxUtil::checksumTx(uint8 *src, int width, int height, uint16 format) +{ + int dataSize = sizeofTx(width, height, format); + + /* for now we use adler32 if something else is better + * we can simply swtich later + */ + /* return (dataSize ? Adler32(src, dataSize, 1) : 0); */ + + /* zlib crc32 */ + return (dataSize ? crc32(crc32(0L, Z_NULL, 0), src, dataSize) : 0); +} + +int +TxUtil::sizeofTx(int width, int height, uint16 format) +{ + int dataSize = 0; + + /* a lookup table for the shifts would be better */ + switch (format) { + case GR_TEXFMT_ARGB_CMP_FXT1: + dataSize = (((width + 0x7) & ~0x7) * ((height + 0x3) & ~0x3)) >> 1; + break; + case GR_TEXFMT_ARGB_CMP_DXT1: + dataSize = (((width + 0x3) & ~0x3) * ((height + 0x3) & ~0x3)) >> 1; + break; + case GR_TEXFMT_ARGB_CMP_DXT3: + case GR_TEXFMT_ARGB_CMP_DXT5: + dataSize = ((width + 0x3) & ~0x3) * ((height + 0x3) & ~0x3); + break; + case GR_TEXFMT_ALPHA_INTENSITY_44: + case GR_TEXFMT_ALPHA_8: + case GR_TEXFMT_INTENSITY_8: + case GR_TEXFMT_P_8: + dataSize = width * height; + break; + case GR_TEXFMT_ARGB_4444: + case GR_TEXFMT_ARGB_1555: + case GR_TEXFMT_RGB_565: + case GR_TEXFMT_ALPHA_INTENSITY_88: + dataSize = (width * height) << 1; + break; + case GR_TEXFMT_ARGB_8888: + dataSize = (width * height) << 2; + break; + default: + /* unsupported format */ + DBG_INFO(80, L"Error: cannot get size. unsupported gfmt:%x\n", format); + ; + } + + return dataSize; +} + +#if 0 /* unused */ +uint32 +TxUtil::chkAlpha(uint32* src, int width, int height) +{ + /* NOTE: _src must be ARGB8888 + * return values + * 0x00000000: 8bit alpha + * 0x00000001: 1bit alpha + * 0xff000001: no alpha + */ + + int _size = width * height; + uint32 alpha = 0; + + __asm { + mov esi, dword ptr [src]; + mov ecx, dword ptr [_size]; + mov ebx, 0xff000000; + + tc1_loop: + mov eax, dword ptr [esi]; + add esi, 4; + + and eax, 0xff000000; + jz alpha1bit; + cmp eax, 0xff000000; + je alpha1bit; + jmp done; + + alpha1bit: + and ebx, eax; + dec ecx; + jnz tc1_loop; + + or ebx, 0x00000001; + mov dword ptr [alpha], ebx; + + done: + } + + return alpha; +} +#endif + +uint32 +TxUtil::checksum(uint8 *src, int width, int height, int size, int rowStride) +{ + /* Rice CRC32 for now. We can switch this to Jabo MD5 or + * any other custom checksum. + * TODO: use *_HIRESTEXTURE option. */ + + if (!src) return 0; + + return RiceCRC32(src, width, height, size, rowStride); +} + +uint64 +TxUtil::checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette) +{ + /* Rice CRC32 for now. We can switch this to Jabo MD5 or + * any other custom checksum. + * TODO: use *_HIRESTEXTURE option. */ + /* Returned value is 64bits: hi=palette crc32 low=texture crc32 */ + + if (!src) return 0; + + uint64 crc64Ret = 0; + + if (palette) { + uint32 crc32 = 0, cimax = 0; + switch (size & 0xff) { + case 1: + if (RiceCRC32_CI8(src, width, height, size, rowStride, &crc32, &cimax)) { + crc64Ret = (uint64)RiceCRC32(palette, cimax + 1, 1, 2, 512); + crc64Ret <<= 32; + crc64Ret |= (uint64)crc32; + } + break; + case 0: + if (RiceCRC32_CI4(src, width, height, size, rowStride, &crc32, &cimax)) { + crc64Ret = (uint64)RiceCRC32(palette, cimax + 1, 1, 2, 32); + crc64Ret <<= 32; + crc64Ret |= (uint64)crc32; + } + } + } + if (!crc64Ret) { + crc64Ret = (uint64)RiceCRC32(src, width, height, size, rowStride); + } + + return crc64Ret; +} + +/* +** Computes Adler32 checksum for a stream of data. +** +** From the specification found in RFC 1950: (ZLIB Compressed Data Format +** Specification version 3.3) +** +** ADLER32 (Adler-32 checksum) This contains a checksum value of the +** uncompressed data (excluding any dictionary data) computed according to +** Adler-32 algorithm. This algorithm is a 32-bit extension and improvement +** of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 standard. +** +** Adler-32 is composed of two sums accumulated per byte: s1 is the sum of +** all bytes, s2 is the sum of all s1 values. Both sums are done modulo +** 65521. s1 is initialized to 1, s2 to zero. The Adler-32 checksum is stored +** as s2*65536 + s1 in most-significant-byte first (network) order. +** +** 8.2. The Adler-32 algorithm +** +** The Adler-32 algorithm is much faster than the CRC32 algorithm yet still +** provides an extremely low probability of undetected errors. +** +** The modulo on unsigned long accumulators can be delayed for 5552 bytes, +** so the modulo operation time is negligible. If the bytes are a, b, c, +** the second sum is 3a + 2b + c + 3, and so is position and order sensitive, +** unlike the first sum, which is just a checksum. That 65521 is prime is +** important to avoid a possible large class of two-byte errors that leave +** the check unchanged. (The Fletcher checksum uses 255, which is not prime +** and which also makes the Fletcher check insensitive to single byte +** changes 0 <-> 255.) +** +** The sum s1 is initialized to 1 instead of zero to make the length of +** the sequence part of s2, so that the length does not have to be checked +** separately. (Any sequence of zeroes has a Fletcher checksum of zero.) +*/ + +uint32 +TxUtil::Adler32(const uint8* data, int Len, uint32 dwAdler32) +{ +#if 1 + /* zlib adler32 */ + return adler32(dwAdler32, data, Len); +#else + register uint32 s1 = dwAdler32 & 0xFFFF; + register uint32 s2 = (dwAdler32 >> 16) & 0xFFFF; + int k; + + while (Len > 0) { + /* 5552 is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + k = (Len < 5552 ? Len : 5552); + Len -= k; + while (k--) { + s1 += *data++; + s2 += s1; + } + /* 65521 is the largest prime smaller than 65536 */ + s1 %= 65521; + s2 %= 65521; + } + + return (s2 << 16) | s1; +#endif +} + +uint32 +TxUtil::Adler32(const uint8* src, int width, int height, int size, int rowStride) +{ + int i; + uint32 ret = 1; + uint32 width_in_bytes = width * size; + + for (i = 0; i < height; i++) { + ret = Adler32(src, width_in_bytes, ret); + src += rowStride; + } + + return ret; +} + +/* Rice CRC32 for hires texture packs */ +/* NOTE: The following is used in Glide64 to calculate the CRC32 + * for Rice hires texture packs. + * + * BYTE* addr = (BYTE*)(gfx.RDRAM + + * rdp.addr[rdp.tiles[tile].t_mem] + + * (rdp.tiles[tile].ul_t * bpl) + + * (((rdp.tiles[tile].ul_s<>1)); + * RiceCRC32(addr, + * rdp.tiles[tile].width, + * rdp.tiles[tile].height, + * (unsigned short)(rdp.tiles[tile].format << 8 | rdp.tiles[tile].size), + * bpl); + */ +uint32 +TxUtil::RiceCRC32(const uint8* src, int width, int height, int size, int rowStride) +{ + /* NOTE: bytes_per_width must be equal or larger than 4 */ + + uint32 crc32Ret = 0; + const uint32 bytes_per_width = ((width << size) + 1) >> 1; + + /*if (bytes_per_width < 4) return 0;*/ + + try { +#ifdef __MSC__ + __asm { + push ebx; + push esi; + push edi; + + mov ecx, dword ptr [src]; + mov eax, dword ptr [height]; + mov edx, 0; + dec eax; + + loop2: + mov ebx, dword ptr [bytes_per_width]; + sub ebx, 4; + + loop1: + mov esi, dword ptr [ecx+ebx]; + xor esi, ebx; + rol edx, 4; + add edx, esi; + sub ebx, 4; + jge loop1; + + xor esi, eax; + add edx, esi; + add ecx, dword ptr [rowStride]; + dec eax; + jge loop2; + + mov dword ptr [crc32Ret], edx; + + pop edi; + pop esi; + pop ebx; + } +#else + asm volatile( + "pushl %%ebx \n" + "pushl %%esi \n" + "pushl %%edi \n" + + "movl %0, %%ecx \n" + "movl %1, %%eax \n" + "movl $0, %%edx \n" + "decl %%eax \n" + + "0: \n" + "movl %2, %%ebx \n" + "subl $4, %%ebx \n" + + "1: \n" + "movl (%%ecx,%%ebx), %%esi \n" + "xorl %%ebx, %%esi \n" + "roll $4, %%edx \n" + "addl %%esi, %%edx \n" + "subl $4, %%ebx \n" + "jge 1b \n" + + "xorl %%eax, %%esi \n" + "addl %%esi, %%edx \n" + "addl %3, %%ecx \n" + "decl %%eax \n" + "jge 0b \n" + + "movl %%edx, %4 \n" + + "popl %%edi \n" + "popl %%esi \n" + "popl %%ebx \n" + : + : "m"(src), "m"(height), "m"(bytes_per_width), "m"(rowStride), "m"(crc32Ret) + : "memory", "cc" + ); +#endif + } catch(...) { + DBG_INFO(80, L"Error: RiceCRC32 exception!\n"); + } + + return crc32Ret; +} + +boolean +TxUtil::RiceCRC32_CI4(const uint8* src, int width, int height, int size, int rowStride, + uint32* crc32, uint32* cimax) +{ + /* NOTE: bytes_per_width must be equal or larger than 4 */ + + uint32 crc32Ret = 0; + uint32 cimaxRet = 0; + const uint32 bytes_per_width = ((width << size) + 1) >> 1; + + /*if (bytes_per_width < 4) return 0;*/ + + /* 4bit CI */ + try { +#ifdef __MSC__ + __asm { + push ebx; + push esi; + push edi; + + mov ecx, dword ptr [src]; + mov eax, dword ptr [height]; + mov edx, 0; + mov edi, 0; + dec eax; + + loop2: + mov ebx, dword ptr [bytes_per_width]; + sub ebx, 4; + + loop1: + mov esi, dword ptr [ecx+ebx]; + + cmp edi, 0x0000000f; + je findmax0; + + push ecx; + mov ecx, esi; + and ecx, 0x0000000f; + cmp ecx, edi; + jb findmax8; + mov edi, ecx; + + findmax8: + mov ecx, esi; + shr ecx, 4; + and ecx, 0x0000000f; + cmp ecx, edi; + jb findmax7; + mov edi, ecx; + + findmax7: + mov ecx, esi; + shr ecx, 8; + and ecx, 0x0000000f; + cmp ecx, edi; + jb findmax6; + mov edi, ecx; + + findmax6: + mov ecx, esi; + shr ecx, 12; + and ecx, 0x0000000f; + cmp ecx, edi; + jb findmax5; + mov edi, ecx; + + findmax5: + mov ecx, esi; + shr ecx, 16; + and ecx, 0x0000000f; + cmp ecx, edi; + jb findmax4; + mov edi, ecx; + + findmax4: + mov ecx, esi; + shr ecx, 20; + and ecx, 0x0000000f; + cmp ecx, edi; + jb findmax3; + mov edi, ecx; + + findmax3: + mov ecx, esi; + shr ecx, 24; + and ecx, 0x0000000f; + cmp ecx, edi; + jb findmax2; + mov edi, ecx; + + findmax2: + mov ecx, esi; + shr ecx, 28; + and ecx, 0x0000000f; + cmp ecx, edi; + jb findmax1; + mov edi, ecx; + + findmax1: + pop ecx; + + findmax0: + xor esi, ebx; + rol edx, 4; + add edx, esi; + sub ebx, 4; + jge loop1; + + xor esi, eax; + add edx, esi; + add ecx, dword ptr [rowStride]; + dec eax; + jge loop2; + + mov dword ptr [crc32Ret], edx; + mov dword ptr [cimaxRet], edi; + + pop edi; + pop esi; + pop ebx; + } +#else + asm volatile( + "pushl %%ebx \n" + "pushl %%esi \n" + "pushl %%edi \n" + + "movl %0, %%ecx \n" + "movl %1, %%eax \n" + "movl $0, %%edx \n" + "movl $0, %%edi \n" + "decl %%eax \n" + + "0: \n" + "movl %2, %%ebx \n" + "subl $4, %%ebx \n" + + "1: \n" + "movl (%%ecx,%%ebx), %%esi \n" + + "cmpl $0x0000000f, %%edi \n" + "je 10f \n" + + "pushl %%ecx \n" + "movl %%esi, %%ecx \n" + "andl $0x0000000f, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 2f \n" + "movl %%ecx, %%edi \n" + + "2: \n" + "movl %%esi, %%ecx \n" + "shrl $4, %%ecx \n" + "andl $0x0000000f, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 3f \n" + "movl %%ecx, %%edi \n" + + "3: \n" + "movl %%esi, %%ecx \n" + "shrl $8, %%ecx \n" + "andl $0x0000000f, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 4f \n" + "movl %%ecx, %%edi \n" + + "4: \n" + "movl %%esi, %%ecx \n" + "shrl $12, %%ecx \n" + "andl $0x0000000f, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 5f \n" + "movl %%ecx, %%edi \n" + + "5: \n" + "movl %%esi, %%ecx \n" + "shrl $16, %%ecx \n" + "andl $0x0000000f, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 6f \n" + "movl %%ecx, %%edi \n" + + "6: \n" + "movl %%esi, %%ecx \n" + "shrl $20, %%ecx \n" + "andl $0x0000000f, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 7f \n" + "movl %%ecx, %%edi \n" + + "7: \n" + "movl %%esi, %%ecx \n" + "shrl $24, %%ecx \n" + "andl $0x0000000f, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 8f \n" + "movl %%ecx, %%edi \n" + + "8: \n" + "movl %%esi, %%ecx \n" + "shrl $28, %%ecx \n" + "andl $0x0000000f, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 9f \n" + "movl %%ecx, %%edi \n" + + "9: \n" + "popl %%ecx \n" + + "10: \n" + "xorl %%ebx, %%esi \n" + "roll $4, %%edx \n" + "addl %%esi, %%edx \n" + "subl $4, %%ebx \n" + "jge 1b \n" + + "xorl %%eax, %%esi \n" + "addl %%esi, %%edx \n" + "addl %3, %%ecx \n" + "decl %%eax \n" + "jge 0b \n" + + "movl %%edx, %4 \n" + "movl %%edi, %5 \n" + + "popl %%edi \n" + "popl %%esi \n" + "popl %%ebx \n" + : + : "m"(src), "m"(height), "m"(bytes_per_width), "m"(rowStride), "m"(crc32Ret), "m"(cimaxRet) + : "memory", "cc" + ); +#endif + } catch(...) { + DBG_INFO(80, L"Error: RiceCRC32 exception!\n"); + } + + *crc32 = crc32Ret; + *cimax = cimaxRet; + + return 1; +} + +boolean +TxUtil::RiceCRC32_CI8(const uint8* src, int width, int height, int size, int rowStride, + uint32* crc32, uint32* cimax) +{ + /* NOTE: bytes_per_width must be equal or larger than 4 */ + + uint32 crc32Ret = 0; + uint32 cimaxRet = 0; + const uint32 bytes_per_width = ((width << size) + 1) >> 1; + + /*if (bytes_per_width < 4) return 0;*/ + + /* 8bit CI */ + try { +#ifdef __MSC__ + __asm { + push ebx; + push esi; + push edi; + + mov ecx, dword ptr [src]; + mov eax, dword ptr [height]; + mov edx, 0; + mov edi, 0; + dec eax; + + loop2: + mov ebx, dword ptr [bytes_per_width]; + sub ebx, 4; + + loop1: + mov esi, dword ptr [ecx+ebx]; + + cmp edi, 0x000000ff; + je findmax0; + + push ecx; + mov ecx, esi; + and ecx, 0x000000ff; + cmp ecx, edi; + jb findmax4; + mov edi, ecx; + + findmax4: + mov ecx, esi; + shr ecx, 8; + and ecx, 0x000000ff; + cmp ecx, edi; + jb findmax3; + mov edi, ecx; + + findmax3: + mov ecx, esi; + shr ecx, 16; + and ecx, 0x000000ff; + cmp ecx, edi; + jb findmax2; + mov edi, ecx; + + findmax2: + mov ecx, esi; + shr ecx, 24; + and ecx, 0x000000ff; + cmp ecx, edi; + jb findmax1; + mov edi, ecx; + + findmax1: + pop ecx; + + findmax0: + xor esi, ebx; + rol edx, 4; + add edx, esi; + sub ebx, 4; + jge loop1; + + xor esi, eax; + add edx, esi; + add ecx, dword ptr [rowStride]; + dec eax; + jge loop2; + + mov dword ptr [crc32Ret], edx; + mov dword ptr [cimaxRet], edi; + + pop edi; + pop esi; + pop ebx; + } +#else + asm volatile( + "pushl %%ebx \n" + "pushl %%esi \n" + "pushl %%edi \n" + + "movl %0, %%ecx \n" + "movl %1, %%eax \n" + "movl $0, %%edx \n" + "movl $0, %%edi \n" + "decl %%eax \n" + + "0: \n" + "movl %2, %%ebx \n" + "subl $4, %%ebx \n" + + "1: \n" + "movl (%%ecx,%%ebx), %%esi \n" + + "cmpl $0x000000ff, %%edi \n" + "je 6f \n" + + "pushl %%ecx \n" + "movl %%esi, %%ecx \n" + "andl $0x000000ff, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 2f \n" + "movl %%ecx, %%edi \n" + + "2: \n" + "movl %%esi, %%ecx \n" + "shrl $8, %%ecx \n" + "andl $0x000000ff, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 3f \n" + "movl %%ecx, %%edi \n" + + "3: \n" + "movl %%esi, %%ecx \n" + "shrl $16, %%ecx \n" + "andl $0x000000ff, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 4f \n" + "movl %%ecx, %%edi \n" + + "4: \n" + "movl %%esi, %%ecx \n" + "shrl $24, %%ecx \n" + "andl $0x000000ff, %%ecx \n" + "cmpl %%edi, %%ecx \n" + "jb 5f \n" + "movl %%ecx, %%edi \n" + + "5: \n" + "popl %%ecx \n" + + "6: \n" + "xorl %%ebx, %%esi \n" + "roll $4, %%edx \n" + "addl %%esi, %%edx \n" + "subl $4, %%ebx \n" + "jge 1b \n" + + "xorl %%eax, %%esi \n" + "addl %%esi, %%edx \n" + "addl %3, %%ecx \n" + "decl %%eax \n" + "jge 0b \n" + + "movl %%edx, %4 \n" + "movl %%edi, %5 \n" + + "popl %%edi \n" + "popl %%esi \n" + "popl %%ebx \n" + : + : "m"(src), "m"(height), "m"(bytes_per_width), "m"(rowStride), "m"(crc32Ret), "m"(cimaxRet) + : "memory", "cc" + ); +#endif + } catch(...) { + DBG_INFO(80, L"Error: RiceCRC32 exception!\n"); + } + + *crc32 = crc32Ret; + *cimax = cimaxRet; + + return 1; +} + +int +TxUtil::log2(int num) +{ + int i = 0; + +#if 1 + if (!num) return 0; +#ifdef __MSC__ + __asm { + mov eax, dword ptr [num]; + bsr eax, eax; + mov dword ptr [i], eax; + } +#else + asm volatile( + "movl %0, %%eax \n" + "bsrl %%eax, %%eax \n" + "movl %%eax, %1 \n" + : + : "m"(num), "m"(i) + : "memory", "cc" + ); +#endif +#else + switch (num) { + case 1: return 0; + case 2: return 1; + case 4: return 2; + case 8: return 3; + case 16: return 4; + case 32: return 5; + case 64: return 6; + case 128: return 7; + case 256: return 8; + case 512: return 9; + case 1024: return 10; + case 2048: return 11; + } +#endif + + return i; +} + +int +TxUtil::grLodLog2(int w, int h) +{ + return (w >= h ? log2(w) : log2(h)); +} + +int +TxUtil::grAspectRatioLog2(int w, int h) +{ + return (w >= h ? log2(w/h) : -log2(h/w)); +} + +int +TxUtil::getNumberofProcessors() +{ + int numcore = 1; + + /* number of logical processors per physical processor */ + try { +#ifdef __MSC__ +#if 1 + /* use win32 api */ + SYSTEM_INFO siSysInfo; + ZeroMemory(&siSysInfo, sizeof(SYSTEM_INFO)); + GetSystemInfo(&siSysInfo); + numcore = siSysInfo.dwNumberOfProcessors; +#else + __asm { + push ebx; + + mov eax, 1; + cpuid; + test edx, 0x10000000; /* check HTT */ + jz uniproc; + and ebx, 0x00ff0000; /* mask logical core counter bit */ + shr ebx, 16; + mov dword ptr [numcore], ebx; + uniproc: + + pop ebx; + } +#endif +#else + asm volatile( + "pushl %%ebx \n" + + "movl $1, %%eax \n" + "cpuid \n" + "testl $0x10000000, %%edx \n" + "jz 0f \n" + "andl $0x00ff0000, %%ebx \n" + "shrl $16, %%ebx \n" + "movl %%ebx, %0 \n" + "0: \n" + + "popl %%ebx \n" + : + : "m"(numcore) + : "memory", "cc" + ); +#endif + } catch(...) { + DBG_INFO(80, L"Error: number of processor detection failed!\n"); + } + + if (numcore > MAX_NUMCORE) numcore = MAX_NUMCORE; + + DBG_INFO(80, L"Number of processors : %d\n", numcore); + + return numcore; +} + + +/* + * Memory buffers for texture manipulations + ******************************************************************************/ +TxMemBuf::TxMemBuf() +{ + int i; + for (i = 0; i < 2; i++) { + _tex[i] = NULL; + _size[i] = 0; + } +} + +TxMemBuf::~TxMemBuf() +{ + shutdown(); +} + +boolean +TxMemBuf::init(int maxwidth, int maxheight) +{ + int i; + for (i = 0; i < 2; i++) { + if (!_tex[i]) { + _tex[i] = (uint8 *)malloc(maxwidth * maxheight * 4); + _size[i] = maxwidth * maxheight * 4; + } + + if (!_tex[i]) { + shutdown(); + return 0; + } + } + return 1; +} + +void +TxMemBuf::shutdown() +{ + int i; + for (i = 0; i < 2; i++) { + if (_tex[i]) free(_tex[i]); + _tex[i] = NULL; + _size[i] = 0; + } +} + +uint8* +TxMemBuf::get(unsigned int num) +{ + return ((num < 2) ? _tex[num] : NULL); +} + +uint32 +TxMemBuf::size_of(unsigned int num) +{ + return ((num < 2) ? _size[num] : 0); +} diff --git a/GLideNHQ/TxUtil.h b/GLideNHQ/TxUtil.h new file mode 100644 index 00000000..b89f660d --- /dev/null +++ b/GLideNHQ/TxUtil.h @@ -0,0 +1,121 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TXUTIL_H__ +#define __TXUTIL_H__ + +/* maximum number of CPU cores allowed */ +#define MAX_NUMCORE 8 + +#include "TxInternal.h" +#include + +#ifndef DXTN_DLL +#ifdef __cplusplus +extern "C"{ +#endif +void tx_compress_dxtn(int srccomps, int width, int height, + const void *source, int destformat, void *dest, + int destRowStride); + +int fxt1_encode(int width, int height, int comps, + const void *source, int srcRowStride, + void *dest, int destRowStride); +#ifdef __cplusplus +} +#endif +#endif /* DXTN_DLL */ + +typedef void (*dxtCompressTexFuncExt)(int srccomps, int width, + int height, const void *srcPixData, + int destformat, void *dest, + int dstRowStride); + +typedef int (*fxtCompressTexFuncExt)(int width, int height, int comps, + const void *source, int srcRowStride, + void *dest, int destRowStride); + +class TxLoadLib +{ +private: +#ifdef DXTN_DLL + HMODULE _dxtnlib; +#endif + fxtCompressTexFuncExt _tx_compress_fxt1; + dxtCompressTexFuncExt _tx_compress_dxtn; + TxLoadLib(); +public: + static TxLoadLib* getInstance() { + static TxLoadLib txLoadLib; + return &txLoadLib; + } + ~TxLoadLib(); + fxtCompressTexFuncExt getfxtCompressTexFuncExt(); + dxtCompressTexFuncExt getdxtCompressTexFuncExt(); +}; + +class TxUtil +{ +private: + uint32 Adler32(const uint8* data, int Len, uint32 Adler); + uint32 Adler32(const uint8* src, int width, int height, int size, int rowStride); + uint32 RiceCRC32(const uint8* src, int width, int height, int size, int rowStride); + boolean RiceCRC32_CI4(const uint8* src, int width, int height, int size, int rowStride, + uint32* crc32, uint32* cimax); + boolean RiceCRC32_CI8(const uint8* src, int width, int height, int size, int rowStride, + uint32* crc32, uint32* cimax); + int log2(int num); +public: + TxUtil() { } + ~TxUtil() { } + int sizeofTx(int width, int height, uint16 format); + uint32 checksumTx(uint8 *data, int width, int height, uint16 format); +#if 0 /* unused */ + uint32 chkAlpha(uint32* src, int width, int height); +#endif + uint32 checksum(uint8 *src, int width, int height, int size, int rowStride); + uint64 checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette); + int grLodLog2(int w, int h); + int grAspectRatioLog2(int w, int h); + int getNumberofProcessors(); +}; + +class TxMemBuf +{ +private: + uint8 *_tex[2]; + uint32 _size[2]; + TxMemBuf(); +public: + static TxMemBuf* getInstance() { + static TxMemBuf txMemBuf; + return &txMemBuf; + } + ~TxMemBuf(); + boolean init(int maxwidth, int maxheight); + void shutdown(void); + uint8 *get(unsigned int num); + uint32 size_of(unsigned int num); +}; + +#endif /* __TXUTIL_H__ */ diff --git a/GLideNHQ/bldno.cpp b/GLideNHQ/bldno.cpp new file mode 100644 index 00000000..f71eefc0 --- /dev/null +++ b/GLideNHQ/bldno.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +int main (void) +{ + struct tm locTime; + time_t sysTime; + char *build; + + time(&sysTime); + locTime = *localtime(&sysTime); + + if ((build = getenv("BUILD_NUMBER")) != NULL) { + printf("#define BUILD_NUMBER %s\n", build); + printf("#define BUILD_NUMBER_STR \"%s\"\n", build); + } else { + unsigned short magic; + magic = (locTime.tm_yday << 7) | + (locTime.tm_hour << 2) | + (locTime.tm_min / 15); + printf("#define BUILD_NUMBER %d\n", magic); + printf("#define BUILD_NUMBER_STR \"%d\"\n", magic); + } + + return 0; +} diff --git a/GLideNHQ/bldno.h b/GLideNHQ/bldno.h new file mode 100644 index 00000000..eb0ec01d --- /dev/null +++ b/GLideNHQ/bldno.h @@ -0,0 +1,2 @@ +#define BUILD_NUMBER 13480 +#define BUILD_NUMBER_STR "13480" diff --git a/GLideNHQ/gpl-2.0.txt b/GLideNHQ/gpl-2.0.txt new file mode 100644 index 00000000..d511905c --- /dev/null +++ b/GLideNHQ/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/GLideNHQ/inc/png.h b/GLideNHQ/inc/png.h new file mode 100644 index 00000000..c48dcdb9 --- /dev/null +++ b/GLideNHQ/inc/png.h @@ -0,0 +1,2686 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.4.1 - February 25, 2010 + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license (See LICENSE, below) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.4.1 - February 25, 2010: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 12.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-7 13 10210 12.so.0.10[.0] + * 1.2.10rc1-2 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.4.0beta1-5 14 10400 14.so.0.0[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.4.0beta7-8 14 10400 14.so.0.0[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.4.0beta9-14 14 10400 14.so.0.0[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.4.0beta15-36 14 10400 14.so.0.0[.0] + * 1.4.0beta37-87 14 10400 14.so.14.0[.0] + * 1.4.0rc01 14 10400 14.so.14.0[.0] + * 1.4.0beta88-109 14 10400 14.so.14.0[.0] + * 1.4.0rc02-08 14 10400 14.so.14.0[.0] + * 1.4.0 14 10400 14.so.14.0[.0] + * 1.4.1beta01-03 14 10401 14.so.14.1[.0] + * 1.4.1rc01 14 10401 14.so.14.1[.0] + * 1.4.1beta04-12 14 10401 14.so.14.1[.0] + * 1.4.1rc02-04 14 10401 14.so.14.1[.0] + * 1.4.1 14 10401 14.so.14.1[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO Specification, + * defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. + */ +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, + png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +#endif +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the + * application must include this before png.h to obtain the definition + * of jmp_buf. + */ +typedef void (PNGAPI *png_longjmp_ptr) PNGARG((jmp_buf, int)); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_alloc_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application, except to store + * the jmp_buf. + */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmpbuf PNG_DEPSTRUCT; /* used in png_error */ + png_longjmp_ptr longjmp_fn PNG_DEPSTRUCT;/* setjmp non-local goto + function. */ +#endif + png_error_ptr error_fn PNG_DEPSTRUCT; /* function for printing + errors and aborting */ + png_error_ptr warning_fn PNG_DEPSTRUCT; /* function for printing + warnings */ + png_voidp error_ptr PNG_DEPSTRUCT; /* user supplied struct for + error functions */ + png_rw_ptr write_data_fn PNG_DEPSTRUCT; /* function for writing + output data */ + png_rw_ptr read_data_fn PNG_DEPSTRUCT; /* function for reading + input data */ + png_voidp io_ptr PNG_DEPSTRUCT; /* ptr to application struct + for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read + transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write + transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct + for user transform */ + png_byte user_transform_depth PNG_DEPSTRUCT; /* bit depth of user + transformed pixels */ + png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user + transformed pixels */ +#endif +#endif + + png_uint_32 mode PNG_DEPSTRUCT; /* tells us where we are in + the PNG file */ + png_uint_32 flags PNG_DEPSTRUCT; /* flags indicating various + things to libpng */ + png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations + to perform */ + + z_stream zstream PNG_DEPSTRUCT; /* pointer to decompression + structure (below) */ + png_bytep zbuf PNG_DEPSTRUCT; /* buffer for zlib */ + png_size_t zbuf_size PNG_DEPSTRUCT; /* size of zbuf */ + int zlib_level PNG_DEPSTRUCT; /* holds zlib compression level */ + int zlib_method PNG_DEPSTRUCT; /* holds zlib compression method */ + int zlib_window_bits PNG_DEPSTRUCT; /* holds zlib compression window + bits */ + int zlib_mem_level PNG_DEPSTRUCT; /* holds zlib compression memory + level */ + int zlib_strategy PNG_DEPSTRUCT; /* holds zlib compression + strategy */ + + png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels */ + png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels */ + png_uint_32 num_rows PNG_DEPSTRUCT; /* number of rows in current pass */ + png_uint_32 usr_width PNG_DEPSTRUCT; /* width of row at start of write */ + png_size_t rowbytes PNG_DEPSTRUCT; /* size of row in bytes */ +#if 0 /* Replaced with the following in libpng-1.4.1 */ + png_size_t irowbytes PNG_DEPSTRUCT; +#endif +/* Added in libpng-1.4.1 */ +#ifdef PNG_USER_LIMITS_SUPPORTED + /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. + * We will change the typedef from png_size_t to png_alloc_size_t + * in libpng-1.6.0 + */ + png_alloc_size_t user_chunk_malloc_max PNG_DEPSTRUCT; +#endif + png_uint_32 iwidth PNG_DEPSTRUCT; /* width of current interlaced + row in pixels */ + png_uint_32 row_number PNG_DEPSTRUCT; /* current row in interlace pass */ + png_bytep prev_row PNG_DEPSTRUCT; /* buffer to save previous + (unfiltered) row */ + png_bytep row_buf PNG_DEPSTRUCT; /* buffer to save current + (unfiltered) row */ + png_bytep sub_row PNG_DEPSTRUCT; /* buffer to save "sub" row + when filtering */ + png_bytep up_row PNG_DEPSTRUCT; /* buffer to save "up" row + when filtering */ + png_bytep avg_row PNG_DEPSTRUCT; /* buffer to save "avg" row + when filtering */ + png_bytep paeth_row PNG_DEPSTRUCT; /* buffer to save "Paeth" row + when filtering */ + png_row_info row_info PNG_DEPSTRUCT; /* used for transformation + routines */ + + png_uint_32 idat_size PNG_DEPSTRUCT; /* current IDAT size for read */ + png_uint_32 crc PNG_DEPSTRUCT; /* current chunk CRC value */ + png_colorp palette PNG_DEPSTRUCT; /* palette from the input file */ + png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in + palette */ + png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparency values */ + png_byte chunk_name[5] PNG_DEPSTRUCT; /* null-terminated name of current + chunk */ + png_byte compression PNG_DEPSTRUCT; /* file compression type + (always 0) */ + png_byte filter PNG_DEPSTRUCT; /* file filter type (always 0) */ + png_byte interlaced PNG_DEPSTRUCT; /* PNG_INTERLACE_NONE, + PNG_INTERLACE_ADAM7 */ + png_byte pass PNG_DEPSTRUCT; /* current interlace pass (0 - 6) */ + png_byte do_filter PNG_DEPSTRUCT; /* row filter flags (see + PNG_FILTER_ below ) */ + png_byte color_type PNG_DEPSTRUCT; /* color type of file */ + png_byte bit_depth PNG_DEPSTRUCT; /* bit depth of file */ + png_byte usr_bit_depth PNG_DEPSTRUCT; /* bit depth of users row */ + png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */ + png_byte channels PNG_DEPSTRUCT; /* number of channels in file */ + png_byte usr_channels PNG_DEPSTRUCT; /* channels at start of write */ + png_byte sig_bytes PNG_DEPSTRUCT; /* magic bytes read/written from + start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler PNG_DEPSTRUCT; /* filler bytes for pixel + expansion */ +#endif + +#ifdef PNG_bKGD_SUPPORTED + png_byte background_gamma_type PNG_DEPSTRUCT; +# ifdef PNG_FLOATING_POINT_SUPPORTED + float background_gamma PNG_DEPSTRUCT; +# endif + png_color_16 background PNG_DEPSTRUCT; /* background color in + screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized + to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing + output */ + png_uint_32 flush_dist PNG_DEPSTRUCT; /* how many rows apart to flush, + 0 - no flush */ + png_uint_32 flush_rows PNG_DEPSTRUCT; /* number of rows written since + last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift PNG_DEPSTRUCT; /* number of "insignificant" bits + 16-bit gamma */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float gamma PNG_DEPSTRUCT; /* file gamma value */ + float screen_gamma PNG_DEPSTRUCT; /* screen gamma value + (display_exponent) */ +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table PNG_DEPSTRUCT; /* gamma table for 8-bit + depth files */ + png_bytep gamma_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */ + png_bytep gamma_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit + depth files */ + png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to + screen */ + png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in each + available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift PNG_DEPSTRUCT; /* shift for significant bit + tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans_alpha PNG_DEPSTRUCT; /* alpha values for + paletted files */ + png_color_16 trans_color PNG_DEPSTRUCT; /* transparent color for + non-paletted files */ +#endif + + png_read_status_ptr read_row_fn PNG_DEPSTRUCT; /* called after each + row is decoded */ + png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each + row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header + data fully read */ + png_progressive_row_ptr row_fn PNG_DEPSTRUCT; /* called after each + prog. row is decoded */ + png_progressive_end_ptr end_fn PNG_DEPSTRUCT; /* called after image + is complete */ + png_bytep save_buffer_ptr PNG_DEPSTRUCT; /* current location in + save_buffer */ + png_bytep save_buffer PNG_DEPSTRUCT; /* buffer for previously + read data */ + png_bytep current_buffer_ptr PNG_DEPSTRUCT; /* current location in + current_buffer */ + png_bytep current_buffer PNG_DEPSTRUCT; /* buffer for recently + used data */ + png_uint_32 push_length PNG_DEPSTRUCT; /* size of current input + chunk */ + png_uint_32 skip_length PNG_DEPSTRUCT; /* bytes to skip in + input data */ + png_size_t save_buffer_size PNG_DEPSTRUCT; /* amount of data now + in save_buffer */ + png_size_t save_buffer_max PNG_DEPSTRUCT; /* total size of + save_buffer */ + png_size_t buffer_size PNG_DEPSTRUCT; /* total amount of + available input data */ + png_size_t current_buffer_size PNG_DEPSTRUCT; /* amount of data now + in current_buffer */ + int process_mode PNG_DEPSTRUCT; /* what push library + is currently doing */ + int cur_palette PNG_DEPSTRUCT; /* current push library + palette index */ + +# ifdef PNG_TEXT_SUPPORTED + png_size_t current_text_size PNG_DEPSTRUCT; /* current size of + text input data */ + png_size_t current_text_left PNG_DEPSTRUCT; /* how much text left + to read in input */ + png_charp current_text PNG_DEPSTRUCT; /* current text chunk + buffer */ + png_charp current_text_ptr PNG_DEPSTRUCT; /* current location + in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* For the Borland special 64K segment handler */ + png_bytepp offset_table_ptr PNG_DEPSTRUCT; + png_bytep offset_table PNG_DEPSTRUCT; + png_uint_16 offset_table_number PNG_DEPSTRUCT; + png_uint_16 offset_table_count PNG_DEPSTRUCT; + png_uint_16 offset_table_count_free PNG_DEPSTRUCT; +#endif + +#ifdef PNG_READ_DITHER_SUPPORTED + png_bytep palette_lookup PNG_DEPSTRUCT; /* lookup table for dithering */ + png_bytep dither_index PNG_DEPSTRUCT; /* index translation for palette + files */ +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist PNG_DEPSTRUCT; /* histogram */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method PNG_DEPSTRUCT; /* heuristic for row + filter selection */ + png_byte num_prev_filters PNG_DEPSTRUCT; /* number of weights + for previous rows */ + png_bytep prev_filters PNG_DEPSTRUCT; /* filter type(s) of + previous row(s) */ + png_uint_16p filter_weights PNG_DEPSTRUCT; /* weight(s) for previous + line(s) */ + png_uint_16p inv_filter_weights PNG_DEPSTRUCT; /* 1/weight(s) for + previous line(s) */ + png_uint_16p filter_costs PNG_DEPSTRUCT; /* relative filter + calculation cost */ + png_uint_16p inv_filter_costs PNG_DEPSTRUCT; /* 1/relative filter + calculation cost */ +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_charp time_buffer PNG_DEPSTRUCT; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + + png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is + responsible for freeing */ + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr PNG_DEPSTRUCT; + png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read + chunk handler */ +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int num_chunk_list PNG_DEPSTRUCT; + png_bytep chunk_list PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status PNG_DEPSTRUCT; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT; + png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT; + png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Changed from png_byte to png_uint_32 at version 1.2.0 */ + png_uint_32 mng_features_permitted PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.7 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_fixed_point int_gamma PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_byte filter_type PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.2.0 */ + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr PNG_DEPSTRUCT; /* user supplied struct for + mem functions */ + png_malloc_ptr malloc_fn PNG_DEPSTRUCT; /* function for + allocating memory */ + png_free_ptr free_fn PNG_DEPSTRUCT; /* function for + freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf PNG_DEPSTRUCT; /* buffer to save current + (unfiltered) row */ + +#ifdef PNG_READ_DITHER_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep dither_sort PNG_DEPSTRUCT; /* working sort array */ + png_bytep index_to_palette PNG_DEPSTRUCT; /* where the original + index currently is + in the palette */ + png_bytep palette_to_index PNG_DEPSTRUCT; /* which original index + points to this + palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type PNG_DEPSTRUCT; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max PNG_DEPSTRUCT; + png_uint_32 user_height_max PNG_DEPSTRUCT; + /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown + * chunks that can be stored (0 means unlimited). + */ + png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + /* Storage for unknown chunk that the library doesn't recognize. */ + png_unknown_chunk unknown_chunk PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.2.26 */ + png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT; + png_uint_32 old_prev_row_size PNG_DEPSTRUCT; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata PNG_DEPSTRUCT; /* buffer for reading chunk data */ + +#ifdef PNG_IO_STATE_SUPPORTED +/* New member added in libpng-1.4.0 */ + png_uint_32 io_state PNG_DEPSTRUCT; +#endif +}; + + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef png_structp version_1_4_1; + +typedef png_struct FAR * FAR * png_structpp; + +/* Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + */ + +/* Returns the version number of the library */ +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; + +extern PNG_EXPORT(png_size_t,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +extern PNG_EXPORT(jmp_buf*, png_set_longjmp_fn) + PNGARG((png_structp png_ptr, png_longjmp_ptr longjmp_fn, size_t + jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif + +/* Reset the compression stream */ +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; +#endif + +/* Write the PNG file signature. */ +extern PNG_EXPORT(void,png_write_sig) PNGARG((png_structp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)) PNG_ALLOCATED; + +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_CONVERT_tIME_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); +#endif +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); +#endif + +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +#define PNG_FILLER_BEFORE 0 +#define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. */ +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +#endif +#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +#define PNG_BACKGROUND_GAMMA_SCREEN 1 +#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Strip the second byte of information from a 16-bit depth file. */ +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_DITHER_SUPPORTED +/* Turn on dithering, and reduce the palette to the number of colors + * available. + */ +extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_dither)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); +#endif +#endif + + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); + +/* Optional call to update the users info structure */ +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); +#endif + +/* Write a row of image data */ +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); + +/* Write a few rows of image data */ +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); + +/* Write the image data */ +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +/* Write the end of the PNG file. */ +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() to say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); +#endif +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); + +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); + +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); + +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); + +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, + png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); + +/* Function to be called when data becomes available */ +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* Function that combines rows. Not very much different than the + * png_combine_row() call. Is this even used????? + */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; +/* Added at libpng version 1.4.0 */ +extern PNG_EXPORT(png_voidp,png_calloc) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; + +/* Added at libpng version 1.2.4 */ +extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; + +/* Frees a pointer allocated by png_malloc() */ +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); +#endif + +#ifndef PNG_NO_ERROR_TEXT +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; + +/* The same, but the chunk name is prepended to the error string. */ +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; + +#else +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN; +#endif + +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +extern PNG_EXPORT(void,png_benign_error) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* Same, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_benign_error) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +extern PNG_EXPORT(void,png_set_benign_errors) PNGARG((png_structp + png_ptr, int allowed)); +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +extern PNG_EXPORT(png_size_t,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image height in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image bit_depth. */ +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image color_type. */ +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image filter_type. */ +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image interlace_type. */ +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image compression_type. */ +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +#endif + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_bKGD_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); +#endif +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); +#endif +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +#endif +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_hIST_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); + +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ +#endif + +#ifdef PNG_iCCP_SUPPORTED +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_sPLT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans_alpha, int num_trans, + png_color_16p trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +#endif + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED */ + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +/* Provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behaviour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep + chunk_name)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +#endif + +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp + png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); +extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp + png_ptr)); +/* Added in libpng-1.4.0 */ +extern PNG_EXPORT(void,png_set_chunk_cache_max) PNGARG((png_structp + png_ptr, png_uint_32 user_chunk_cache_max)); +extern PNG_EXPORT(png_uint_32,png_get_chunk_cache_max) + PNGARG((png_structp png_ptr)); +/* Added in libpng-1.4.1 */ +extern PNG_EXPORT(void,png_set_chunk_malloc_max) PNGARG((png_structp + png_ptr, png_alloc_size_t user_chunk_cache_max)); +extern PNG_EXPORT(png_alloc_size_t,png_get_chunk_malloc_max) + PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +PNG_EXPORT(png_uint_32,png_get_pixels_per_inch) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(png_uint_32,png_get_x_pixels_per_inch) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(png_uint_32,png_get_y_pixels_per_inch) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(float,png_get_x_offset_inches) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(float,png_get_y_offset_inches) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(png_uint_32,png_get_pHYs_dpi) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_io_state) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(png_bytep,png_get_io_chunk_name) + PNGARG((png_structp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +#define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +#define PNG_IO_READING 0x0001 /* currently reading */ +#define PNG_IO_WRITING 0x0002 /* currently writing */ +#define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +#define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +#define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +#define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +#define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +#define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs + */ + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L \ + - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +/* We could make special-case BIG_ENDIAN macros that do direct reads here */ +# define png_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) +# define png_get_uint_16(buf) \ + (((png_uint_32)(*(buf)) << 8) + \ + ((png_uint_32)(*((buf) + 1)))) +#ifdef PNG_GET_INT_32_SUPPORTED +# define png_get_int_32(buf) \ + (((png_int_32)(*(buf)) << 24) + \ + ((png_int_32)(*((buf) + 1)) << 16) + \ + ((png_int_32)(*((buf) + 2)) << 8) + \ + ((png_int_32)(*((buf) + 3)))) +#endif +#else +extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); +#ifdef PNG_GET_INT_32_SUPPORTED +extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); +#endif +#endif +extern PNG_EXPORT(png_uint_32,png_get_uint_31) + PNGARG((png_structp png_ptr, png_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +extern PNG_EXPORT(void,png_save_uint_32) + PNGARG((png_bytep buf, png_uint_32 i)); +extern PNG_EXPORT(void,png_save_int_32) + PNGARG((png_bytep buf, png_int_32 i)); + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +extern PNG_EXPORT(void,png_save_uint_16) + PNGARG((png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ + +/* ************************************************************************* */ + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/GLideNHQ/inc/pngconf.h b/GLideNHQ/inc/pngconf.h new file mode 100644 index 00000000..4aacf9c7 --- /dev/null +++ b/GLideNHQ/inc/pngconf.h @@ -0,0 +1,1510 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.4.1 - February 25, 2010 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_NO_LIMITS_H +# include +#endif + +/* Added at libpng-1.2.9 */ + +/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" + * script. + */ +#ifdef PNG_CONFIGURE_LIBPNG +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +#endif + +/* + * Added at libpng-1.2.8 + * + * PNG_USER_CONFIG has to be defined on the compiler command line. This + * includes the resource compiler for Windows DLL configurations. + */ +#ifdef PNG_USER_CONFIG +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD +# endif +# include "pngusr.h" +#endif + +/* + * If you create a private DLL you need to define in "pngusr.h" the followings: + * #define PNG_USER_PRIVATEBUILD + * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." + * #define PNG_USER_DLLFNAME_POSTFIX + * e.g. // private DLL "libpng13gx.dll" + * #define PNG_USER_DLLFNAME_POSTFIX "gx" + * + * The following macros are also at your disposal if you want to complete the + * DLL VERSIONINFO structure. + * - PNG_USER_VERSIONINFO_COMMENTS + * - PNG_USER_VERSIONINFO_COMPANYNAME + * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS + */ + +#ifdef __STDC__ +# ifdef SPECIALBUILD +# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ + are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") +# endif + +# ifdef PRIVATEBUILD +# pragma message("PRIVATEBUILD is deprecated.\ + Use PNG_USER_PRIVATEBUILD instead.") +# define PNG_USER_PRIVATEBUILD PRIVATEBUILD +# endif +#endif /* __STDC__ */ + +/* End of material added to libpng-1.2.8 */ + +#ifndef PNG_VERSION_INFO_ONLY + +/* This is the size of the compression buffer, and thus the size of + * an IDAT chunk. Make this whatever size you feel is best for your + * machine. One of these will be allocated per png_struct. When this + * is full, it writes the data to the disk, and does some other + * calculations. Making this an extremely small size will slow + * the library down, but you may want to experiment to determine + * where it becomes significant, if you are concerned with memory + * usage. Note that zlib allocates at least 32Kb also. For readers, + * this describes the size of the buffer available to read the data in. + * Unless this gets smaller than the size of a row (compressed), + * it should not make much difference how big this is. + */ + +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +/* Enable if you want a write-only libpng */ + +#ifndef PNG_NO_READ_SUPPORTED +# define PNG_READ_SUPPORTED +#endif + +/* Enable if you want a read-only libpng */ + +#ifndef PNG_NO_WRITE_SUPPORTED +# define PNG_WRITE_SUPPORTED +#endif + +/* Enabled in 1.4.0. */ +#ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +#else +# ifndef PNG_BENIGN_ERRORS_SUPPORTED +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED) +# define PNG_WARNINGS_SUPPORTED +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED) +# define PNG_ERROR_TEXT_SUPPORTED +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED) +# define PNG_CHECK_cHRM_SUPPORTED +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_ALIGNED_MEMORY) && !defined(PNG_ALIGNED_MEMORY_SUPPORTED) +# define PNG_ALIGNED_MEMORY_SUPPORTED +#endif + +/* Enabled by default in 1.2.0. You can disable this if you don't need to + support PNGs that are embedded in MNG datastreams */ +#ifndef PNG_NO_MNG_FEATURES +# ifndef PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED +# endif +#endif + +/* Added at libpng version 1.4.0 */ +#ifndef PNG_NO_FLOATING_POINT_SUPPORTED +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED +# endif +#endif + +/* Added at libpng-1.4.0beta49 for testing (this test is no longer used + in libpng and png_calloc() is always present) + */ +#define PNG_CALLOC_SUPPORTED + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. +#define PNG_MAX_MALLOC_64K + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Special munging to support doing things the 'cygwin' way: + * 'Normal' png-on-win32 defines/defaults: + * PNG_BUILD_DLL -- building dll + * PNG_USE_DLL -- building an application, linking to dll + * (no define) -- building static library, or building an + * application and linking to the static lib + * 'Cygwin' defines/defaults: + * PNG_BUILD_DLL -- (ignored) building the dll + * (no define) -- (ignored) building an application, linking to the dll + * PNG_STATIC -- (ignored) building the static lib, or building an + * application that links to the static lib. + * ALL_STATIC -- (ignored) building various static libs, or building an + * application that links to the static libs. + * Thus, + * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and + * this bit of #ifdefs will define the 'correct' config variables based on + * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but + * unnecessary. + * + * Also, the precedence order is: + * ALL_STATIC (since we can't #undef something outside our namespace) + * PNG_BUILD_DLL + * PNG_STATIC + * (nothing) == PNG_USE_DLL + * + * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent + * of auto-import in binutils, we no longer need to worry about + * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, + * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes + * to __declspec() stuff. However, we DO need to worry about + * PNG_BUILD_DLL and PNG_STATIC because those change some defaults + * such as CONSOLE_IO. + */ +#ifdef __CYGWIN__ +# ifdef ALL_STATIC +# ifdef PNG_BUILD_DLL +# undef PNG_BUILD_DLL +# endif +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifdef PNG_DLL +# undef PNG_DLL +# endif +# ifndef PNG_STATIC +# define PNG_STATIC +# endif +# else +# ifdef PNG_BUILD_DLL +# ifdef PNG_STATIC +# undef PNG_STATIC +# endif +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifndef PNG_DLL +# define PNG_DLL +# endif +# else +# ifdef PNG_STATIC +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifdef PNG_DLL +# undef PNG_DLL +# endif +# else +# ifndef PNG_USE_DLL +# define PNG_USE_DLL +# endif +# ifndef PNG_DLL +# define PNG_DLL +# endif +# endif +# endif +# endif +#endif + +/* This protects us against compilers that run on a windowing system + * and thus don't have or would rather us not use the stdio types: + * stdin, stdout, and stderr. The only one currently used is stderr + * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will + * prevent these from being compiled and used. #defining PNG_NO_STDIO + * will also prevent these, plus will prevent the entire set of stdio + * macros and functions (FILE *, printf, etc.) from being compiled and used, + * unless (PNG_DEBUG > 0) has been #defined. + * + * #define PNG_NO_CONSOLE_IO + * #define PNG_NO_STDIO + */ + +#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED) +# define PNG_STDIO_SUPPORTED +#endif + + +#ifdef PNG_BUILD_DLL +# if !defined(PNG_CONSOLE_IO_SUPPORTED) && !defined(PNG_NO_CONSOLE_IO) +# define PNG_NO_CONSOLE_IO +# endif +#endif + +# ifdef PNG_NO_STDIO +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include +# endif +# endif +# else +# include +# endif + +#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED) +# define PNG_CONSOLE_IO_SUPPORTED +#endif + +/* This macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +#ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +#else + +#ifdef _NO_PROTO +# define PNGARG(arglist) () +#else +# define PNGARG(arglist) arglist +#endif /* _NO_PROTO */ + +#endif /* OF */ + +#endif /* PNGARG */ + +/* Try to determine if we are compiling on a Mac. Note that testing for + * just __MWERKS__ is not good enough, because the Codewarrior is now used + * on non-Mac platforms. + */ +#ifndef MACOS +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS +# endif +#endif + +/* Enough people need this for various reasons to include it here */ +#if !defined(MACOS) && !defined(RISCOS) +# include +#endif + +/* PNG_SETJMP_NOT_SUPPORTED and PNG_NO_SETJMP_SUPPORTED are deprecated. */ +#if !defined(PNG_NO_SETJMP) && \ + !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) +# define PNG_SETJMP_SUPPORTED +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This is an attempt to force a single setjmp behaviour on Linux. If + * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + * + * You can bypass this test if you know that your application uses exactly + * the same setjmp.h that was included when libpng was built. Only define + * PNG_SKIP_SETJMP_CHECK while building your application, prior to the + * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK + * while building a separate libpng library for general use. + */ + +# ifndef PNG_SKIP_SETJMP_CHECK +# ifdef __linux__ +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + /* If you encounter a compiler error here, see the explanation + * near the end of INSTALL. + */ + __pngconf.h__ in libpng already includes setjmp.h; + __dont__ include it again.; +# endif +# endif /* __linux__ */ +# endif /* PNG_SKIP_SETJMP_CHECK */ + + /* Include setjmp.h for error handling */ +# include + +# ifdef __linux__ +# ifdef PNG_SAVE_BSD_SOURCE +# ifdef _BSD_SOURCE +# undef _BSD_SOURCE +# endif +# define _BSD_SOURCE +# undef PNG_SAVE_BSD_SOURCE +# endif +# endif /* __linux__ */ +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef BSD +# include +#else +# include +#endif + +/* Other defines for things like memory and the like can go here. */ + +/* This controls how fine the dithering gets. As this allocates + * a largish chunk of memory (32K), those who are not as concerned + * with dithering quality can decrease some or all of these. + */ +#ifndef PNG_DITHER_RED_BITS +# define PNG_DITHER_RED_BITS 5 +#endif +#ifndef PNG_DITHER_GREEN_BITS +# define PNG_DITHER_GREEN_BITS 5 +#endif +#ifndef PNG_DITHER_BLUE_BITS +# define PNG_DITHER_BLUE_BITS 5 +#endif + +/* This controls how fine the gamma correction becomes when you + * are only interested in 8 bits anyway. Increasing this value + * results in more memory being used, and more pow() functions + * being called to fill in the gamma tables. Don't set this value + * less then 8, and even that may not work (I haven't tested it). + */ + +#ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +#endif + +/* This controls how much a difference in gamma we can tolerate before + * we actually start doing gamma conversion. + */ +#ifndef PNG_GAMMA_THRESHOLD +# define PNG_GAMMA_THRESHOLD 0.05 +#endif + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + */ + +#ifndef PNG_CONST +# ifndef PNG_NO_CONST +# define PNG_CONST const +# else +# define PNG_CONST +# endif +#endif + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to and #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. Some of these depend upon some others being + * defined. I haven't figured out all the interactions here, so you may + * have to experiment awhile to get everything to compile. If you are + * creating or using a shared library, you probably shouldn't touch this, + * as it will affect the size of the structures, and this will cause bad + * things to happen if the library and/or application ever change. + */ + +/* Any features you will not be using can be undef'ed here */ + +/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user + * to turn it off with PNG_NO_READ|WRITE_TRANSFORMS on the compile line, + * then pick and choose which ones to define without having to edit this + * file. It is safe to use the PNG_NO_READ|WRITE_TRANSFORMS + * if you only want to have a png-compliant reader/writer but don't need + * any of the extra transformations. This saves about 80 kbytes in a + * typical installation of the library. (PNG_NO_* form added in version + * 1.0.1c, for consistency; PNG_*_TRANSFORMS_NOT_SUPPORTED deprecated in + * 1.4.0) + */ + +/* Ignore attempt to turn off both floating and fixed point support */ +#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ + !defined(PNG_NO_FIXED_POINT_SUPPORTED) +# define PNG_FIXED_POINT_SUPPORTED +#endif + +#ifdef PNG_READ_SUPPORTED + +/* PNG_READ_TRANSFORMS_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_TRANSFORMS) +# define PNG_READ_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_READ_EXPAND +# define PNG_READ_EXPAND_SUPPORTED +# endif +# ifndef PNG_NO_READ_SHIFT +# define PNG_READ_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACK +# define PNG_READ_PACK_SUPPORTED +# endif +# ifndef PNG_NO_READ_BGR +# define PNG_READ_BGR_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP +# define PNG_READ_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACKSWAP +# define PNG_READ_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT +# define PNG_READ_INVERT_SUPPORTED +# endif +#if 0 /* removed from libpng-1.4.0 */ +# ifndef PNG_NO_READ_DITHER +# define PNG_READ_DITHER_SUPPORTED +# endif +#endif /* 0 */ +# ifndef PNG_NO_READ_BACKGROUND +# define PNG_READ_BACKGROUND_SUPPORTED +# endif +# ifndef PNG_NO_READ_16_TO_8 +# define PNG_READ_16_TO_8_SUPPORTED +# endif +# ifndef PNG_NO_READ_FILLER +# define PNG_READ_FILLER_SUPPORTED +# endif +# ifndef PNG_NO_READ_GAMMA +# define PNG_READ_GAMMA_SUPPORTED +# endif +# ifndef PNG_NO_READ_GRAY_TO_RGB +# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP_ALPHA +# define PNG_READ_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT_ALPHA +# define PNG_READ_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_STRIP_ALPHA +# define PNG_READ_STRIP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_USER_TRANSFORM +# define PNG_READ_USER_TRANSFORM_SUPPORTED +# endif +# ifndef PNG_NO_READ_RGB_TO_GRAY +# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_NO_PROGRESSIVE_READ) && \ + !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following define: */ + +#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ + +/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */ +#if !defined(PNG_NO_SEQUENTIAL_READ) && \ + !defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \ + !defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED) +# define PNG_SEQUENTIAL_READ_SUPPORTED +#endif + +#ifndef PNG_NO_READ_COMPOSITE_NODIV +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# endif +#endif + +#if !defined(PNG_NO_GET_INT_32) || defined(PNG_READ_oFFS_SUPPORTED) || \ + defined(PNG_READ_pCAL_SUPPORTED) +# ifndef PNG_GET_INT_32_SUPPORTED +# define PNG_GET_INT_32_SUPPORTED +# endif +#endif + +#endif /* PNG_READ_SUPPORTED */ + +#ifdef PNG_WRITE_SUPPORTED + +/* PNG_WRITE_TRANSFORMS_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_TRANSFORMS) +# define PNG_WRITE_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_WRITE_SHIFT +# define PNG_WRITE_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACK +# define PNG_WRITE_PACK_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_BGR +# define PNG_WRITE_BGR_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_SWAP +# define PNG_WRITE_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACKSWAP +# define PNG_WRITE_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT +# define PNG_WRITE_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_FILLER +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# endif +# ifndef PNG_NO_WRITE_SWAP_ALPHA +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT_ALPHA +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_USER_TRANSFORM +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ + !defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* This is not required for PNG-compliant encoders, but can cause + * trouble if left undefined + */ +# define PNG_WRITE_INTERLACING_SUPPORTED +#endif + +#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ + !defined(PNG_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#endif + +#ifndef PNG_NO_WRITE_FLUSH +# define PNG_WRITE_FLUSH_SUPPORTED +#endif + +#if !defined(PNG_NO_SAVE_INT_32) || defined(PNG_WRITE_oFFS_SUPPORTED) || \ + defined(PNG_WRITE_pCAL_SUPPORTED) +# ifndef PNG_SAVE_INT_32_SUPPORTED +# define PNG_SAVE_INT_32_SUPPORTED +# endif +#endif + +#endif /* PNG_WRITE_SUPPORTED */ + +#define PNG_NO_ERROR_NUMBERS + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +# ifndef PNG_NO_USER_TRANSFORM_PTR +# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# endif +#endif + +#if defined(PNG_STDIO_SUPPORTED) && !defined(PNG_TIME_RFC1123_SUPPORTED) +# define PNG_TIME_RFC1123_SUPPORTED +#endif + +/* This adds extra functions in pngget.c for accessing data from the + * info pointer (added in version 0.99) + * png_get_image_width() + * png_get_image_height() + * png_get_bit_depth() + * png_get_color_type() + * png_get_compression_type() + * png_get_filter_type() + * png_get_interlace_type() + * png_get_pixel_aspect_ratio() + * png_get_pixels_per_meter() + * png_get_x_offset_pixels() + * png_get_y_offset_pixels() + * png_get_x_offset_microns() + * png_get_y_offset_microns() + */ +#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) +# define PNG_EASY_ACCESS_SUPPORTED +#endif + +/* Added at libpng-1.2.0 */ +#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) +# define PNG_USER_MEM_SUPPORTED +#endif + +/* Added at libpng-1.2.6 */ +#ifndef PNG_NO_SET_USER_LIMITS +# ifndef PNG_SET_USER_LIMITS_SUPPORTED +# define PNG_SET_USER_LIMITS_SUPPORTED +# endif + /* Feature added at libpng-1.4.0, this flag added at 1.4.1 */ +# ifndef PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +# define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +# endif + /* Feature added at libpng-1.4.1, this flag added at 1.4.1 */ +# ifndef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +# define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +# endif +#endif + +/* Added at libpng-1.2.43 */ +#ifndef PNG_USER_LIMITS_SUPPORTED +# ifndef PNG_NO_USER_LIMITS +# define PNG_USER_LIMITS_SUPPORTED +# endif +#endif + +/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGs no matter + * how large, set these two limits to 0x7fffffffL + */ +#ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +#endif +#ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +#endif + +/* Added at libpng-1.2.43. To accept all valid PNGs no matter + * how large, set these two limits to 0. + */ +#ifndef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 0 +#endif + +/* Added at libpng-1.2.43 */ +#ifndef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 0 +#endif + +/* Added at libpng-1.4.0 */ +#if !defined(PNG_NO_IO_STATE) && !defined(PNG_IO_STATE_SUPPORTED) +# define PNG_IO_STATE_SUPPORTED +#endif + +#ifndef PNG_LITERAL_SHARP +# define PNG_LITERAL_SHARP 0x23 +#endif +#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET +# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b +#endif +#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET +# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d +#endif +#ifndef PNG_STRING_NEWLINE +#define PNG_STRING_NEWLINE "\n" +#endif + +/* These are currently experimental features, define them if you want */ + +/* Very little testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# endif +#endif +*/ + +/* This is only for PowerPC big-endian and 680x0 systems */ +/* some testing */ +/* +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +# define PNG_READ_BIG_ENDIAN_SUPPORTED +#endif +*/ + +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# define PNG_USE_READ_MACROS +#endif + +/* Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING */ + +#if !defined(PNG_NO_POINTER_INDEXING) && \ + !defined(PNG_POINTER_INDEXING_SUPPORTED) +# define PNG_POINTER_INDEXING_SUPPORTED +#endif + + +/* Any chunks you are not interested in, you can undef here. The + * ones that allocate memory may be expecially important (hIST, + * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info + * a bit smaller. + */ + +/* The size of the png_text structure changed in libpng-1.0.6 when + * iTXt support was added. iTXt support was turned off by default through + * libpng-1.2.x, to support old apps that malloc the png_text structure + * instead of calling png_set_text() and letting libpng malloc it. It + * was turned on by default in libpng-1.4.0. + */ + +/* PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ +#if defined(PNG_READ_SUPPORTED) && \ + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) +# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#endif + +/* PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ +#if defined(PNG_WRITE_SUPPORTED) && \ + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) +# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_READ_TEXT +# define PNG_NO_READ_iTXt +# define PNG_NO_READ_tEXt +# define PNG_NO_READ_zTXt +#endif + +#ifndef PNG_NO_READ_bKGD +# define PNG_READ_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +#endif +#ifndef PNG_NO_READ_cHRM +# define PNG_READ_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +#endif +#ifndef PNG_NO_READ_gAMA +# define PNG_READ_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +#endif +#ifndef PNG_NO_READ_hIST +# define PNG_READ_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +#endif +#ifndef PNG_NO_READ_iCCP +# define PNG_READ_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +#endif +#ifndef PNG_NO_READ_iTXt +# ifndef PNG_READ_iTXt_SUPPORTED +# define PNG_READ_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_oFFs +# define PNG_READ_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +#endif +#ifndef PNG_NO_READ_pCAL +# define PNG_READ_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_sCAL +# define PNG_READ_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_pHYs +# define PNG_READ_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +#endif +#ifndef PNG_NO_READ_sBIT +# define PNG_READ_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sPLT +# define PNG_READ_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sRGB +# define PNG_READ_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +#endif +#ifndef PNG_NO_READ_tEXt +# define PNG_READ_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_tIME +# define PNG_READ_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +#endif +#ifndef PNG_NO_READ_tRNS +# define PNG_READ_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +#endif +#ifndef PNG_NO_READ_zTXt +# define PNG_READ_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_OPT_PLTE +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ +#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ + defined(PNG_READ_zTXt_SUPPORTED) +# define PNG_READ_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +#endif + +#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifndef PNG_NO_READ_UNKNOWN_CHUNKS +# ifndef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_READ_USER_CHUNKS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_USER_CHUNKS +# ifndef PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_READ_USER_CHUNKS_SUPPORTED +# endif +# ifndef PNG_USER_CHUNKS_SUPPORTED +# define PNG_USER_CHUNKS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_WRITE_TEXT +# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_tEXt +# define PNG_NO_WRITE_zTXt +#endif +#ifndef PNG_NO_WRITE_bKGD +# define PNG_WRITE_bKGD_SUPPORTED +# ifndef PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_cHRM +# define PNG_WRITE_cHRM_SUPPORTED +# ifndef PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_gAMA +# define PNG_WRITE_gAMA_SUPPORTED +# ifndef PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_hIST +# define PNG_WRITE_hIST_SUPPORTED +# ifndef PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iCCP +# define PNG_WRITE_iCCP_SUPPORTED +# ifndef PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iTXt +# ifndef PNG_WRITE_iTXt_SUPPORTED +# define PNG_WRITE_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_oFFs +# define PNG_WRITE_oFFs_SUPPORTED +# ifndef PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pCAL +# define PNG_WRITE_pCAL_SUPPORTED +# ifndef PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sCAL +# define PNG_WRITE_sCAL_SUPPORTED +# ifndef PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pHYs +# define PNG_WRITE_pHYs_SUPPORTED +# ifndef PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sBIT +# define PNG_WRITE_sBIT_SUPPORTED +# ifndef PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sPLT +# define PNG_WRITE_sPLT_SUPPORTED +# ifndef PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sRGB +# define PNG_WRITE_sRGB_SUPPORTED +# ifndef PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tEXt +# define PNG_WRITE_tEXt_SUPPORTED +# ifndef PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tIME +# define PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tRNS +# define PNG_WRITE_tRNS_SUPPORTED +# ifndef PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_zTXt +# define PNG_WRITE_zTXt_SUPPORTED +# ifndef PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +# endif +#endif +#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ + defined(PNG_WRITE_zTXt_SUPPORTED) +# define PNG_WRITE_TEXT_SUPPORTED +# ifndef PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +# endif +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_NO_CONVERT_tIME +# ifndef _WIN32_WCE +/* The "tm" structure is not supported on WindowsCE */ +# ifndef PNG_CONVERT_tIME_SUPPORTED +# define PNG_CONVERT_tIME_SUPPORTED +# endif +# endif +# endif +#endif + +#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifndef PNG_NO_WRITE_FILTER +# ifndef PNG_WRITE_FILTER_SUPPORTED +# define PNG_WRITE_FILTER_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +/* Turn this off to disable png_read_png() and + * png_write_png() and leave the row_pointers member + * out of the info structure. + */ +#ifndef PNG_NO_INFO_IMAGE +# define PNG_INFO_IMAGE_SUPPORTED +#endif + +/* Need the time information for converting tIME chunks */ +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on WindowsCE */ +# include +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. + */ + +#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) +typedef unsigned int png_uint_32; +typedef int png_int_32; +#else +typedef unsigned long png_uint_32; +typedef long png_int_32; +#endif +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +#ifdef PNG_NO_SIZE_T + typedef unsigned int png_size_t; +#else + typedef size_t png_size_t; +#endif +#define png_sizeof(x) sizeof(x) + +/* The following is needed for medium model support. It cannot be in the + * pngpriv.h header. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + * defines FAR. (SJT) + */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#ifdef FAR +# ifdef M_I86MM +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + to fixed-point with a multiple of 100,000, e.g., int_gamma */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; + +#ifndef PNG_NO_STDIO +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +/* Define PNG_BUILD_DLL if the module being built is a Windows + * LIBPNG DLL. + * + * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. + * It is equivalent to Microsoft predefined macro _DLL that is + * automatically defined when you compile using the share + * version of the CRT (C Run-Time library) + * + * The cygwin mods make this behavior a little different: + * Define PNG_BUILD_DLL if you are building a dll for use with cygwin + * Define PNG_STATIC if you are building a static library for use with cygwin, + * -or- if you are building an application that you want to link to the + * static library. + * PNG_USE_DLL is defined by default (no user action needed) unless one of + * the other flags is defined. + */ + +#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) +# define PNG_DLL +#endif + +#ifdef __CYGWIN__ +# undef PNGAPI +# define PNGAPI __cdecl +# undef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#define PNG_USE_LOCAL_ARRAYS /* Not used in libpng, defined for legacy apps */ + +/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", + * you may get warnings regarding the linkage of png_zalloc and png_zfree. + * Don't ignore those warnings; you must also reset the default calling + * convention in your compiler to match your PNGAPI, and you must build + * zlib and your applications the same way you build libpng. + */ + +#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) +# ifndef PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF +# endif +#endif + +#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) +# define PNG_IMPEXP +#endif + +#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) + +# ifndef PNGAPI +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif +# endif + +# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP +# endif + +# ifndef PNG_IMPEXP + +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol + + /* Borland/Microsoft */ +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif + +# ifndef PNG_IMPEXP +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif +# endif /* PNG_IMPEXP */ +#else /* !(DLL || non-cygwin WINDOWS) */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# ifndef PNGAPI +# define PNGAPI _System +# endif +# else +# if 0 /* ... other platforms, with other meanings */ +# endif +# endif +#endif + +#ifndef PNGAPI +# define PNGAPI +#endif +#ifndef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#ifdef PNG_BUILDSYMS +# ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END +# endif +#endif + +#ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. + */ +# ifdef __GNUC__ +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif /* PNG_PRIVATE */ +# endif /* __GNUC__ */ +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif + +/* Users may want to use these so they are not private. Any library + * functions that are passed far data must be model-independent. + */ + +/* memory model/platform independent fns */ +#ifndef PNG_ABORT +# ifdef _WINDOWS_ +# define PNG_ABORT() ExitProcess(0) +# else +# define PNG_ABORT() abort() +# endif +#endif + +#ifdef USE_FAR_KEYWORD +/* Use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_strcpy _fstrcpy +# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +# define png_sprintf sprintf +#else +# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy lstrcpyA +# define png_strncpy lstrcpynA +# define png_strlen lstrlenA +# define png_memcmp memcmp +# define png_memcpy CopyMemory +# define png_memset memset +# define png_sprintf wsprintfA +# else +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy strcpy +# define png_strncpy strncpy /* Added to v 1.2.6 */ +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +# define png_sprintf sprintf +# ifndef PNG_NO_SNPRINTF +# ifdef _MSC_VER +# define png_snprintf _snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 _snprintf +# define png_snprintf6 _snprintf +# else +# define png_snprintf snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 snprintf +# define png_snprintf6 snprintf +# endif +# else + /* You don't have or don't want to use snprintf(). Caution: Using + * sprintf instead of snprintf exposes your application to accidental + * or malevolent buffer overflows. If you don't have snprintf() + * as a general rule you should provide one (you can get one from + * Portable OpenSSH). + */ +# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) +# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) +# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ + sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) +# endif +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, + * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 + * to png_alloc_size_t are not necessary; in fact, it is recommended + * not to use them at all so that the compiler can complain when something + * turns out to be problematic. + * Casts in the other direction (from png_alloc_size_t to png_size_t or + * png_uint_32) should be explicitly applied; however, we do not expect + * to encounter practical situations that require such conversions. + */ +#if defined(__TURBOC__) && !defined(__FLAT__) +# define png_mem_alloc farmalloc +# define png_mem_free farfree + typedef unsigned long png_alloc_size_t; +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) +# define png_mem_alloc(s) halloc(s, 1) +# define png_mem_free hfree + typedef unsigned long png_alloc_size_t; +# else +# if defined(_WINDOWS_) && (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) +# define png_mem_alloc(s) HeapAlloc(GetProcessHeap(), 0, s) +# define png_mem_free(p) HeapFree(GetProcessHeap(), 0, p) + typedef DWORD png_alloc_size_t; +# else +# define png_mem_alloc malloc +# define png_mem_free free + typedef png_size_t png_alloc_size_t; +# endif +# endif +#endif +/* End of memory model/platform independent support */ + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + + +/* Added at libpng-1.2.8 */ +#endif /* PNG_VERSION_INFO_ONLY */ + +#endif /* PNGCONF_H */ diff --git a/GLideNHQ/inc/zconf.h b/GLideNHQ/inc/zconf.h new file mode 100644 index 00000000..03a9431c --- /dev/null +++ b/GLideNHQ/inc/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$ */ + +#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/GLideNHQ/inc/zlib.h b/GLideNHQ/inc/zlib.h new file mode 100644 index 00000000..02281792 --- /dev/null +++ b/GLideNHQ/inc/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/GLideNHQ/lib/dxtn.lib b/GLideNHQ/lib/dxtn.lib new file mode 100644 index 0000000000000000000000000000000000000000..960604a404f5d49223ba4c6321925f85bd42fd2d GIT binary patch literal 126254 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

3(~akVa`PtCfFWpp4})96I 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 literal 0 HcmV?d00001 diff --git a/GLideNHQ/lib/dxtnd.lib b/GLideNHQ/lib/dxtnd.lib new file mode 100644 index 0000000000000000000000000000000000000000..5234791f10f2bc48f1cf54ad18f4236b29c7e3ab GIT binary patch literal 67224 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 b;n+_{;#q^)#3gE!okpTI*`Xn7^NM~08-Mqh literal 0 HcmV?d00001 diff --git a/GLideNHQ/lib/libpng.lib b/GLideNHQ/lib/libpng.lib new file mode 100644 index 0000000000000000000000000000000000000000..fe82d31d03d49847e9f2d9ff80b40a54daddac83 GIT binary patch literal 322288 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¨h$uF}P#AS((xu<+` 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 K$y*A#qyG=InEGx2 literal 0 HcmV?d00001 diff --git a/GLideNHQ/lib/libpngd.lib b/GLideNHQ/lib/libpngd.lib new file mode 100644 index 0000000000000000000000000000000000000000..4cfdfc6188c43e186dd2046b1816e24d2ed35182 GIT binary patch literal 923454 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 z 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

QC&6-YvqK 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 literal 0 HcmV?d00001 diff --git a/GLideNHQ/tc-1.1+/Makefile.gcc b/GLideNHQ/tc-1.1+/Makefile.gcc new file mode 100644 index 00000000..9e270b60 --- /dev/null +++ b/GLideNHQ/tc-1.1+/Makefile.gcc @@ -0,0 +1,94 @@ +# Texture compression Linux makefile +# Version: 1.1+ +# +# Copyright (C) 2004 Daniel Borca All Rights Reserved. +# +# Copyright (C) 2007 Hiroshi Morii +# Added support for RGBA input, DXT3,5 workaround for ATI Radeons, +# and _mesa_upscale_teximage2d speedup. +# +# this is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# this is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Make; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + +# +# Available options: +# +# Environment variables: +# ARGB=1 enable support for ARGB inputs +# default = no +# RADEON=1 enable DXT3,5 workaround for ATI Radeon +# default = no +# YUV=1 use YUV to determine representative color +# default = no +# +# Targets: +# all: build dynamic module +# clean: remove object files +# realclean: remove all generated files +# + + +.PHONY: all clean realclean + +DLLNAME = libdxtn.a + +CC = gcc +CFLAGS = -Wall -W -pedantic -ansi -Wno-long-long +CFLAGS += -O3 -ffast-math -funroll-loops +#CFLAGS += -fomit-frame-pointer -fexpensive-optimizations +CFLAGS += -fPIC -DPIC +AR = ar +RANLIB = ranlib + +ifdef ARGB +CFLAGS += -DARGB +endif + +ifdef RADEON +CFLAGS += -DRADEON +endif + +ifdef YUV +CFLAGS += -DYUV +endif + +LD = gcc +LDFLAGS = -static +LDLIBS = + +SOURCES = \ + fxt1.c \ + dxtn.c \ + wrapper.c \ + texstore.c + +OBJECTS = $(SOURCES:.c=.o) + +.c.o: + $(CC) -o $@ $(CFLAGS) -c $< + +all: $(DLLNAME) + +$(DLLNAME): $(OBJECTS) + $(AR) rc $@ $(OBJECTS) + $(RANLIB) $@ + +clean: + -$(RM) $(OBJECTS) + +realclean: clean + -$(RM) $(DLLNAME) + +-include depend diff --git a/GLideNHQ/tc-1.1+/Makefile.vc8 b/GLideNHQ/tc-1.1+/Makefile.vc8 new file mode 100644 index 00000000..a78fd694 --- /dev/null +++ b/GLideNHQ/tc-1.1+/Makefile.vc8 @@ -0,0 +1,143 @@ +# Texture compression Win32 makefile +# Version: 1.1+ +# +# Copyright (C) 2004 Daniel Borca All Rights Reserved. +# +# Copyright (C) 2007 Hiroshi Morii +# Added support for RGBA input, DXT3,5 workaround for ATI Radeons, +# and _mesa_upscale_teximage2d speedup. +# +# this is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# this is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Make; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +# This makefile MUST be processed by GNU make!!! +# +# Available options: +# +# Environment variables: +# DEBUG=1 enable debugging checks and messages +# default = no +# DLL=1 build dll +# default = no +# ARGB=1 enable support for ARGB inputs +# default = no +# RADEON=1 enable DXT3,5 workaround for ATI Radeon +# default = no +# YUV=1 use YUV to determine representative color +# default = no +# +# Targets: +# all: build everything +# clean: remove object files +# realclean: remove all generated files +# + +.PHONY: all clean realclean +.SUFFIXES: .c .obj + +ifdef DLL +DLLNAME = dxtn.dll +else +ifdef DEBUG +DLLNAME = dxtnd.lib +else +DLLNAME = dxtn.lib +endif +endif + +CC = cl +AS = nasm +ifdef DLL +LD = _link +else +LD = lib +endif +RC = rc + +#ifeq ($(wildcard $(addsuffix /rm.exe,$(subst ;, ,$(PATH)))),) +#UNLINK = del $(subst /,\,$(1)) +#else +UNLINK = $(RM) $(1) +#endif + +LDFLAGS = -nologo -machine:X86 -nodefaultlib + +ifdef DLL +LDFLAGS += -dll -opt:WIN98 +endif + +ASFLAGS = -O6 -fwin32 -D__WIN32__ --prefix _ +ASFLAGS += $(CDEFS) + +CFLAGS = -nologo -W3 -WX -D__MSC__=1 -D_CRT_SECURE_NO_DEPRECATE + +ifdef ARGB +CFLAGS += -DARGB +endif + +ifdef RADEON +CFLAGS += -DRADEON +endif + +ifdef YUV +CFLAGS += -DYUV +endif + +ifdef DLL +CFLAGS += -D__WIN32__ +LDLIBS = user32.lib kernel32.lib +endif + +ifdef DEBUG +CFLAGS += -MTd -Zi -DDEBUG +#LDFLAGS += -debug +ifdef DLL +LDLIBS += LIBCMTD.lib +endif +OPTFLAGS ?= -Od +else +CFLAGS += -DNDEBUG -MT -GL +LDFLAGS += -ltcg:STATUS +ifdef DLL +LDLIBS += LIBCMT.lib +endif +OPTFLAGS ?= -O2 +endif + +CFLAGS += -I. +CFLAGS += $(CDEFS) $(OPTFLAGS) + +SOURCE = \ + fxt1.c \ + dxtn.c \ + wrapper.c \ + texstore.c + +OBJECTS = $(SOURCE:.c=.obj) + +.c.obj: + $(CC) -Fo$@ $(CFLAGS) -c $< + +all: $(DLLNAME) + +$(DLLNAME): $(OBJECTS) + $(LD) -out:$@ $(LDFLAGS) $^ $(LDLIBS) + +clean: + -$(RM) *.obj + +realclean: clean + -$(RM) $(DLLNAME) + -$(RM) *.pdb diff --git a/GLideNHQ/tc-1.1+/dxtn.c b/GLideNHQ/tc-1.1+/dxtn.c new file mode 100644 index 00000000..e2d335ae --- /dev/null +++ b/GLideNHQ/tc-1.1+/dxtn.c @@ -0,0 +1,884 @@ +/* + * DXTn codec + * Version: 1.1 + * + * Copyright (C) 2004 Daniel Borca All Rights Reserved. + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Copyright (C) 2007 Hiroshi Morii + * Added support for ARGB inputs, DXT3,5 workaround for ATI Radeons, and + * YUV conversions to determine representative colors. + */ + + +#include +#include +#include + +#include + +#include "types.h" +#include "internal.h" +#include "dxtn.h" + + +/***************************************************************************\ + * DXTn encoder + * + * The encoder was built by reversing the decoder, + * and is vaguely based on FXT1 codec. Note that this code + * is merely a proof of concept, since it is highly UNoptimized! +\***************************************************************************/ + + +#define MAX_COMP 4 /* ever needed maximum number of components in texel */ +#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */ +#define N_TEXELS 16 /* number of texels in a block (always 16) */ +#define COLOR565(v) (word)((((v)[RCOMP] & 0xf8) << 8) | (((v)[GCOMP] & 0xfc) << 3) | ((v)[BCOMP] >> 3)) + + +static const int dxtn_color_tlat[2][4] = { + { 0, 2, 3, 1 }, + { 0, 2, 1, 3 } +}; + +static const int dxtn_alpha_tlat[2][8] = { + { 0, 2, 3, 4, 5, 6, 7, 1 }, + { 0, 2, 3, 4, 5, 1, 6, 7 } +}; + + +static void +dxt1_rgb_quantize (dword *cc, const byte *lines[], int comps) +{ + float b, iv[MAX_COMP]; /* interpolation vector */ + + dword hi; /* high doubleword */ + int color0, color1; + int n_vect; + const int n_comp = 3; + int black = 0; + +#ifndef YUV + int minSum = 2000; /* big enough */ +#else + int minSum = 2000000; +#endif + int maxSum = -1; /* small enough */ + int minCol = 0; /* phoudoin: silent compiler! */ + int maxCol = 0; /* phoudoin: silent compiler! */ + + byte input[N_TEXELS][MAX_COMP]; + int i, k, l; + + /* make the whole block opaque */ + /* we will NEVER reference ACOMP of any pixel */ + + /* 4 texels each line */ +#ifndef ARGB + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + for (i = 0; i < comps; i++) { + input[k + l * 4][i] = *lines[l]++; + } + } + } +#else + /* H.Morii - support for ARGB inputs */ + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + input[k + l * 4][2] = *lines[l]++; + input[k + l * 4][1] = *lines[l]++; + input[k + l * 4][0] = *lines[l]++; + if (comps == 4) input[k + l * 4][3] = *lines[l]++; + } + } +#endif + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + for (k = 0; k < N_TEXELS; k++) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + /* RGB to YUV conversion according to CCIR 601 specs + * Y = 0.299R+0.587G+0.114B + * U = 0.713(R - Y) = 0.500R-0.419G-0.081B + * V = 0.564(B - Y) = -0.169R-0.331G+0.500B + */ + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minCol = k; + } + if (maxSum < sum) { + maxSum = sum; + maxCol = k; + } + if (sum == 0) { + black = 1; + } + } + + color0 = COLOR565(input[minCol]); + color1 = COLOR565(input[maxCol]); + + if (color0 == color1) { + /* we'll use 3-vector */ + cc[0] = color0 | (color1 << 16); + hi = black ? -1 : 0; + } else { + if (black && ((color0 == 0) || (color1 == 0))) { + /* we still can use 4-vector */ + black = 0; + } + + if (black ^ (color0 <= color1)) { + int aux; + aux = color0; + color0 = color1; + color1 = aux; + aux = minCol; + minCol = maxCol; + maxCol = aux; + } + n_vect = (color0 <= color1) ? 2 : 3; + + MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]); + + /* add in texels */ + cc[0] = color0 | (color1 << 16); + hi = 0; + for (k = N_TEXELS - 1; k >= 0; k--) { + int texel = 3; + int sum = 0; + if (black) { + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } + } + if (!black || sum) { + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + texel = dxtn_color_tlat[black][texel]; + } + /* add in texel */ + hi <<= 2; + hi |= texel; + } + } + cc[1] = hi; +} + + +static void +dxt1_rgba_quantize (dword *cc, const byte *lines[], int comps) +{ + float b, iv[MAX_COMP]; /* interpolation vector */ + + dword hi; /* high doubleword */ + int color0, color1; + int n_vect; + const int n_comp = 3; + int transparent = 0; + +#ifndef YUV + int minSum = 2000; /* big enough */ +#else + int minSum = 2000000; +#endif + int maxSum = -1; /* small enough */ + int minCol = 0; /* phoudoin: silent compiler! */ + int maxCol = 0; /* phoudoin: silent compiler! */ + + byte input[N_TEXELS][MAX_COMP]; + int i, k, l; + + if (comps == 3) { + /* make the whole block opaque */ + memset(input, -1, sizeof(input)); + } + + /* 4 texels each line */ +#ifndef ARGB + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + for (i = 0; i < comps; i++) { + input[k + l * 4][i] = *lines[l]++; + } + } + } +#else + /* H.Morii - support for ARGB inputs */ + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + input[k + l * 4][2] = *lines[l]++; + input[k + l * 4][1] = *lines[l]++; + input[k + l * 4][0] = *lines[l]++; + if (comps == 4) input[k + l * 4][3] = *lines[l]++; + } + } +#endif + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + for (k = 0; k < N_TEXELS; k++) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minCol = k; + } + if (maxSum < sum) { + maxSum = sum; + maxCol = k; + } + if (input[k][ACOMP] < 128) { + transparent = 1; + } + } + + color0 = COLOR565(input[minCol]); + color1 = COLOR565(input[maxCol]); + + if (color0 == color1) { + /* we'll use 3-vector */ + cc[0] = color0 | (color1 << 16); + hi = transparent ? -1 : 0; + } else { + if (transparent ^ (color0 <= color1)) { + int aux; + aux = color0; + color0 = color1; + color1 = aux; + aux = minCol; + minCol = maxCol; + maxCol = aux; + } + n_vect = (color0 <= color1) ? 2 : 3; + + MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]); + + /* add in texels */ + cc[0] = color0 | (color1 << 16); + hi = 0; + for (k = N_TEXELS - 1; k >= 0; k--) { + int texel = 3; + if (input[k][ACOMP] >= 128) { + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + texel = dxtn_color_tlat[transparent][texel]; + } + /* add in texel */ + hi <<= 2; + hi |= texel; + } + } + cc[1] = hi; +} + + +static void +dxt3_rgba_quantize (dword *cc, const byte *lines[], int comps) +{ + float b, iv[MAX_COMP]; /* interpolation vector */ + + dword lolo, lohi; /* low quadword: lo dword, hi dword */ + dword hihi; /* high quadword: high dword */ + int color0, color1; + const int n_vect = 3; + const int n_comp = 3; + +#ifndef YUV + int minSum = 2000; /* big enough */ +#else + int minSum = 2000000; +#endif + int maxSum = -1; /* small enough */ + int minCol = 0; /* phoudoin: silent compiler! */ + int maxCol = 0; /* phoudoin: silent compiler! */ + + byte input[N_TEXELS][MAX_COMP]; + int i, k, l; + + if (comps == 3) { + /* make the whole block opaque */ + memset(input, -1, sizeof(input)); + } + + /* 4 texels each line */ +#ifndef ARGB + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + for (i = 0; i < comps; i++) { + input[k + l * 4][i] = *lines[l]++; + } + } + } +#else + /* H.Morii - support for ARGB inputs */ + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + input[k + l * 4][2] = *lines[l]++; + input[k + l * 4][1] = *lines[l]++; + input[k + l * 4][0] = *lines[l]++; + if (comps == 4) input[k + l * 4][3] = *lines[l]++; + } + } +#endif + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + for (k = 0; k < N_TEXELS; k++) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minCol = k; + } + if (maxSum < sum) { + maxSum = sum; + maxCol = k; + } + } + + /* add in alphas */ + lolo = lohi = 0; + for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { + /* add in alpha */ + lohi <<= 4; + lohi |= input[k][ACOMP] >> 4; + } + cc[1] = lohi; + for (; k >= 0; k--) { + /* add in alpha */ + lolo <<= 4; + lolo |= input[k][ACOMP] >> 4; + } + cc[0] = lolo; + + color0 = COLOR565(input[minCol]); + color1 = COLOR565(input[maxCol]); + +#ifdef RADEON + /* H.Morii - Workaround for ATI Radeon + * According to the OpenGL EXT_texture_compression_s3tc specs, + * the encoding of the RGB components for DXT3 and DXT5 formats + * use the non-transparent encodings of DXT1 but treated as + * though color0 > color1, regardless of the actual values of + * color0 and color1. ATI Radeons however require the values to + * be color0 > color1. + */ + if (color0 < color1) { + int aux; + aux = color0; + color0 = color1; + color1 = aux; + aux = minCol; + minCol = maxCol; + maxCol = aux; + } +#endif + + cc[2] = color0 | (color1 << 16); + + hihi = 0; + if (color0 != color1) { + MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]); + + /* add in texels */ + for (k = N_TEXELS - 1; k >= 0; k--) { + int texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + texel = dxtn_color_tlat[0][texel]; + /* add in texel */ + hihi <<= 2; + hihi |= texel; + } + } + cc[3] = hihi; +} + + +static void +dxt5_rgba_quantize (dword *cc, const byte *lines[], int comps) +{ + float b, iv[MAX_COMP]; /* interpolation vector */ + + qword lo; /* low quadword */ + dword hihi; /* high quadword: high dword */ + int color0, color1; + const int n_vect = 3; + const int n_comp = 3; + +#ifndef YUV + int minSum = 2000; /* big enough */ +#else + int minSum = 2000000; +#endif + int maxSum = -1; /* small enough */ + int minCol = 0; /* phoudoin: silent compiler! */ + int maxCol = 0; /* phoudoin: silent compiler! */ + int alpha0 = 2000; /* big enough */ + int alpha1 = -1; /* small enough */ + int anyZero = 0, anyOne = 0; + int a_vect; + + byte input[N_TEXELS][MAX_COMP]; + int i, k, l; + + if (comps == 3) { + /* make the whole block opaque */ + memset(input, -1, sizeof(input)); + } + + /* 4 texels each line */ +#ifndef ARGB + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + for (i = 0; i < comps; i++) { + input[k + l * 4][i] = *lines[l]++; + } + } + } +#else + /* H.Morii - support for ARGB inputs */ + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + input[k + l * 4][2] = *lines[l]++; + input[k + l * 4][1] = *lines[l]++; + input[k + l * 4][0] = *lines[l]++; + if (comps == 4) input[k + l * 4][3] = *lines[l]++; + } + } +#endif + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + for (k = 0; k < N_TEXELS; k++) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minCol = k; + } + if (maxSum < sum) { + maxSum = sum; + maxCol = k; + } + if (alpha0 > input[k][ACOMP]) { + alpha0 = input[k][ACOMP]; + } + if (alpha1 < input[k][ACOMP]) { + alpha1 = input[k][ACOMP]; + } + if (input[k][ACOMP] == 0) { + anyZero = 1; + } + if (input[k][ACOMP] == 255) { + anyOne = 1; + } + } + + /* add in alphas */ + if (alpha0 == alpha1) { + /* we'll use 6-vector */ + cc[0] = alpha0 | (alpha1 << 8); + cc[1] = 0; + } else { + if (anyZero && ((alpha0 == 0) || (alpha1 == 0))) { + /* we still might use 8-vector */ + anyZero = 0; + } + if (anyOne && ((alpha0 == 255) || (alpha1 == 255))) { + /* we still might use 8-vector */ + anyOne = 0; + } + if ((anyZero | anyOne) ^ (alpha0 <= alpha1)) { + int aux; + aux = alpha0; + alpha0 = alpha1; + alpha1 = aux; + } + a_vect = (alpha0 <= alpha1) ? 5 : 7; + + /* compute interpolation vector */ + iv[ACOMP] = (float)a_vect / (alpha1 - alpha0); + b = -iv[ACOMP] * alpha0 + 0.5F; + + /* add in alphas */ + Q_MOV32(lo, 0); + for (k = N_TEXELS - 1; k >= 0; k--) { + int texel = -1; + if (anyZero | anyOne) { + if (input[k][ACOMP] == 0) { + texel = 6; + } else if (input[k][ACOMP] == 255) { + texel = 7; + } + } + /* interpolate alpha */ + if (texel == -1) { + float dot = input[k][ACOMP] * iv[ACOMP]; + texel = (int)(dot + b); +#if SAFECDOT + if (texel < 0) { + texel = 0; + } else if (texel > a_vect) { + texel = a_vect; + } +#endif + texel = dxtn_alpha_tlat[anyZero | anyOne][texel]; + } + /* add in texel */ + Q_SHL(lo, 3); + Q_OR32(lo, texel); + } + Q_SHL(lo, 16); + Q_OR32(lo, alpha0 | (alpha1 << 8)); + ((qword *)cc)[0] = lo; + } + + color0 = COLOR565(input[minCol]); + color1 = COLOR565(input[maxCol]); + +#ifdef RADEON /* H.Morii - Workaround for ATI Radeon */ + if (color0 < color1) { + int aux; + aux = color0; + color0 = color1; + color1 = aux; + aux = minCol; + minCol = maxCol; + maxCol = aux; + } +#endif + + cc[2] = color0 | (color1 << 16); + + hihi = 0; + if (color0 != color1) { + MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]); + + /* add in texels */ + for (k = N_TEXELS - 1; k >= 0; k--) { + int texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + texel = dxtn_color_tlat[0][texel]; + /* add in texel */ + hihi <<= 2; + hihi |= texel; + } + } + cc[3] = hihi; +} + + +#define ENCODER(dxtn, n) \ +int TAPIENTRY \ +dxtn##_encode (int width, int height, int comps, \ + const void *source, int srcRowStride, \ + void *dest, int destRowStride) \ +{ \ + int x, y; \ + const byte *data; \ + dword *encoded = (dword *)dest; \ + void *newSource = NULL; \ + \ + /* Replicate image if width is not M4 or height is not M4 */ \ + if ((width & 3) | (height & 3)) { \ + int newWidth = (width + 3) & ~3; \ + int newHeight = (height + 3) & ~3; \ + newSource = malloc(comps * newWidth * newHeight * sizeof(byte *));\ + _mesa_upscale_teximage2d(width, height, newWidth, newHeight, \ + comps, (const byte *)source, \ + srcRowStride, (byte *)newSource); \ + source = newSource; \ + width = newWidth; \ + height = newHeight; \ + srcRowStride = comps * newWidth; \ + } \ + \ + data = (const byte *)source; \ + destRowStride = (destRowStride - width * n) / 4; \ + for (y = 0; y < height; y += 4) { \ + unsigned int offs = 0 + (y + 0) * srcRowStride; \ + for (x = 0; x < width; x += 4) { \ + const byte *lines[4]; \ + lines[0] = &data[offs]; \ + lines[1] = lines[0] + srcRowStride; \ + lines[2] = lines[1] + srcRowStride; \ + lines[3] = lines[2] + srcRowStride; \ + offs += 4 * comps; \ + dxtn##_quantize(encoded, lines, comps); \ + /* 4x4 block */ \ + encoded += n; \ + } \ + encoded += destRowStride; \ + } \ + \ + if (newSource != NULL) { \ + free(newSource); \ + } \ + \ + return 0; \ +} + +ENCODER(dxt1_rgb, 2) +ENCODER(dxt1_rgba, 2) +ENCODER(dxt3_rgba, 4) +ENCODER(dxt5_rgba, 4) + + +/***************************************************************************\ + * DXTn decoder + * + * The decoder is based on GL_EXT_texture_compression_s3tc + * specification and serves as a concept for the encoder. +\***************************************************************************/ + + +/* lookup table for scaling 4 bit colors up to 8 bits */ +static const byte _rgb_scale_4[] = { + 0, 17, 34, 51, 68, 85, 102, 119, + 136, 153, 170, 187, 204, 221, 238, 255 +}; + +/* lookup table for scaling 5 bit colors up to 8 bits */ +static const byte _rgb_scale_5[] = { + 0, 8, 16, 25, 33, 41, 49, 58, + 66, 74, 82, 90, 99, 107, 115, 123, + 132, 140, 148, 156, 165, 173, 181, 189, + 197, 206, 214, 222, 230, 239, 247, 255 +}; + +/* lookup table for scaling 6 bit colors up to 8 bits */ +static const byte _rgb_scale_6[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 45, 49, 53, 57, 61, + 65, 69, 73, 77, 81, 85, 89, 93, + 97, 101, 105, 109, 113, 117, 121, 125, + 130, 134, 138, 142, 146, 150, 154, 158, + 162, 166, 170, 174, 178, 182, 186, 190, + 194, 198, 202, 206, 210, 215, 219, 223, + 227, 231, 235, 239, 243, 247, 251, 255 +}; + + +#define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31)) +#define UP4(c) _rgb_scale_4[(c) & 15] +#define UP5(c) _rgb_scale_5[(c) & 31] +#define UP6(c) _rgb_scale_6[(c) & 63] +#define ZERO_4UBV(v) *((dword *)(v)) = 0 + + +void TAPIENTRY +dxt1_rgb_decode_1 (const void *texture, int stride, + int i, int j, byte *rgba) +{ + const byte *src = (const byte *)texture + + ((j / 4) * ((stride + 3) / 4) + i / 4) * 8; + const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3; + if (code == 0) { + rgba[RCOMP] = UP5(CC_SEL(src, 11)); + rgba[GCOMP] = UP6(CC_SEL(src, 5)); + rgba[BCOMP] = UP5(CC_SEL(src, 0)); + } else if (code == 1) { + rgba[RCOMP] = UP5(CC_SEL(src, 27)); + rgba[GCOMP] = UP6(CC_SEL(src, 21)); + rgba[BCOMP] = UP5(CC_SEL(src, 16)); + } else { + const word col0 = src[0] | (src[1] << 8); + const word col1 = src[2] | (src[3] << 8); + if (col0 > col1) { + if (code == 2) { + rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3; + rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3; + rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3; + } else { + rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3; + rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3; + rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3; + } + } else { + if (code == 2) { + rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2; + rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2; + rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2; + } else { + ZERO_4UBV(rgba); + } + } + } + rgba[ACOMP] = 255; +} + + +void TAPIENTRY +dxt1_rgba_decode_1 (const void *texture, int stride, + int i, int j, byte *rgba) +{ + /* Same as rgb_dxt1 above, except alpha=0 if col0<=col1 and code=3. */ + const byte *src = (const byte *)texture + + ((j / 4) * ((stride + 3) / 4) + i / 4) * 8; + const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3; + if (code == 0) { + rgba[RCOMP] = UP5(CC_SEL(src, 11)); + rgba[GCOMP] = UP6(CC_SEL(src, 5)); + rgba[BCOMP] = UP5(CC_SEL(src, 0)); + rgba[ACOMP] = 255; + } else if (code == 1) { + rgba[RCOMP] = UP5(CC_SEL(src, 27)); + rgba[GCOMP] = UP6(CC_SEL(src, 21)); + rgba[BCOMP] = UP5(CC_SEL(src, 16)); + rgba[ACOMP] = 255; + } else { + const word col0 = src[0] | (src[1] << 8); + const word col1 = src[2] | (src[3] << 8); + if (col0 > col1) { + if (code == 2) { + rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3; + rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3; + rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3; + } else { + rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3; + rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3; + rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3; + } + rgba[ACOMP] = 255; + } else { + if (code == 2) { + rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2; + rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2; + rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2; + rgba[ACOMP] = 255; + } else { + ZERO_4UBV(rgba); + } + } + } +} + + +void TAPIENTRY +dxt3_rgba_decode_1 (const void *texture, int stride, + int i, int j, byte *rgba) +{ + const byte *src = (const byte *)texture + + ((j / 4) * ((stride + 3) / 4) + i / 4) * 16; + const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3; + const dword *cc = (const dword *)(src + 8); + if (code == 0) { + rgba[RCOMP] = UP5(CC_SEL(cc, 11)); + rgba[GCOMP] = UP6(CC_SEL(cc, 5)); + rgba[BCOMP] = UP5(CC_SEL(cc, 0)); + } else if (code == 1) { + rgba[RCOMP] = UP5(CC_SEL(cc, 27)); + rgba[GCOMP] = UP6(CC_SEL(cc, 21)); + rgba[BCOMP] = UP5(CC_SEL(cc, 16)); + } else if (code == 2) { + /* (col0 * (4 - code) + col1 * (code - 1)) / 3 */ + rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3; + rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3; + rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3; + } else { + rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3; + rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3; + rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3; + } + rgba[ACOMP] = UP4(src[((j & 3) * 4 + (i & 3)) / 2] >> ((i & 1) * 4)); +} + + +void TAPIENTRY +dxt5_rgba_decode_1 (const void *texture, int stride, + int i, int j, byte *rgba) +{ + const byte *src = (const byte *)texture + + ((j / 4) * ((stride + 3) / 4) + i / 4) * 16; + const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3; + const dword *cc = (const dword *)(src + 8); + const byte alpha0 = src[0]; + const byte alpha1 = src[1]; + const int alphaShift = (((j & 3) * 4) + (i & 3)) * 3 + 16; + const int acode = ((alphaShift == 31) + ? CC_SEL(src + 2, alphaShift - 16) + : CC_SEL(src, alphaShift)) & 0x7; + if (code == 0) { + rgba[RCOMP] = UP5(CC_SEL(cc, 11)); + rgba[GCOMP] = UP6(CC_SEL(cc, 5)); + rgba[BCOMP] = UP5(CC_SEL(cc, 0)); + } else if (code == 1) { + rgba[RCOMP] = UP5(CC_SEL(cc, 27)); + rgba[GCOMP] = UP6(CC_SEL(cc, 21)); + rgba[BCOMP] = UP5(CC_SEL(cc, 16)); + } else if (code == 2) { + /* (col0 * (4 - code) + col1 * (code - 1)) / 3 */ + rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3; + rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3; + rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3; + } else { + rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3; + rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3; + rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3; + } + if (acode == 0) { + rgba[ACOMP] = alpha0; + } else if (acode == 1) { + rgba[ACOMP] = alpha1; + } else if (alpha0 > alpha1) { + rgba[ACOMP] = ((8 - acode) * alpha0 + (acode - 1) * alpha1) / 7; + } else if (acode == 6) { + rgba[ACOMP] = 0; + } else if (acode == 7) { + rgba[ACOMP] = 255; + } else { + rgba[ACOMP] = ((6 - acode) * alpha0 + (acode - 1) * alpha1) / 5; + } +} diff --git a/GLideNHQ/tc-1.1+/dxtn.h b/GLideNHQ/tc-1.1+/dxtn.h new file mode 100644 index 00000000..4078fd9f --- /dev/null +++ b/GLideNHQ/tc-1.1+/dxtn.h @@ -0,0 +1,62 @@ +/* + * DXTn codec + * Version: 1.1 + * + * Copyright (C) 2004 Daniel Borca All Rights Reserved. + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef DXTN_H_included +#define DXTN_H_included + +TAPI int TAPIENTRY +dxt1_rgb_encode (int width, int height, int comps, + const void *source, int srcRowStride, + void *dest, int destRowStride); + +TAPI int TAPIENTRY +dxt1_rgba_encode (int width, int height, int comps, + const void *source, int srcRowStride, + void *dest, int destRowStride); + +TAPI int TAPIENTRY +dxt3_rgba_encode (int width, int height, int comps, + const void *source, int srcRowStride, + void *dest, int destRowStride); + +TAPI int TAPIENTRY +dxt5_rgba_encode (int width, int height, int comps, + const void *source, int srcRowStride, + void *dest, int destRowStride); + +TAPI void TAPIENTRY +dxt1_rgb_decode_1 (const void *texture, int stride /* in pixels */, + int i, int j, byte *rgba); + +TAPI void TAPIENTRY +dxt1_rgba_decode_1 (const void *texture, int stride /* in pixels */, + int i, int j, byte *rgba); + +TAPI void TAPIENTRY +dxt3_rgba_decode_1 (const void *texture, int stride /* in pixels */, + int i, int j, byte *rgba); + +TAPI void TAPIENTRY +dxt5_rgba_decode_1 (const void *texture, int stride /* in pixels */, + int i, int j, byte *rgba); + +#endif diff --git a/GLideNHQ/tc-1.1+/fxt1.c b/GLideNHQ/tc-1.1+/fxt1.c new file mode 100644 index 00000000..1287ced5 --- /dev/null +++ b/GLideNHQ/tc-1.1+/fxt1.c @@ -0,0 +1,1459 @@ +/* + * FXT1 codec + * Version: 1.1 + * + * Copyright (C) 2004 Daniel Borca All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DANIEL BORCA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Copyright (C) 2007 Hiroshi Morii + * Added support for ARGB inputs. + */ + + +#include +#include + +#include "types.h" +#include "internal.h" +#include "fxt1.h" + + +/***************************************************************************\ + * FXT1 encoder + * + * The encoder was built by reversing the decoder, + * and is vaguely based on Texus2 by 3dfx. Note that this code + * is merely a proof of concept, since it is highly UNoptimized; + * moreover, it is sub-optimal due to initial conditions passed + * to Lloyd's algorithm (the interpolation modes are even worse). +\***************************************************************************/ + + +#define MAX_COMP 4 /* ever needed maximum number of components in texel */ +#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */ +#define N_TEXELS 32 /* number of texels in a block (always 32) */ +#define LL_N_REP 50 /* number of iterations in lloyd's vq */ +#define LL_RMS_D 10 /* fault tolerance (maximum delta) */ +#define LL_RMS_E 255 /* fault tolerance (maximum error) */ +#define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */ +#define ISTBLACK(v) (*((dword *)(v)) == 0) +#define COPY_4UBV(DST, SRC) *((dword *)(DST)) = *((dword *)(SRC)) + + +static int +fxt1_bestcol (float vec[][MAX_COMP], int nv, + byte input[MAX_COMP], int nc) +{ + int i, j, best = -1; + float err = 1e9; /* big enough */ + + for (j = 0; j < nv; j++) { + float e = 0.0F; + for (i = 0; i < nc; i++) { + e += (vec[j][i] - input[i]) * (vec[j][i] - input[i]); + } + if (e < err) { + err = e; + best = j; + } + } + + return best; +} + + +static int +fxt1_worst (float vec[MAX_COMP], + byte input[N_TEXELS][MAX_COMP], int nc, int n) +{ + int i, k, worst = -1; + float err = -1.0F; /* small enough */ + + for (k = 0; k < n; k++) { + float e = 0.0F; + for (i = 0; i < nc; i++) { + e += (vec[i] - input[k][i]) * (vec[i] - input[k][i]); + } + if (e > err) { + err = e; + worst = k; + } + } + + return worst; +} + + +static int +fxt1_variance (double variance[MAX_COMP], + byte input[N_TEXELS][MAX_COMP], int nc, int n) +{ + int i, k, best = 0; + dword sx, sx2; + double var, maxvar = -1; /* small enough */ + double teenth = 1.0 / n; + + for (i = 0; i < nc; i++) { + sx = sx2 = 0; + for (k = 0; k < n; k++) { + int t = input[k][i]; + sx += t; + sx2 += t * t; + } + var = sx2 * teenth - sx * sx * teenth * teenth; + if (maxvar < var) { + maxvar = var; + best = i; + } + if (variance) { + variance[i] = var; + } + } + + return best; +} + + +static int +fxt1_choose (float vec[][MAX_COMP], int nv, + byte input[N_TEXELS][MAX_COMP], int nc, int n) +{ +#if 0 + /* Choose colors from a grid. + */ + int i, j; + + for (j = 0; j < nv; j++) { + int m = j * (n - 1) / (nv - 1); + for (i = 0; i < nc; i++) { + vec[j][i] = input[m][i]; + } + } +#else + /* Our solution here is to find the darkest and brightest colors in + * the 8x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + int i, j, k; +#ifndef YUV + int minSum = 2000; /* big enough */ +#else + int minSum = 2000000; +#endif + int maxSum = -1; /* small enough */ + int minCol = 0; /* phoudoin: silent compiler! */ + int maxCol = 0; /* phoudoin: silent compiler! */ + + struct { + int flag; + dword key; + int freq; + int idx; + } hist[N_TEXELS]; + int lenh = 0; + + memset(hist, 0, sizeof(hist)); + + for (k = 0; k < n; k++) { + int l; + dword key = 0; + int sum = 0; + for (i = 0; i < nc; i++) { + key <<= 8; + key |= input[k][i]; +#ifndef YUV + sum += input[k][i]; +#else + /* RGB to YUV conversion according to CCIR 601 specs + * Y = 0.299R+0.587G+0.114B + * U = 0.713(R - Y) = 0.500R-0.419G-0.081B + * V = 0.564(B - Y) = -0.169R-0.331G+0.500B + */ + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + } + for (l = 0; l < n; l++) { + if (!hist[l].flag) { + /* alloc new slot */ + hist[l].flag = !0; + hist[l].key = key; + hist[l].freq = 1; + hist[l].idx = k; + lenh = l + 1; + break; + } else if (hist[l].key == key) { + hist[l].freq++; + break; + } + } + if (minSum > sum) { + minSum = sum; + minCol = k; + } + if (maxSum < sum) { + maxSum = sum; + maxCol = k; + } + } + + if (lenh <= nv) { + for (j = 0; j < lenh; j++) { + for (i = 0; i < nc; i++) { + vec[j][i] = (float)input[hist[j].idx][i]; + } + } + for (; j < nv; j++) { + for (i = 0; i < nc; i++) { + vec[j][i] = vec[0][i]; + } + } + return 0; + } + + for (j = 0; j < nv; j++) { + for (i = 0; i < nc; i++) { + vec[j][i] = ((nv - 1 - j) * input[minCol][i] + j * input[maxCol][i] + (nv - 1) / 2) / (float)(nv - 1); + } + } +#endif + + return !0; +} + + +static int +fxt1_lloyd (float vec[][MAX_COMP], int nv, + byte input[N_TEXELS][MAX_COMP], int nc, int n) +{ + /* Use the generalized lloyd's algorithm for VQ: + * find 4 color vectors. + * + * for each sample color + * sort to nearest vector. + * + * replace each vector with the centroid of it's matching colors. + * + * repeat until RMS doesn't improve. + * + * if a color vector has no samples, or becomes the same as another + * vector, replace it with the color which is farthest from a sample. + * + * vec[][MAX_COMP] initial vectors and resulting colors + * nv number of resulting colors required + * input[N_TEXELS][MAX_COMP] input texels + * nc number of components in input / vec + * n number of input samples + */ + + int sum[MAX_VECT][MAX_COMP]; /* used to accumulate closest texels */ + int cnt[MAX_VECT]; /* how many times a certain vector was chosen */ + float error, lasterror = 1e9; + + int i, j, k, rep; + + /* the quantizer */ + for (rep = 0; rep < LL_N_REP; rep++) { + /* reset sums & counters */ + for (j = 0; j < nv; j++) { + for (i = 0; i < nc; i++) { + sum[j][i] = 0; + } + cnt[j] = 0; + } + error = 0; + + /* scan whole block */ + for (k = 0; k < n; k++) { +#if 1 + int best = -1; + float err = 1e9; /* big enough */ + /* determine best vector */ + for (j = 0; j < nv; j++) { + float e = (vec[j][0] - input[k][0]) * (vec[j][0] - input[k][0]) + + (vec[j][1] - input[k][1]) * (vec[j][1] - input[k][1]) + + (vec[j][2] - input[k][2]) * (vec[j][2] - input[k][2]); + if (nc == 4) { + e += (vec[j][3] - input[k][3]) * (vec[j][3] - input[k][3]); + } + if (e < err) { + err = e; + best = j; + } + } +#else + int best = fxt1_bestcol(vec, nv, input[k], nc, &err); +#endif + /* add in closest color */ + for (i = 0; i < nc; i++) { + sum[best][i] += input[k][i]; + } + /* mark this vector as used */ + cnt[best]++; + /* accumulate error */ + error += err; + } + + /* check RMS */ + if ((error < LL_RMS_E) || + ((error < lasterror) && ((lasterror - error) < LL_RMS_D))) { + return !0; /* good match */ + } + lasterror = error; + + /* move each vector to the barycenter of its closest colors */ + for (j = 0; j < nv; j++) { + if (cnt[j]) { + float div = 1.0F / cnt[j]; + for (i = 0; i < nc; i++) { + vec[j][i] = div * sum[j][i]; + } + } else { + /* this vec has no samples or is identical with a previous vec */ + int worst = fxt1_worst(vec[j], input, nc, n); + for (i = 0; i < nc; i++) { + vec[j][i] = input[worst][i]; + } + } + } + } + + return 0; /* could not converge fast enough */ +} + + +static void +fxt1_quantize_CHROMA (dword *cc, + byte input[N_TEXELS][MAX_COMP]) +{ + const int n_vect = 4; /* 4 base vectors to find */ + const int n_comp = 3; /* 3 components: R, G, B */ + float vec[MAX_VECT][MAX_COMP]; + int i, j, k; + qword hi; /* high quadword */ + dword lohi, lolo; /* low quadword: hi dword, lo dword */ + + if (fxt1_choose(vec, n_vect, input, n_comp, N_TEXELS) != 0) { + fxt1_lloyd(vec, n_vect, input, n_comp, N_TEXELS); + } + + Q_MOV32(hi, 4); /* cc-chroma = "010" + unused bit */ + for (j = n_vect - 1; j >= 0; j--) { + for (i = 0; i < n_comp; i++) { + /* add in colors */ + Q_SHL(hi, 5); + Q_OR32(hi, (dword)(vec[j][i] / 8.0F)); + } + } + ((qword *)cc)[1] = hi; + + lohi = lolo = 0; + /* right microtile */ + for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { + lohi <<= 2; + lohi |= fxt1_bestcol(vec, n_vect, input[k], n_comp); + } + /* left microtile */ + for (; k >= 0; k--) { + lolo <<= 2; + lolo |= fxt1_bestcol(vec, n_vect, input[k], n_comp); + } + cc[1] = lohi; + cc[0] = lolo; +} + + +static void +fxt1_quantize_ALPHA0 (dword *cc, + byte input[N_TEXELS][MAX_COMP], + byte reord[N_TEXELS][MAX_COMP], int n) +{ + const int n_vect = 3; /* 3 base vectors to find */ + const int n_comp = 4; /* 4 components: R, G, B, A */ + float vec[MAX_VECT][MAX_COMP]; + int i, j, k; + qword hi; /* high quadword */ + dword lohi, lolo; /* low quadword: hi dword, lo dword */ + + /* the last vector indicates zero */ + for (i = 0; i < n_comp; i++) { + vec[n_vect][i] = 0; + } + + /* the first n texels in reord are guaranteed to be non-zero */ + if (fxt1_choose(vec, n_vect, reord, n_comp, n) != 0) { + fxt1_lloyd(vec, n_vect, reord, n_comp, n); + } + + Q_MOV32(hi, 6); /* alpha = "011" + lerp = 0 */ + for (j = n_vect - 1; j >= 0; j--) { + /* add in alphas */ + Q_SHL(hi, 5); + Q_OR32(hi, (dword)(vec[j][ACOMP] / 8.0F)); + } + for (j = n_vect - 1; j >= 0; j--) { + for (i = 0; i < n_comp - 1; i++) { + /* add in colors */ + Q_SHL(hi, 5); + Q_OR32(hi, (dword)(vec[j][i] / 8.0F)); + } + } + ((qword *)cc)[1] = hi; + + lohi = lolo = 0; + /* right microtile */ + for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { + lohi <<= 2; + lohi |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp); + } + /* left microtile */ + for (; k >= 0; k--) { + lolo <<= 2; + lolo |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp); + } + cc[1] = lohi; + cc[0] = lolo; +} + + +static void +fxt1_quantize_ALPHA1 (dword *cc, + byte input[N_TEXELS][MAX_COMP]) +{ + const int n_vect = 3; /* highest vector number in each microtile */ + const int n_comp = 4; /* 4 components: R, G, B, A */ + float vec[1 + 1 + 1][MAX_COMP]; /* 1.5 extrema for each sub-block */ + float b, iv[MAX_COMP]; /* interpolation vector */ + int i, j, k; + qword hi; /* high quadword */ + dword lohi, lolo; /* low quadword: hi dword, lo dword */ + + int minSum; + int maxSum; + int minColL = 0, maxColL = 0; + int minColR = 0, maxColR = 0; + int sumL = 0, sumR = 0; + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ +#ifndef YUV + minSum = 2000; /* big enough */ +#else + minSum = 2000000; +#endif + maxSum = -1; /* small enough */ + for (k = 0; k < N_TEXELS / 2; k++) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minColL = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColL = k; + } + sumL += sum; + } +#ifndef YUV + minSum = 2000; /* big enough */ +#else + minSum = 2000000; +#endif + maxSum = -1; /* small enough */ + for (; k < N_TEXELS; k++) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minColR = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColR = k; + } + sumR += sum; + } + + /* choose the common vector (yuck!) */ + { + int j1, j2; + int v1 = 0, v2 = 0; + float err = 1e9; /* big enough */ + float tv[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */ + for (i = 0; i < n_comp; i++) { + tv[0][i] = input[minColL][i]; + tv[1][i] = input[maxColL][i]; + tv[2][i] = input[minColR][i]; + tv[3][i] = input[maxColR][i]; + } + for (j1 = 0; j1 < 2; j1++) { + for (j2 = 2; j2 < 4; j2++) { + float e = 0.0F; + for (i = 0; i < n_comp; i++) { + e += (tv[j1][i] - tv[j2][i]) * (tv[j1][i] - tv[j2][i]); + } + if (e < err) { + err = e; + v1 = j1; + v2 = j2; + } + } + } + for (i = 0; i < n_comp; i++) { + vec[0][i] = tv[1 - v1][i]; + vec[1][i] = (tv[v1][i] * sumL + tv[v2][i] * sumR) / (sumL + sumR); + vec[2][i] = tv[5 - v2][i]; + } + } + + /* left microtile */ + cc[0] = 0; + if (minColL != maxColL) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]); + + /* add in texels */ + lolo = 0; + for (k = N_TEXELS / 2 - 1; k >= 0; k--) { + int texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + lolo <<= 2; + lolo |= texel; + } + + cc[0] = lolo; + } + + /* right microtile */ + cc[1] = 0; + if (minColR != maxColR) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[1]); + + /* add in texels */ + lohi = 0; + for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { + int texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + lohi <<= 2; + lohi |= texel; + } + + cc[1] = lohi; + } + + Q_MOV32(hi, 7); /* alpha = "011" + lerp = 1 */ + for (j = n_vect - 1; j >= 0; j--) { + /* add in alphas */ + Q_SHL(hi, 5); + Q_OR32(hi, (dword)(vec[j][ACOMP] / 8.0F)); + } + for (j = n_vect - 1; j >= 0; j--) { + for (i = 0; i < n_comp - 1; i++) { + /* add in colors */ + Q_SHL(hi, 5); + Q_OR32(hi, (dword)(vec[j][i] / 8.0F)); + } + } + ((qword *)cc)[1] = hi; +} + + +static void +fxt1_quantize_HI (dword *cc, + byte input[N_TEXELS][MAX_COMP], + byte reord[N_TEXELS][MAX_COMP], int n) +{ + const int n_vect = 6; /* highest vector number */ + const int n_comp = 3; /* 3 components: R, G, B */ + float b = 0.0F; /* phoudoin: silent compiler! */ + float iv[MAX_COMP]; /* interpolation vector */ + int i, k; + dword hihi; /* high quadword: hi dword */ + +#ifndef YUV + int minSum = 2000; /* big enough */ +#else + int minSum = 2000000; +#endif + int maxSum = -1; /* small enough */ + int minCol = 0; /* phoudoin: silent compiler! */ + int maxCol = 0; /* phoudoin: silent compiler! */ + + /* Our solution here is to find the darkest and brightest colors in + * the 8x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + for (k = 0; k < n; k++) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += reord[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minCol = k; + } + if (maxSum < sum) { + maxSum = sum; + maxCol = k; + } + } + + hihi = 0; /* cc-hi = "00" */ + for (i = 0; i < n_comp; i++) { + /* add in colors */ + hihi <<= 5; + hihi |= reord[maxCol][i] >> 3; + } + for (i = 0; i < n_comp; i++) { + /* add in colors */ + hihi <<= 5; + hihi |= reord[minCol][i] >> 3; + } + cc[3] = hihi; + cc[0] = cc[1] = cc[2] = 0; + + /* compute interpolation vector */ + if (minCol != maxCol) { + MAKEIVEC(n_vect, n_comp, iv, b, reord[minCol], reord[maxCol]); + } + + /* add in texels */ + for (k = N_TEXELS - 1; k >= 0; k--) { + int t = k * 3; + dword *kk = (dword *)((byte *)cc + t / 8); + int texel = n_vect + 1; /* transparent black */ + + if (!ISTBLACK(input[k])) { + if (minCol != maxCol) { + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + kk[0] |= texel << (t & 7); + } + } else { + /* add in texel */ + kk[0] |= texel << (t & 7); + } + } +} + + +static void +fxt1_quantize_MIXED1 (dword *cc, + byte input[N_TEXELS][MAX_COMP]) +{ + const int n_vect = 2; /* highest vector number in each microtile */ + const int n_comp = 3; /* 3 components: R, G, B */ + byte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */ + float b, iv[MAX_COMP]; /* interpolation vector */ + int i, j, k; + qword hi; /* high quadword */ + dword lohi, lolo; /* low quadword: hi dword, lo dword */ + + int minSum; + int maxSum; + int minColL = 0, maxColL = -1; + int minColR = 0, maxColR = -1; + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ +#ifndef YUV + minSum = 2000; /* big enough */ +#else + minSum = 2000000; +#endif + maxSum = -1; /* small enough */ + for (k = 0; k < N_TEXELS / 2; k++) { + if (!ISTBLACK(input[k])) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minColL = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColL = k; + } + } + } +#ifndef YUV + minSum = 2000; /* big enough */ +#else + minSum = 2000000; +#endif + maxSum = -1; /* small enough */ + for (; k < N_TEXELS; k++) { + if (!ISTBLACK(input[k])) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minColR = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColR = k; + } + } + } + + /* left microtile */ + if (maxColL == -1) { + /* all transparent black */ + cc[0] = ~0UL; + for (i = 0; i < n_comp; i++) { + vec[0][i] = 0; + vec[1][i] = 0; + } + } else { + cc[0] = 0; + for (i = 0; i < n_comp; i++) { + vec[0][i] = input[minColL][i]; + vec[1][i] = input[maxColL][i]; + } + if (minColL != maxColL) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]); + + /* add in texels */ + lolo = 0; + for (k = N_TEXELS / 2 - 1; k >= 0; k--) { + int texel = n_vect + 1; /* transparent black */ + if (!ISTBLACK(input[k])) { + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + } + /* add in texel */ + lolo <<= 2; + lolo |= texel; + } + cc[0] = lolo; + } + } + + /* right microtile */ + if (maxColR == -1) { + /* all transparent black */ + cc[1] = ~0UL; + for (i = 0; i < n_comp; i++) { + vec[2][i] = 0; + vec[3][i] = 0; + } + } else { + cc[1] = 0; + for (i = 0; i < n_comp; i++) { + vec[2][i] = input[minColR][i]; + vec[3][i] = input[maxColR][i]; + } + if (minColR != maxColR) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]); + + /* add in texels */ + lohi = 0; + for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { + int texel = n_vect + 1; /* transparent black */ + if (!ISTBLACK(input[k])) { + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + } + /* add in texel */ + lohi <<= 2; + lohi |= texel; + } + cc[1] = lohi; + } + } + + Q_MOV32(hi, 9 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */ + for (j = 2 * 2 - 1; j >= 0; j--) { + for (i = 0; i < n_comp; i++) { + /* add in colors */ + Q_SHL(hi, 5); + Q_OR32(hi, vec[j][i] >> 3); + } + } + ((qword *)cc)[1] = hi; +} + + +static void +fxt1_quantize_MIXED0 (dword *cc, + byte input[N_TEXELS][MAX_COMP]) +{ + const int n_vect = 3; /* highest vector number in each microtile */ + const int n_comp = 3; /* 3 components: R, G, B */ + byte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */ + float b, iv[MAX_COMP]; /* interpolation vector */ + int i, j, k; + qword hi; /* high quadword */ + dword lohi, lolo; /* low quadword: hi dword, lo dword */ + + int minColL = 0, maxColL = 0; + int minColR = 0, maxColR = 0; +#if 0 + int minSum; + int maxSum; + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ +#ifndef YUV + minSum = 2000; /* big enough */ +#else + minSum = 2000000; +#endif + maxSum = -1; /* small enough */ + for (k = 0; k < N_TEXELS / 2; k++) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minColL = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColL = k; + } + } + minSum = 2000; /* big enough */ + maxSum = -1; /* small enough */ + for (; k < N_TEXELS; k++) { + int sum = 0; +#ifndef YUV + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } +#else + sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP]; +#endif + if (minSum > sum) { + minSum = sum; + minColR = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColR = k; + } + } +#else + int minVal; + int maxVal; + int maxVarL = fxt1_variance(NULL, input, n_comp, N_TEXELS / 2); + int maxVarR = fxt1_variance(NULL, &input[N_TEXELS / 2], n_comp, N_TEXELS / 2); + + /* Scan the channel with max variance for lo & hi + * and use those as the two representative colors. + */ + minVal = 2000; /* big enough */ + maxVal = -1; /* small enough */ + for (k = 0; k < N_TEXELS / 2; k++) { + int t = input[k][maxVarL]; + if (minVal > t) { + minVal = t; + minColL = k; + } + if (maxVal < t) { + maxVal = t; + maxColL = k; + } + } + minVal = 2000; /* big enough */ + maxVal = -1; /* small enough */ + for (; k < N_TEXELS; k++) { + int t = input[k][maxVarR]; + if (minVal > t) { + minVal = t; + minColR = k; + } + if (maxVal < t) { + maxVal = t; + maxColR = k; + } + } +#endif + + /* left microtile */ + cc[0] = 0; + for (i = 0; i < n_comp; i++) { + vec[0][i] = input[minColL][i]; + vec[1][i] = input[maxColL][i]; + } + if (minColL != maxColL) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]); + + /* add in texels */ + lolo = 0; + for (k = N_TEXELS / 2 - 1; k >= 0; k--) { + int texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + lolo <<= 2; + lolo |= texel; + } + + /* funky encoding for LSB of green */ + if ((int)((lolo >> 1) & 1) != (((vec[1][GCOMP] ^ vec[0][GCOMP]) >> 2) & 1)) { + for (i = 0; i < n_comp; i++) { + vec[1][i] = input[minColL][i]; + vec[0][i] = input[maxColL][i]; + } + lolo = ~lolo; + } + + cc[0] = lolo; + } + + /* right microtile */ + cc[1] = 0; + for (i = 0; i < n_comp; i++) { + vec[2][i] = input[minColR][i]; + vec[3][i] = input[maxColR][i]; + } + if (minColR != maxColR) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]); + + /* add in texels */ + lohi = 0; + for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { + int texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + lohi <<= 2; + lohi |= texel; + } + + /* funky encoding for LSB of green */ + if ((int)((lohi >> 1) & 1) != (((vec[3][GCOMP] ^ vec[2][GCOMP]) >> 2) & 1)) { + for (i = 0; i < n_comp; i++) { + vec[3][i] = input[minColR][i]; + vec[2][i] = input[maxColR][i]; + } + lohi = ~lohi; + } + + cc[1] = lohi; + } + + Q_MOV32(hi, 8 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */ + for (j = 2 * 2 - 1; j >= 0; j--) { + for (i = 0; i < n_comp; i++) { + /* add in colors */ + Q_SHL(hi, 5); + Q_OR32(hi, vec[j][i] >> 3); + } + } + ((qword *)cc)[1] = hi; +} + + +static void +fxt1_quantize (dword *cc, const byte *lines[], int comps) +{ + int trualpha; + byte reord[N_TEXELS][MAX_COMP]; + + byte input[N_TEXELS][MAX_COMP]; +#ifndef ARGB + int i; +#endif + int k, l; + + if (comps == 3) { + /* make the whole block opaque */ + memset(input, -1, sizeof(input)); + } + + /* 8 texels each line */ +#ifndef ARGB + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + for (i = 0; i < comps; i++) { + input[k + l * 4][i] = *lines[l]++; + } + } + for (; k < 8; k++) { + for (i = 0; i < comps; i++) { + input[k + l * 4 + 12][i] = *lines[l]++; + } + } + } +#else + /* H.Morii - support for ARGB inputs */ + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + input[k + l * 4][2] = *lines[l]++; + input[k + l * 4][1] = *lines[l]++; + input[k + l * 4][0] = *lines[l]++; + if (comps == 4) input[k + l * 4][3] = *lines[l]++; + } + for (; k < 8; k++) { + input[k + l * 4 + 12][2] = *lines[l]++; + input[k + l * 4 + 12][1] = *lines[l]++; + input[k + l * 4 + 12][0] = *lines[l]++; + if (comps == 4) input[k + l * 4 + 12][3] = *lines[l]++; + } + } +#endif + + /* block layout: + * 00, 01, 02, 03, 08, 09, 0a, 0b + * 10, 11, 12, 13, 18, 19, 1a, 1b + * 04, 05, 06, 07, 0c, 0d, 0e, 0f + * 14, 15, 16, 17, 1c, 1d, 1e, 1f + */ + + /* [dBorca] + * stupidity flows forth from this + */ + l = N_TEXELS; + trualpha = 0; + if (comps == 4) { + /* skip all transparent black texels */ + l = 0; + for (k = 0; k < N_TEXELS; k++) { + /* test all components against 0 */ + if (!ISTBLACK(input[k])) { + /* texel is not transparent black */ + COPY_4UBV(reord[l], input[k]); + if (reord[l][ACOMP] < (255 - ALPHA_TS)) { + /* non-opaque texel */ + trualpha = !0; + } + l++; + } + } + } + +#if 0 + if (trualpha) { + fxt1_quantize_ALPHA0(cc, input, reord, l); + } else if (l == 0) { + cc[0] = cc[1] = cc[2] = -1; + cc[3] = 0; + } else if (l < N_TEXELS) { + fxt1_quantize_HI(cc, input, reord, l); + } else { + fxt1_quantize_CHROMA(cc, input); + } + (void)fxt1_quantize_ALPHA1; + (void)fxt1_quantize_MIXED1; + (void)fxt1_quantize_MIXED0; +#else + if (trualpha) { + fxt1_quantize_ALPHA1(cc, input); + } else if (l == 0) { + cc[0] = cc[1] = cc[2] = ~0UL; + cc[3] = 0; + } else if (l < N_TEXELS) { + fxt1_quantize_MIXED1(cc, input); + } else { + fxt1_quantize_MIXED0(cc, input); + } + (void)fxt1_quantize_ALPHA0; + (void)fxt1_quantize_HI; + (void)fxt1_quantize_CHROMA; +#endif +} + + +TAPI int TAPIENTRY +fxt1_encode (int width, int height, int comps, + const void *source, int srcRowStride, + void *dest, int destRowStride) +{ + int x, y; + const byte *data; + dword *encoded = (dword *)dest; + void *newSource = NULL; + + /* Replicate image if width is not M8 or height is not M4 */ + if ((width & 7) | (height & 3)) { + int newWidth = (width + 7) & ~7; + int newHeight = (height + 3) & ~3; + newSource = malloc(comps * newWidth * newHeight * sizeof(byte *)); + _mesa_upscale_teximage2d(width, height, newWidth, newHeight, + comps, (const byte *)source, + srcRowStride, (byte *)newSource); + source = newSource; + width = newWidth; + height = newHeight; + srcRowStride = comps * newWidth; + } + + data = (const byte *)source; + destRowStride = (destRowStride - width * 2) / 4; + for (y = 0; y < height; y += 4) { + unsigned int offs = 0 + (y + 0) * srcRowStride; + for (x = 0; x < width; x += 8) { + const byte *lines[4]; + lines[0] = &data[offs]; + lines[1] = lines[0] + srcRowStride; + lines[2] = lines[1] + srcRowStride; + lines[3] = lines[2] + srcRowStride; + offs += 8 * comps; + fxt1_quantize(encoded, lines, comps); + /* 128 bits per 8x4 block */ + encoded += 4; + } + encoded += destRowStride; + } + + if (newSource != NULL) { + free(newSource); + } + + return 0; +} + + +/***************************************************************************\ + * FXT1 decoder + * + * The decoder is based on GL_3DFX_texture_compression_FXT1 + * specification and serves as a concept for the encoder. +\***************************************************************************/ + + +/* lookup table for scaling 5 bit colors up to 8 bits */ +static const byte _rgb_scale_5[] = { + 0, 8, 16, 25, 33, 41, 49, 58, + 66, 74, 82, 90, 99, 107, 115, 123, + 132, 140, 148, 156, 165, 173, 181, 189, + 197, 206, 214, 222, 230, 239, 247, 255 +}; + +/* lookup table for scaling 6 bit colors up to 8 bits */ +static const byte _rgb_scale_6[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 45, 49, 53, 57, 61, + 65, 69, 73, 77, 81, 85, 89, 93, + 97, 101, 105, 109, 113, 117, 121, 125, + 130, 134, 138, 142, 146, 150, 154, 158, + 162, 166, 170, 174, 178, 182, 186, 190, + 194, 198, 202, 206, 210, 215, 219, 223, + 227, 231, 235, 239, 243, 247, 251, 255 +}; + + +#define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31)) +#define UP5(c) _rgb_scale_5[(c) & 31] +#define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)] +#define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n) +#define ZERO_4UBV(v) *((dword *)(v)) = 0 + + +static void +fxt1_decode_1HI (const byte *code, int t, byte *rgba) +{ + const dword *cc; + + t *= 3; + cc = (const dword *)(code + t / 8); + t = (cc[0] >> (t & 7)) & 7; + + if (t == 7) { + ZERO_4UBV(rgba); + } else { + cc = (const dword *)(code + 12); + if (t == 0) { + rgba[BCOMP] = UP5(CC_SEL(cc, 0)); + rgba[GCOMP] = UP5(CC_SEL(cc, 5)); + rgba[RCOMP] = UP5(CC_SEL(cc, 10)); + } else if (t == 6) { + rgba[BCOMP] = UP5(CC_SEL(cc, 15)); + rgba[GCOMP] = UP5(CC_SEL(cc, 20)); + rgba[RCOMP] = UP5(CC_SEL(cc, 25)); + } else { + rgba[BCOMP] = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15))); + rgba[GCOMP] = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20))); + rgba[RCOMP] = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25))); + } + rgba[ACOMP] = 255; + } +} + + +static void +fxt1_decode_1CHROMA (const byte *code, int t, byte *rgba) +{ + const dword *cc; + dword kk; + + cc = (const dword *)code; + if (t & 16) { + cc++; + t &= 15; + } + t = (cc[0] >> (t * 2)) & 3; + + t *= 15; + cc = (const dword *)(code + 8 + t / 8); + kk = cc[0] >> (t & 7); + rgba[BCOMP] = UP5(kk); + rgba[GCOMP] = UP5(kk >> 5); + rgba[RCOMP] = UP5(kk >> 10); + rgba[ACOMP] = 255; +} + + +static void +fxt1_decode_1MIXED (const byte *code, int t, byte *rgba) +{ + const dword *cc; + int col[2][3]; + int glsb, selb; + + cc = (const dword *)code; + if (t & 16) { + t &= 15; + t = (cc[1] >> (t * 2)) & 3; + /* col 2 */ + col[0][BCOMP] = (*(const dword *)(code + 11)) >> 6; + col[0][GCOMP] = CC_SEL(cc, 99); + col[0][RCOMP] = CC_SEL(cc, 104); + /* col 3 */ + col[1][BCOMP] = CC_SEL(cc, 109); + col[1][GCOMP] = CC_SEL(cc, 114); + col[1][RCOMP] = CC_SEL(cc, 119); + glsb = CC_SEL(cc, 126); + selb = CC_SEL(cc, 33); + } else { + t = (cc[0] >> (t * 2)) & 3; + /* col 0 */ + col[0][BCOMP] = CC_SEL(cc, 64); + col[0][GCOMP] = CC_SEL(cc, 69); + col[0][RCOMP] = CC_SEL(cc, 74); + /* col 1 */ + col[1][BCOMP] = CC_SEL(cc, 79); + col[1][GCOMP] = CC_SEL(cc, 84); + col[1][RCOMP] = CC_SEL(cc, 89); + glsb = CC_SEL(cc, 125); + selb = CC_SEL(cc, 1); + } + + if (CC_SEL(cc, 124) & 1) { + /* alpha[0] == 1 */ + + if (t == 3) { + ZERO_4UBV(rgba); + } else { + if (t == 0) { + rgba[BCOMP] = UP5(col[0][BCOMP]); + rgba[GCOMP] = UP5(col[0][GCOMP]); + rgba[RCOMP] = UP5(col[0][RCOMP]); + } else if (t == 2) { + rgba[BCOMP] = UP5(col[1][BCOMP]); + rgba[GCOMP] = UP6(col[1][GCOMP], glsb); + rgba[RCOMP] = UP5(col[1][RCOMP]); + } else { + rgba[BCOMP] = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2; + rgba[GCOMP] = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2; + rgba[RCOMP] = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2; + } + rgba[ACOMP] = 255; + } + } else { + /* alpha[0] == 0 */ + + if (t == 0) { + rgba[BCOMP] = UP5(col[0][BCOMP]); + rgba[GCOMP] = UP6(col[0][GCOMP], glsb ^ selb); + rgba[RCOMP] = UP5(col[0][RCOMP]); + } else if (t == 3) { + rgba[BCOMP] = UP5(col[1][BCOMP]); + rgba[GCOMP] = UP6(col[1][GCOMP], glsb); + rgba[RCOMP] = UP5(col[1][RCOMP]); + } else { + rgba[BCOMP] = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP])); + rgba[GCOMP] = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb), + UP6(col[1][GCOMP], glsb)); + rgba[RCOMP] = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP])); + } + rgba[ACOMP] = 255; + } +} + + +static void +fxt1_decode_1ALPHA (const byte *code, int t, byte *rgba) +{ + const dword *cc; + + cc = (const dword *)code; + if (CC_SEL(cc, 124) & 1) { + /* lerp == 1 */ + int col0[4]; + + if (t & 16) { + t &= 15; + t = (cc[1] >> (t * 2)) & 3; + /* col 2 */ + col0[BCOMP] = (*(const dword *)(code + 11)) >> 6; + col0[GCOMP] = CC_SEL(cc, 99); + col0[RCOMP] = CC_SEL(cc, 104); + col0[ACOMP] = CC_SEL(cc, 119); + } else { + t = (cc[0] >> (t * 2)) & 3; + /* col 0 */ + col0[BCOMP] = CC_SEL(cc, 64); + col0[GCOMP] = CC_SEL(cc, 69); + col0[RCOMP] = CC_SEL(cc, 74); + col0[ACOMP] = CC_SEL(cc, 109); + } + + if (t == 0) { + rgba[BCOMP] = UP5(col0[BCOMP]); + rgba[GCOMP] = UP5(col0[GCOMP]); + rgba[RCOMP] = UP5(col0[RCOMP]); + rgba[ACOMP] = UP5(col0[ACOMP]); + } else if (t == 3) { + rgba[BCOMP] = UP5(CC_SEL(cc, 79)); + rgba[GCOMP] = UP5(CC_SEL(cc, 84)); + rgba[RCOMP] = UP5(CC_SEL(cc, 89)); + rgba[ACOMP] = UP5(CC_SEL(cc, 114)); + } else { + rgba[BCOMP] = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79))); + rgba[GCOMP] = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84))); + rgba[RCOMP] = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89))); + rgba[ACOMP] = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114))); + } + } else { + /* lerp == 0 */ + + if (t & 16) { + cc++; + t &= 15; + } + t = (cc[0] >> (t * 2)) & 3; + + if (t == 3) { + ZERO_4UBV(rgba); + } else { + dword kk; + cc = (const dword *)code; + rgba[ACOMP] = UP5(cc[3] >> (t * 5 + 13)); + t *= 15; + cc = (const dword *)(code + 8 + t / 8); + kk = cc[0] >> (t & 7); + rgba[BCOMP] = UP5(kk); + rgba[GCOMP] = UP5(kk >> 5); + rgba[RCOMP] = UP5(kk >> 10); + } + } +} + + +TAPI void TAPIENTRY +fxt1_decode_1 (const void *texture, int stride, + int i, int j, byte *rgba) +{ + static void (*decode_1[]) (const byte *, int, byte *) = { + fxt1_decode_1HI, /* cc-high = "00?" */ + fxt1_decode_1HI, /* cc-high = "00?" */ + fxt1_decode_1CHROMA, /* cc-chroma = "010" */ + fxt1_decode_1ALPHA, /* alpha = "011" */ + fxt1_decode_1MIXED, /* mixed = "1??" */ + fxt1_decode_1MIXED, /* mixed = "1??" */ + fxt1_decode_1MIXED, /* mixed = "1??" */ + fxt1_decode_1MIXED /* mixed = "1??" */ + }; + + const byte *code = (const byte *)texture + + ((j / 4) * (stride / 8) + (i / 8)) * 16; + int mode = CC_SEL(code, 125); + int t = i & 7; + + if (t & 4) { + t += 12; + } + t += (j & 3) * 4; + + decode_1[mode](code, t, rgba); + +#if VERBOSE + { + extern int cc_chroma; + extern int cc_alpha; + extern int cc_high; + extern int cc_mixed; + static int *cctype[] = { + &cc_high, + &cc_high, + &cc_chroma, + &cc_alpha, + &cc_mixed, + &cc_mixed, + &cc_mixed, + &cc_mixed + }; + (*cctype[mode])++; + } +#endif +} diff --git a/GLideNHQ/tc-1.1+/fxt1.h b/GLideNHQ/tc-1.1+/fxt1.h new file mode 100644 index 00000000..c2919bba --- /dev/null +++ b/GLideNHQ/tc-1.1+/fxt1.h @@ -0,0 +1,38 @@ +/* + * FXT1 codec + * Version: 1.1 + * + * Copyright (C) 2004 Daniel Borca All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DANIEL BORCA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef FXT1_H_included +#define FXT1_H_included + +TAPI int TAPIENTRY +fxt1_encode (int width, int height, int comps, + const void *source, int srcRowStride, + void *dest, int destRowStride); + +TAPI void TAPIENTRY +fxt1_decode_1 (const void *texture, int stride /* in pixels */, + int i, int j, byte *rgba); + +#endif diff --git a/GLideNHQ/tc-1.1+/fxt1license.txt b/GLideNHQ/tc-1.1+/fxt1license.txt new file mode 100644 index 00000000..234c6c6b --- /dev/null +++ b/GLideNHQ/tc-1.1+/fxt1license.txt @@ -0,0 +1,244 @@ +3DFX FXT1 Source Code General Public License + + +1. PREAMBLE + + This license is for software that provides texture compression and + decompression, particularly in the context of video games. The license + is intended to offer terms similar to some standard General Public + Licenses designed to foster open standards and unrestricted + accessibility to source code. Some of these licenses require that, as + a condition of the license of the software, any derivative works + (that is, new software which is a work containing the original program + or a portion of it) must be available for general use, without + restriction other than for a minor transfer fee, and that the source + code for such derivative works must likewise be made available. The + only restriction is that such derivative works must be subject to + the same General Public License terms as the original work. + + This 3dfx FXT1 Source Code General Public License differs from the + standard licenses of this type in that it does not require the entire + derivative work to be made available under the terms of this license + nor is the recipient required to make available the source code for + the entire derivative work. Rather, the license is limited to only the + identifiable portion of the derivative work that is derived from the + licensed software. The precise terms and conditions for copying, + distribution and modification follow. + + +2. DEFINITIONS + + 2.1 This License applies to any program (or other "work") which + contains a notice placed by the copyright holder saying it may be + distributed under the terms of this 3dfx FXT1 Source Code General + Public License. + + 2.2 The term "Program" as used in this Agreement refers to 3DFX's + FXT1 source code and object code and any Derivative Work. + + 2.3 "Derivative Work" means, for the purpose of the License, that + portion of any work that contains the Program or the identifiable + portion of a work that is derived from the Program, either verbatim or + with modifications and/or translated into another language, and that + performs texture compression and decompression. It does not include + any other portions of a work. + + 2.4 "Modifications of the Program" means any work, which includes a + Derivative Work, and includes the whole of such work. + + 2.5 "License" means this 3dfx FXT1 Source Code General Public License. + + 2.6 The "Source Code" for a work means the preferred form of the work + for making modifications to it. For an executable work, complete source + code means all the source code for all modules it contains, any + associated interface definition files, and the scripts used to control + compilation and installation of the executable work. + + 2.7 "3dfx" means 3dfx Interactive, Inc. + + +3. LICENSED ACTIVITIES + + 3.1 COPYING - You may copy and distribute verbatim copies of the + Program's Source Code as you receive it, in any medium, subject to the + provision of section 3.3 and provided also that: + + (a) you conspicuously and appropriately publish on each copy + an appropriate copyright notice (3dfx Interactive, Inc. 1999), a notice + that recipients who wish to copy, distribute or modify the Program can + only do so subject to this License, and a disclaimer of warranty as + set forth in section 5; + + (b) keep intact all the notices that refer to this License and + to the absence of any warranty; and + + (c) give all recipients of the Program a copy of this License + along with the Program or instructions on how to easily receive a copy + of this License. + + + 3.2 MODIFICATION OF THE PROGRAM/DERIVATIVE WORKS - You may modify your + copy or copies of the Program or any portion of it, and copy and + distribute such modifications subject to the provisions of section 3.3 + and provided that you also meet all of the following conditions: + + (a) you conspicuously and appropriately publish on each copy + of a Derivative Work an appropriate copyright notice, a notice that + recipients who wish to copy, distribute or modify the Derivative Work + can only do so subject to this License, and a disclaimer of warranty + as set forth in section 5; + + (b) keep intact all the notices that refer to this License and + to the absence of any warranty; and + + (c) give all recipients of the Derivative Work a copy of this + License along with the Derivative Work or instructions on how to easily + receive a copy of this License. + + (d) You must cause the modified files of the Derivative Work + to carry prominent notices stating that you changed the files and the + date of any change. + + (e) You must cause any Derivative Work that you distribute or + publish to be licensed at no charge to all third parties under the + terms of this License. + + (f) If the Derivative Work normally reads commands + interactively when run, you must cause it, when started running for + such interactive use, to print or display an announcement as follows: + + "COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED THIS + SOFTWARE IS FREE AND PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, + EITHER EXPRESSED OR IMPLIED. SEE THE 3DFX FXT1 GENERAL PUBLIC LICENSE + FOR A FULL TEXT OF THE DISTRIBUTION AND NON-WARRANTY PROVISIONS + (REQUEST COPY FROM INFO@3DFX.COM)." + + (g) The requirements of this section 3.2 do not apply to the + modified work as a whole but only to the Derivative Work. It is not + the intent of this License to claim rights or contest your rights to + work written entirely by you; rather, the intent is to exercise the + right to control the distribution of Derivative Works. + + + 3.3 DISTRIBUTION + + (a) All copies of the Program or Derivative Works which are + distributed must include in the file headers the following language + verbatim: + + "THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED + ONLY PURSUANT TO THE 3DFX FXT1 GENERAL PUBLIC LICENSE. A COPY OF THIS + LICENSE MAY BE OBTAINED FROM THE DISTRIBUTOR OR BY CONTACTING 3DFX + INTERACTIVE INC (info@3dfx.com). THIS PROGRAM. IS PROVIDED "AS IS" + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. SEE THE + 3DFX FXT1 GENERAL PUBLIC LICENSE FOR A FULL TEXT OF THE NON-WARRANTY + PROVISIONS. + + USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO + RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS + IN TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, + AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR + SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF + THE UNITED STATES. + + COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED" + + (b) You may distribute the Program or a Derivative Work in + object code or executable form under the terms of Sections 3.1 and 3.2 + provided that you also do one of the following: + + (1) Accompany it with the complete corresponding + machine-readable source code, which must be distributed under the + terms of Sections 3.1 and 3.2; or, + + (2) Accompany it with a written offer, valid for at + least three years, to give any third party, for a charge no more than + your cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 3.1 and 3.2 on a medium + customarily used for software interchange; or, + + (3) Accompany it with the information you received as + to the offer to distribute corresponding source code. (This alternative + is allowed only for noncommercial distribution and only if you received + the program in object code or executable form with such an offer, in + accord with Subsection 3.3(b)(2) above.) + + (c) The source code distributed need not include anything + that is normally distributed (in either source or binary form) with + the major components (compiler, kernel, and so on) of the operating + system on which the executable runs, unless that component itself + accompanies the executable code. + + (d) If distribution of executable code or object code is made + by offering access to copy from a designated place, then offering + equivalent access to copy the source code from the same place counts + as distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + (e) Each time you redistribute the Program or any Derivative + Work, the recipient automatically receives a license from 3dfx and + successor licensors to copy, distribute or modify the Program and + Derivative Works subject to the terms and conditions of the License. + You may not impose any further restrictions on the recipients' + exercise of the rights granted herein. You are not responsible for + enforcing compliance by third parties to this License. + + (f) You may not copy, modify, sublicense, or distribute the + Program or any Derivative Works except as expressly provided under + this License. Any attempt otherwise to copy, modify, sublicense or + distribute the Program or any Derivative Works is void, and will + automatically terminate your rights under this License. However, + parties who have received copies, or rights, from you under this + License will not have their licenses terminated so long as such + parties remain in full compliance. + + +4. MISCELLANEOUS + + 4.1 Acceptance of this License is voluntary. By using, modifying or + distributing the Program or any Derivative Work, you indicate your + acceptance of this License to do so, and all its terms and conditions + for copying, distributing or modifying the Program or works based on + it. Nothing else grants you permission to modify or distribute the + Program or Derivative Works and doing so without acceptance of this + License is in violation of the U.S. and international copyright laws. + + 4.2 If the distribution and/or use of the Program or Derivative Works + is restricted in certain countries either by patents or by copyrighted + interfaces, the original copyright holder who places the Program under + this License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only in + or among countries not thus excluded. In such case, this License + incorporates the limitation as if written in the body of this License. + + 4.3 This License is to be construed according to the laws of the + State of California and you consent to personal jurisdiction in the + State of California in the event it is necessary to enforce the + provisions of this License. + + +5. NO WARRANTIES + + 5.1 TO THE EXTENT PERMITTED BY APPLICABLE LAW, THERE IS NO WARRANTY + FOR THE PROGRAM. OR DERIVATIVE WORKS THE COPYRIGHT HOLDERS AND/OR + OTHER PARTIES PROVIDE THE PROGRAM AND ANY DERIVATIVE WORKS"AS IS" + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY + AND PERFORMANCE OF THE PROGRAM AND ANY DERIVATIVE WORK IS WITH YOU. + SHOULD THE PROGRAM OR ANY DERIVATIVE WORK PROVE DEFECTIVE, YOU ASSUME + THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 5.2 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL 3DFX + INTERACTIVE, INC., OR ANY OTHER COPYRIGHT HOLDER, OR ANY OTHER PARTY + WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM OR DERIVATIVE WORKS AS + PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, + SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR + INABILITY TO USE THE PROGRAM OR DERIVATIVE WORKS (INCLUDING BUT NOT + LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES + SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM OR + DERIVATIVE WORKS TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH + HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. + diff --git a/GLideNHQ/tc-1.1+/internal.h b/GLideNHQ/tc-1.1+/internal.h new file mode 100644 index 00000000..f1cd6dca --- /dev/null +++ b/GLideNHQ/tc-1.1+/internal.h @@ -0,0 +1,137 @@ +/* + * Texture compression + * Version: 1.0 + * + * Copyright (C) 2004 Daniel Borca All Rights Reserved. + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef INTERNAL_H_included +#define INTERNAL_H_included + +/*****************************************************************************\ + * DLL stuff +\*****************************************************************************/ + +#ifdef __WIN32__ +#define TAPI __declspec(dllexport) +#define TAPIENTRY /*__stdcall*/ +#else +#define TAPI +#define TAPIENTRY +#endif + + +/*****************************************************************************\ + * 64bit types on 32bit machine +\*****************************************************************************/ + +#if (defined(__GNUC__) && !defined(__cplusplus)) || defined(__MSC__) + +typedef unsigned long long qword; + +#define Q_MOV32(a, b) a = b +#define Q_OR32(a, b) a |= b +#define Q_SHL(a, c) a <<= c + +#else /* !__GNUC__ */ + +typedef struct { + dword lo, hi; +} qword; + +#define Q_MOV32(a, b) a.lo = b +#define Q_OR32(a, b) a.lo |= b +#define Q_SHL(a, c) \ + do { \ + if ((c) >= 32) { \ + a.hi = a.lo << ((c) - 32); \ + a.lo = 0; \ + } else { \ + a.hi = (a.hi << (c)) | (a.lo >> (32 - (c)));\ + a.lo <<= c; \ + } \ + } while (0) + +#endif /* !__GNUC__ */ + + +/*****************************************************************************\ + * Config +\*****************************************************************************/ + +#define RCOMP 0 +#define GCOMP 1 +#define BCOMP 2 +#define ACOMP 3 + +/*****************************************************************************\ + * Metric +\*****************************************************************************/ + +#define F(i) (float)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */ +#define SAFECDOT 1 /* for paranoids */ + +#define MAKEIVEC(NV, NC, IV, B, V0, V1) \ + do { \ + /* compute interpolation vector */\ + float d2 = 0.0F; \ + float rd2; \ + \ + for (i = 0; i < NC; i++) { \ + IV[i] = (V1[i] - V0[i]) * F(i);\ + d2 += IV[i] * IV[i]; \ + } \ + rd2 = (float)NV / d2; \ + B = 0; \ + for (i = 0; i < NC; i++) { \ + IV[i] *= F(i); \ + B -= IV[i] * V0[i]; \ + IV[i] *= rd2; \ + } \ + B = B * rd2 + 0.5F; \ + } while (0) + +#define CALCCDOT(TEXEL, NV, NC, IV, B, V)\ + do { \ + float dot = 0.0F; \ + for (i = 0; i < NC; i++) { \ + dot += V[i] * IV[i]; \ + } \ + TEXEL = (int)(dot + B); \ + if (SAFECDOT) { \ + if (TEXEL < 0) { \ + TEXEL = 0; \ + } else if (TEXEL > NV) { \ + TEXEL = NV; \ + } \ + } \ + } while (0) + + +/*****************************************************************************\ + * Utility functions +\*****************************************************************************/ + +void +_mesa_upscale_teximage2d (unsigned int inWidth, unsigned int inHeight, + unsigned int outWidth, unsigned int outHeight, + unsigned int comps, + const byte *src, int srcRowStride, + unsigned char *dest); + +#endif diff --git a/GLideNHQ/tc-1.1+/texstore.c b/GLideNHQ/tc-1.1+/texstore.c new file mode 100644 index 00000000..2eb0306f --- /dev/null +++ b/GLideNHQ/tc-1.1+/texstore.c @@ -0,0 +1,93 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Copyright (C) 2007 Hiroshi Morii + * _mesa_upscale_teximage2d speedup + */ + +#include + +#include "types.h" +#include "internal.h" + + +void +_mesa_upscale_teximage2d (unsigned int inWidth, unsigned int inHeight, + unsigned int outWidth, unsigned int outHeight, + unsigned int comps, + const byte *src, int srcRowStride, + byte *dest) +{ + unsigned int i, j, k; + + assert(outWidth >= inWidth); + assert(outHeight >= inHeight); + +#if 1 /* H.Morii - faster loops */ + for (i = 0; i < inHeight; i++) { + for (j = 0; j < inWidth; j++) { + const int aa = (i * outWidth + j) * comps; + const int bb = i * srcRowStride + j * comps; + for (k = 0; k < comps; k++) { + dest[aa + k] = src[bb + k]; + } + } + for (; j < outWidth; j++) { + const int aa = (i * outWidth + j) * comps; + const int bb = i * srcRowStride + (j - inWidth) * comps; + for (k = 0; k < comps; k++) { + dest[aa + k] = src[bb + k]; + } + } + } + for (; i < outHeight; i++) { + for (j = 0; j < inWidth; j++) { + const int aa = (i * outWidth + j) * comps; + const int bb = (i - inHeight) * srcRowStride + j * comps; + for (k = 0; k < comps; k++) { + dest[aa + k] = src[bb + k]; + } + } + for (; j < outWidth; j++) { + const int aa = (i * outWidth + j) * comps; + const int bb = (i - inHeight) * srcRowStride + (j - inWidth) * comps; + for (k = 0; k < comps; k++) { + dest[aa + k] = src[bb + k]; + } + } + } +#else + for (i = 0; i < outHeight; i++) { + const int ii = i % inHeight; + for (j = 0; j < outWidth; j++) { + const int jj = j % inWidth; + const int aa = (i * outWidth + j) * comps; + const int bb = ii * srcRowStride + jj * comps; + for (k = 0; k < comps; k++) { + dest[aa + k] = src[bb + k]; + } + } + } +#endif +} diff --git a/GLideNHQ/tc-1.1+/types.h b/GLideNHQ/tc-1.1+/types.h new file mode 100644 index 00000000..40e7153a --- /dev/null +++ b/GLideNHQ/tc-1.1+/types.h @@ -0,0 +1,11 @@ +#ifndef TYPES_H_included +#define TYPES_H_included + +/*****************************************************************************\ + * 32bit types +\*****************************************************************************/ +typedef unsigned char byte; /* 8-bit */ +typedef unsigned short word; /* 16-bit */ +typedef unsigned int dword; /* 32-bit */ + +#endif diff --git a/GLideNHQ/tc-1.1+/wrapper.c b/GLideNHQ/tc-1.1+/wrapper.c new file mode 100644 index 00000000..7bc8d610 --- /dev/null +++ b/GLideNHQ/tc-1.1+/wrapper.c @@ -0,0 +1,110 @@ +/* + * Texture compression + * Version: 1.0 + * + * Copyright (C) 2004 Daniel Borca All Rights Reserved. + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include + +#include "types.h" +#include "internal.h" +#include "dxtn.h" + + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + + +TAPI void TAPIENTRY +fetch_2d_texel_rgb_dxt1 (int texImage_RowStride, + const byte *texImage_Data, + int i, int j, + byte *texel) +{ + dxt1_rgb_decode_1(texImage_Data, texImage_RowStride, i, j, texel); +} + + +TAPI void TAPIENTRY +fetch_2d_texel_rgba_dxt1 (int texImage_RowStride, + const byte *texImage_Data, + int i, int j, + byte *texel) +{ + dxt1_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel); +} + + +TAPI void TAPIENTRY +fetch_2d_texel_rgba_dxt3 (int texImage_RowStride, + const byte *texImage_Data, + int i, int j, + byte *texel) +{ + dxt3_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel); +} + + +TAPI void TAPIENTRY +fetch_2d_texel_rgba_dxt5 (int texImage_RowStride, + const byte *texImage_Data, + int i, int j, + byte *texel) +{ + dxt5_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel); +} + + +TAPI void TAPIENTRY +tx_compress_dxtn (int srccomps, int width, int height, + const byte *source, int destformat, byte *dest, + int destRowStride) +{ + int srcRowStride = width * srccomps; + int rv; + + switch (destformat) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + rv = dxt1_rgb_encode(width, height, srccomps, + source, srcRowStride, + dest, destRowStride); + break; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + rv = dxt1_rgba_encode(width, height, srccomps, + source, srcRowStride, + dest, destRowStride); + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + rv = dxt3_rgba_encode(width, height, srccomps, + source, srcRowStride, + dest, destRowStride); + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + rv = dxt5_rgba_encode(width, height, srccomps, + source, srcRowStride, + dest, destRowStride); + break; + default: + assert(0); + } + + /*return rv;*/ +} diff --git a/GLideNHQ/test/Makefile.gcc b/GLideNHQ/test/Makefile.gcc new file mode 100644 index 00000000..e76af4bf --- /dev/null +++ b/GLideNHQ/test/Makefile.gcc @@ -0,0 +1,70 @@ +# This MUST be processed by GNU make +# +# Texture Filtering Test Linux Makefile +# Version: 1.0 +# +# Copyright (C) 2007 Hiroshi Morii All Rights Reserved. +# Email koolsmoky(at)users.sourceforge.net +# Web http://www.3dfxzone.it/koolsmoky +# +# this is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# this is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Make; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# Available options: +# +# Environment variables: +# +# Targets: +# all: build dynamic module +# clean: remove object files +# realclean: remove all generated files +# + +# +# GCC does not have SEH (structured exception handling) +# + +.PHONY: all clean realclean + +CC = g++ +CFLAGS += -I. -I../ +CFLAGS += -fPIC -DPIC +CFLAGS += -DGHQCHK=1 + +LD = g++ +LDFLAGS += -ldl -lstdc++ + +RM = rm + +SOURCES = \ + test.cpp \ + ../Ext_TxFilter.cpp + +OBJECTS = $(SOURCES:.cpp=.o) + +.cpp.o: + $(CC) -o $@ $(CFLAGS) -c $< + +all: test.exe + +test.exe: $(OBJECTS) + $(LD) -o $@ $(LDFLAGS) $^ + +clean: + -$(RM) *.o + +realclean: clean + -$(RM) test.exe diff --git a/GLideNHQ/test/Makefile.vc8 b/GLideNHQ/test/Makefile.vc8 new file mode 100644 index 00000000..007f5389 --- /dev/null +++ b/GLideNHQ/test/Makefile.vc8 @@ -0,0 +1,68 @@ +# This MUST be processed by GNU make +# +# Texture Filtering Test MSVC Makefile +# Version: 1.0 +# +# Copyright (C) 2007 Hiroshi Morii All Rights Reserved. +# Email koolsmoky(at)users.sourceforge.net +# Web http://www.3dfxzone.it/koolsmoky +# +# this is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# this is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Make; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# Available options: +# +# Targets: +# all: build everything +# clean: remove object files +# realclean: remove all generated files +# + +.PHONY: all clean realclean +.SUFFIXES: .cpp .obj + +CC = cl +LD = _link # change this to suite your build environment + +UNLINK = $(RM) $(1) + +CFLAGS += -D__MSC__ -DWIN32 -D_CONSOLE -EHa -D_CRT_SECURE_NO_DEPRECATE +CFLAGS += -I. -I../ +CFLAGS += -DGHQCHK=1 + +#LDFLAGS += -ltcg:STATUS + +SOURCES = \ + test.cpp \ + ../Ext_TxFilter.cpp + +OBJECTS = $(SOURCES:.cpp=.obj) + +.cpp.obj: + $(CC) -Fo$@ $(CFLAGS) -c $< + +all: test.exe + +test.exe: $(OBJECTS) + $(LD) -out:$@ $(LDFLAGS) $(OBJECTS) + +$(OBJECTS): $(SOURCES) + +clean: + -$(RM) *.obj *.pdb *.ilk + +realclean: clean + -$(RM) test.exe diff --git a/GLideNHQ/test/test.cpp b/GLideNHQ/test/test.cpp new file mode 100644 index 00000000..6c83972b --- /dev/null +++ b/GLideNHQ/test/test.cpp @@ -0,0 +1,120 @@ +/* + * Texture Filtering + * Version: 1.0 + * + * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. + * Email koolsmoky(at)users.sourceforge.net + * Web http://www.3dfxzone.it/koolsmoky + * + * this is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * this is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Ext_TxFilter.h" +#include +#include +#include + +void DisplayLoadProgress(const wchar_t *format, ...) +{ +#if 0 + va_list args; + wchar_t wbuf[INFO_BUF]; + char buf[INFO_BUF]; + + /* process input */ + va_start(args, format); + vswprintf(wbuf, format, args); + va_end(args); + + /* XXX: convert to multibyte */ + wcstombs(buf, wbuf, INFO_BUF); + printf(buf); +#else + static unsigned int i = 0; + i++; + if (i == 1) printf("\b-"); + else if (i == 2) printf("\b\\"); + else if (i == 3) printf("\b|"); + else { + printf("\b/"); + i = 0; + } +#endif +} + +int main(int argc, char* argv[]) +{ + float dummy = 1.1; /* force the compiler to load floating point support */ + boolean bret = 0; + int options = 0; + + /* Plugin path */ + wchar_t path[MAX_PATH]; +#ifdef WIN32 + GETCWD(MAX_PATH, path); +#else + char cbuf[MAX_PATH]; + GETCWD(MAX_PATH, cbuf); + mbstowcs(path, cbuf, MAX_PATH); +#endif + + /* ROM name */ + wchar_t name[21] = L"DEFAULT"; + + printf("------------------------------------------------------------------\n"); + printf(" GlideHQ Hires Texture Checker version 1.2\n"); + printf(" Copyright (C) 2010 Hiroshi Morii All Rights Reserved\n"); + printf(" email : koolsmoky(at)users.sourceforge.net\n"); + printf(" website : http://www.3dfxzone.it/koolsmoky\n"); + printf("\n"); + printf(" Glide64 official website : http://glide64.emuxhaven.net\n"); + printf("\n"); + printf(" Usage: ghqchk.exe \"INTERNAL ROM NAME\"\n"); + printf("------------------------------------------------------------------\n"); + + if (argc != 2) return 0; + + printf("Checking \"%s\"... ", argv[1]); + + mbstowcs(name, argv[1], 21); + + //options |= COMPRESS_TEX; + //options |= COMPRESS_HIRESTEX; + //options |= S3TC_COMPRESSION; + //options |= TILE_HIRESTEX; + //options |= FORCE16BPP_TEX; + //options |= FORCE16BPP_HIRESTEX; + //options |= GZ_TEXCACHE; + options |= GZ_HIRESTEXCACHE; + //options |= (DUMP_TEXCACHE|DUMP_HIRESTEXCACHE); + options |= LET_TEXARTISTS_FLY; + //options |= DUMP_TEX; + options |= RICE_HIRESTEXTURES; + + bret = ext_ghq_init(1024, // max texture width supported by hardware + 1024, // max texture height supported by hardware + 32, // max texture bpp supported by hardware + options, + 0, // cache texture to system memory + path, // plugin path + name, // name of ROM. must be no longer than 256 characters + DisplayLoadProgress); + + ext_ghq_shutdown(); + + printf("\bDone!\nLogged to ghqchk.txt\n"); + + return bret; +}