diff --git a/common/GameUI/cvarslider.cpp b/common/GameUI/cvarslider.cpp index 7220538..7e01ace 100644 --- a/common/GameUI/cvarslider.cpp +++ b/common/GameUI/cvarslider.cpp @@ -52,40 +52,24 @@ CCvarSlider::CCvarSlider( Panel *parent, const char *panelName, char const *capt //----------------------------------------------------------------------------- void CCvarSlider::SetupSlider( float minValue, float maxValue, const char *cvarname, bool bAllowOutOfRange ) { - // make sure min/max don't go outside cvar range if there's one - ConVarRef var( cvarname, true ); - if ( var.IsValid() ) - { - float flCVarMin; - if ( var.GetMin( flCVarMin ) ) - { - minValue = m_bUseConVarMinMax ? flCVarMin : MAX( minValue, flCVarMin ); - } - float flCVarMax; - if ( var.GetMax( flCVarMax ) ) - { - maxValue = m_bUseConVarMinMax ? flCVarMax : MIN( maxValue, flCVarMax ); - } - } - m_flMinValue = minValue; m_flMaxValue = maxValue; // scale by CVARSLIDER_SCALE_FACTOR - SetRange( (int)( CVARSLIDER_SCALE_FACTOR * minValue ), (int)( CVARSLIDER_SCALE_FACTOR * maxValue ) ); + SetRange((int)(CVARSLIDER_SCALE_FACTOR * minValue), (int)(CVARSLIDER_SCALE_FACTOR * maxValue)); - char szMin[ 32 ]; - char szMax[ 32 ]; + char szMin[32]; + char szMax[32]; - Q_snprintf( szMin, sizeof( szMin ), "%.2f", minValue ); - Q_snprintf( szMax, sizeof( szMax ), "%.2f", maxValue ); + Q_snprintf(szMin, sizeof(szMin), "%.2f", minValue); + Q_snprintf(szMax, sizeof(szMax), "%.2f", maxValue); - SetTickCaptions( szMin, szMax ); + SetTickCaptions(szMin, szMax); - Q_strncpy( m_szCvarName, cvarname, sizeof( m_szCvarName ) ); + Q_strncpy(m_szCvarName, cvarname, sizeof(m_szCvarName)); - m_bModifiedOnce = false; - m_bAllowOutOfRange = bAllowOutOfRange; + m_bModifiedOnce = false; + m_bAllowOutOfRange = bAllowOutOfRange; // Set slider to current value Reset(); diff --git a/common/IObjectContainer.h b/common/IObjectContainer.h new file mode 100644 index 0000000..5ca4f59 --- /dev/null +++ b/common/IObjectContainer.h @@ -0,0 +1,32 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: IObjectContainer.h: interface for the ObjectContainer class. +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef IOBJECTCONTAINER_H +#define IOBJECTCONTAINER_H + +#pragma once + +class IObjectContainer +{ +public: + virtual ~IObjectContainer() {}; + + virtual void Init() = 0; + + virtual bool Add(void * newObject) = 0; + virtual bool Remove(void * object) = 0; + virtual void Clear(bool freeElementsMemory) = 0; + + virtual void * GetFirst() = 0; + virtual void * GetNext() = 0; + + virtual int CountElements() = 0;; + virtual bool Contains(void * object) = 0; + virtual bool IsEmpty() = 0; +}; + +#endif // !defined IOBJECTCONTAINER_H diff --git a/common/IRunGameEngine.h b/common/IRunGameEngine.h new file mode 100644 index 0000000..084e1cd --- /dev/null +++ b/common/IRunGameEngine.h @@ -0,0 +1,81 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#ifndef IRUNGAMEENGINE_H +#define IRUNGAMEENGINE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "interface.h" + +#ifdef GetUserName +#undef GetUserName +#endif + +//----------------------------------------------------------------------------- +// Purpose: Interface to running the game engine +//----------------------------------------------------------------------------- +abstract_class IRunGameEngine : public IBaseInterface +{ +public: + // Returns true if the engine is running, false otherwise. + virtual bool IsRunning() = 0; + + // Adds text to the engine command buffer. Only works if IsRunning() + // returns true on success, false on failure + virtual bool AddTextCommand(const char *text) = 0; + + // runs the engine with the specified command line parameters. Only works if !IsRunning() + // returns true on success, false on failure + virtual bool RunEngine(const char *gameDir, const char *commandLineParams) = 0; + + // returns true if the player is currently connected to a game server + virtual bool IsInGame() = 0; + + // gets information about the server the engine is currently connected to + // returns true on success, false on failure + virtual bool GetGameInfo(char *infoBuffer, int bufferSize) = 0; + + // tells the engine our userID + virtual void SetTrackerUserID(int trackerID, const char *trackerName) = 0; + + // this next section could probably moved to another interface + // iterates users + // returns the number of user + virtual int GetPlayerCount() = 0; + + // returns a playerID for a player + // playerIndex is in the range [0, GetPlayerCount) + virtual unsigned int GetPlayerFriendsID(int playerIndex) = 0; + + // gets the in-game name of another user, returns NULL if that user doesn't exists + virtual const char *GetPlayerName(int friendsID, char *name, int namelen) = 0; + + // gets the friends name of a player + virtual const char *GetPlayerFriendsName(int friendsID, char *name, int namelen) = 0; + + // returns the engine build number and mod version string for server versioning + virtual unsigned int GetEngineBuildNumber() = 0; + virtual const char *GetProductVersionString() = 0; + + // new interface to RunEngine (done so we don't have to roll the interface version) + virtual bool RunEngine2(const char *gameDir, const char *commandLineParams, bool isSourceGame) = 0; + + enum ERunResult + { + k_ERunResultOkay = 0, + k_ERunResultModNotInstalled = 1, + k_ERunResultAppNotFound = 2, + k_ERunResultNotInitialized = 3, + }; + virtual ERunResult RunEngine( int iAppID, const char *gameDir, const char *commandLineParams ) = 0; + +}; + +#define RUNGAMEENGINE_INTERFACE_VERSION "RunGameEngine005" + +#endif // IRUNGAMEENGINE_H diff --git a/common/ValveCDKeyGameAndTerritoryCodes.h b/common/ValveCDKeyGameAndTerritoryCodes.h new file mode 100644 index 0000000..a371012 --- /dev/null +++ b/common/ValveCDKeyGameAndTerritoryCodes.h @@ -0,0 +1,173 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef VALVECDKEYGAMEANDTERRITORYCODES_H +#define VALVECDKEYGAMEANDTERRITORYCODES_H +#ifdef _WIN32 +#pragma once +#endif + +// imported from MainIntegration/Deliverables/Production/Client/Inc/NewValveCDKeyGenerator.h +// if the enums there change, this needs to change +//!! these need to be moved out into a seperate file in steam, so that src can use the directly published version + +// +// GameCode +// + +enum EGameCode +{ + // DoD uses SteamInstanceId = 1 + // DoD CD-key Steam IDs are displayed as VALVE_1:xxxxxxxx where xxxx is the SteamLocalUserId mentioned above. + // DoD CD-keys uses an odd scheme (invented in a rush) whereby the SteamLocalUserID is generated by hashing + // (MD5) the CD key parameters (Territory,GameCode,UniqueSerialNumber) and truncating the resulting hash for + // a reasonable display length (26 bits, i.e. eMaskLargestAcceptableLocalUserId above, which is about 8 decimal digits). + // **The generator must therefore discard any UniqueSerialNumbers that cause hashes to collide.** + // This means that when generating a new batch from a non-zero StartUniqueSerialNumber, the generator has + // to generate them all from 0 anyway to populate an array of 'hash has been used' flags -- it then only + // prints out new keys higher than the requested StartUniqueSerialNumber. + // IMPORTANT: this means that each match of N keys generated consumes MORE THAN N UniqueSerialNumbers -- + // so each new batch MUST be started with the correct "Next StartUniqueSerialNumber" that was output + // at the end of the previous batch, or the new batch will overlap with the previous batch. + eDayOfDefeat = 0, + + // CZ uses SteamInstanceId = 2 (**as will all future games using this system**) + // CZ CD-key SteamLocalUserIds have + // high32bits = ( GameCode << sc_uNumBitsSalesTerritory) | SalesTerritory + // low32bits = UniqueSerialNumber + // CZ CD-key Steam IDs will be displayed as VALVE_2:GameCode:UniqueSerialNumber + // (i.e. the DoD hashing scheme is *NOT* used). + eConditionZero = 1, + + // CyberCafes receive all legacy and future products, under this one code. + // They have their own SalesTerritory codes too. + // If a CDKey has this game code OR a CyberCafe SalesTerritory then it is a 'cybercafe CDkey'. + eCyberCafeBundle = 2, + + eHalfLife2 = 3, + + eHalfLife2RetailCE = 4, + + eHalfLife2Retail = 5, +}; + + +// +// SalesTerritory +// + +enum ESalesTerritory +{ + // DoD first batch 80,000 keys **Next free 'StartUniqueSerialNumber' = 80032 + // DoD second batch 30,000 keys **Next free 'StartUniqueSerialNumber' = 110081 + // OLD KEY ... NOTE: this CZ first batch for USA (code 0) of 275,000 may also be distributed in Canada + // OLD KEY ... i.e. they should ideally have had code 11, but we didn't want to re-issue them. + // OLD KEY ConditionZero first batch 275,000 keys **Next free 'StartUniqueSerialNumber' = 275000 + // NEW KEY These were moved to region 11 as suggested above (part of first batch of 379,000) + eUSA = 0, + + // DoD first batch 7,500 keys **Next free 'StartUniqueSerialNumber' = 7500 + eAustralia = 1, + + // DoD first batch 15,000 keys **Next free 'StartUniqueSerialNumber' = 15000 + eKorea = 2, + + // DoD first batch 10,000 keys **Next free 'StartUniqueSerialNumber' = 10000 + eTaiwan = 3, + + // DoD first batch 5,000 keys **Next free 'StartUniqueSerialNumber' = 5000 + eJapan = 4, + + // DoD first batch 25,000 keys **Next free 'StartUniqueSerialNumber' = 25003 + // ConditionZero first batch 99,000 keys **Next free 'StartUniqueSerialNumber' = 99000 + eUK = 5, + + // DoD first batch 15,000 keys **Next free 'StartUniqueSerialNumber' = 15002 + // ConditionZero first batch 77,000 keys **Next free 'StartUniqueSerialNumber' = 77000 + eFrance = 6, + + // DoD first batch 3,000 keys **Next free 'StartUniqueSerialNumber' = 3000 + // DoD second batch 5,000 keys **Next free 'StartUniqueSerialNumber' = 8002 + // ConditionZero first batch 132,000 keys **Next free 'StartUniqueSerialNumber' = 132000 + eGermany = 7, + + // DoD first batch 3,000 keys **Next free 'StartUniqueSerialNumber' = 3000 + // ConditionZero first batch 27,500 keys **Next free 'StartUniqueSerialNumber' = 27500 + eSpain = 8, + + // DoD first batch 3,000 keys **Next free 'StartUniqueSerialNumber' = 3000 + // ConditionZero first batch 44,000 keys **Next free 'StartUniqueSerialNumber' = 44000 + eItaly = 9, + + // DoD first batch 65,000 keys **Next free 'StartUniqueSerialNumber' = 65039 + // DoD second batch 20,000 keys **Next free 'StartUniqueSerialNumber' = 85058 + eChina = 10, + + // This is ALL 'American' ENGLISH-SPEAKING TERRITORIES (e.g. USA, Austrailia, Canada, NZ, but *NOT* UK). + // Vivendi track sales by language, rather that geographically. + // OLD KEY ... NOTE: CZ first batch for USA (code 0) of 275,000 will also be distributed in these territories + // OLD KEY ... i.e. they should ideally have had this code, but we didn't want to re-issue them. + // OLD KEY ConditionZero first batch 25,000 keys **Next free 'StartUniqueSerialNumber' = 25000 + // OLD KEY ConditionZero second batch 79,000 keys **Next free 'StartUniqueSerialNumber' = 104000 + // NEW KEY ConditionZero first batch 379,000 keys **Next free 'StartUniqueSerialNumber' = + eEnglish = 11, + + // CyberCafe specific territories. If a CDKey has this game code OR a CyberCafe SalesTerritory then it is a 'cybercafe CDkey'. + // CyberCafeBundle first batch 15,000 keys **Next free 'StartUniqueSerialNumber' = 15000 + eCyberCafeEurope = 12, + // CyberCafeBundle first batch 15,000 keys **Next free 'StartUniqueSerialNumber' = 15000 + eCyberCafeNorthAndSouthAmerica = 13, + // CyberCafeBundle first batch 15,000 keys **Next free 'StartUniqueSerialNumber' = 15000 + eCyberCafeKorea = 14, + // CyberCafeBundle first batch 15,000 keys **Next free 'StartUniqueSerialNumber' = 15000 + eCyberCafeChinaTaiwan = 15, + // CyberCafeBundle first batch 15,000 keys **Next free 'StartUniqueSerialNumber' = 15000 + eCyberCafeRestOfAsia = 16, + + // ATI OEM + // *** After intranet security breach, only the first 40,000 of these keys are valid: + // OLD KEY HL2 first batch 250,000 keys + // *** After intranet security breach, these keys use a new MAC key: + // NEW KEY HL2 first batch start=40,000 210,000 keys + eATI_OEM = 17, + + // ConditionZero first batch 5,500 keys **Next free 'StartUniqueSerialNumber' = 5500 + eLatinAmerica = 18, + + // ConditionZero first batch 16,500 keys **Next free 'StartUniqueSerialNumber' = 16500 + eBrazil = 19, + + // ConditionZero first batch 66,000 keys **Next free 'StartUniqueSerialNumber' = 66000 + eNordic = 20, + + // This a Vivendi code meaning "Belgium, Luxembourg, French speaking territories of Africa, French overseas departments, Netherlands, Quebec" + // ConditionZero first batch 40,700 keys **Next free 'StartUniqueSerialNumber' = 40700 + eExportFrance = 21, + + // This a Vivendi code meaning "Austria, Switzerland, Bulgaria, Czech Republic, Hungary, Lithuania, Poland, Romania, Russian Federation, Slovenia, Slovakia" + // ConditionZero first batch 16,500 keys **Next free 'StartUniqueSerialNumber' = 16500 + eExportNorth = 22, + + // This a Vivendi code meaning "Cyprus, Egypt, Greece, Israel, Lebanon, Malta, Turkey" + // ConditionZero first batch 40,700 keys **Next free 'StartUniqueSerialNumber' = 40700 + eExportSouth = 23, + + // MISSING ONES ARE ON MI (24..29) + + // ATI Rebate + // HL2 first batch 100,000 keys + eATI_Rebate = 30, + + // Used for internal and pre-release testing keys. + // DoD first batch 20 keys **Next free 'StartUniqueSerialNumber' = 20 + // DoD second batch 150 keys **Next free 'StartUniqueSerialNumber' = 170 + // DoD second batch 500 keys **Next free 'StartUniqueSerialNumber' = 670 + // ConditionZero first batch 200 keys **Next free 'StartUniqueSerialNumber' = 200 + // CyberCafeBundle first batch 100 keys **Next free 'StartUniqueSerialNumber' = 100 + eInternal = 255 +}; + +#endif // VALVECDKEYGAMEANDTERRITORYCODES_H diff --git a/common/imageutils.cpp b/common/imageutils.cpp new file mode 100644 index 0000000..96d6eee --- /dev/null +++ b/common/imageutils.cpp @@ -0,0 +1,2301 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// NOTE: To make use of this file, g_pFullFileSystem must be defined, or you can modify +// this source to take an IFileSystem * as input. +// +//=======================================================================================// + +// @note Tom Bui: we need to use fopen below in the jpeg code, so we can't have this on... +#ifdef PROTECTED_THINGS_ENABLE +#if !defined( POSIX ) +#undef fopen +#endif // POSIX +#endif + +#if defined( WIN32 ) && !defined( _X360 ) +#include // SRC only!! +#elif defined( POSIX ) +#include +#include +#ifdef OSX +#include +#endif +#endif + +#include "imageutils.h" +#include "filesystem.h" +#include "utlbuffer.h" +#include "bitmap/bitmap.h" +#include "vtf/vtf.h" + +// clang3 on OSX folks the attribute into the prototype, causing a compile failure +// filed radar bug 10397783 +#if ( __clang_major__ == 3 ) +#include +extern void longjmp( jmp_buf, int ) __attribute__((noreturn)); +#endif + + +#ifdef ENGINE_DLL + #include "common.h" +#elif CLIENT_DLL + // @note Tom Bui: instead of forcing the project to include EngineInterface.h... + #include "cdll_int.h" + // engine interface singleton accessors + extern IVEngineClient *engine; + extern class IGameUIFuncs *gameuifuncs; + extern class IEngineSound *enginesound; + extern class IMatchmaking *matchmaking; + extern class IXboxSystem *xboxsystem; + extern class IAchievementMgr *achievementmgr; + extern class CSteamAPIContext *steamapicontext; +#elif REPLAY_DLL + #include "replay/ienginereplay.h" + extern IEngineReplay *g_pEngine; +#elif ENGINE_DLL + #include "EngineInterface.h" +#else + #include "cdll_int.h" + extern IVEngineClient *engine; +#endif + +// use the JPEGLIB_USE_STDIO define so that we can read in jpeg's from outside the game directory tree. +#define JPEGLIB_USE_STDIO +#include "jpeglib/jpeglib.h" +#undef JPEGLIB_USE_STDIO + +#include "libpng/png.h" + +#include + +#include "bitmap/tgawriter.h" +#include "ivtex.h" +#ifdef WIN32 +#include +#endif +#ifdef OSX +#include +#endif + +#ifndef WIN32 +#define DeleteFile(s) remove(s) +#endif + +#if defined( _X360 ) +#include "xbox/xbox_win32stubs.h" +#endif + + + +// memdbgon must be the last include file in a .cpp file!!! +#include + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +struct ValveJpegErrorHandler_t +{ + // The default manager + struct jpeg_error_mgr m_Base; + // For handling any errors + jmp_buf m_ErrorContext; +}; + +#define JPEG_OUTPUT_BUF_SIZE 4096 + +struct JPEGDestinationManager_t +{ + struct jpeg_destination_mgr pub; // public fields + + CUtlBuffer *pBuffer; // target/final buffer + byte *buffer; // start of temp buffer +}; + + +//----------------------------------------------------------------------------- +// Purpose: We'll override the default error handler so we can deal with errors without having to exit the engine +//----------------------------------------------------------------------------- +static void ValveJpegErrorHandler( j_common_ptr cinfo ) +{ + ValveJpegErrorHandler_t *pError = reinterpret_cast< ValveJpegErrorHandler_t * >( cinfo->err ); + + char buffer[ JMSG_LENGTH_MAX ]; + + /* Create the message */ + ( *cinfo->err->format_message )( cinfo, buffer ); + + Warning( "%s\n", buffer ); + + // Bail + longjmp( pError->m_ErrorContext, 1 ); +} + + +// convert the JPEG file given to a TGA file at the given output path. +ConversionErrorType ImgUtl_ConvertJPEGToTGA( const char *jpegpath, const char *tgaPath, bool bRequirePowerOfTwo ) +{ +#if !defined( _X360 ) + + // + // !FIXME! This really probably should use ImgUtl_ReadJPEGAsRGBA, to avoid duplicated code. + // + + struct jpeg_decompress_struct jpegInfo; + struct ValveJpegErrorHandler_t jerr; + JSAMPROW row_pointer[1]; + int row_stride; + int cur_row = 0; + + // image attributes + int image_height; + int image_width; + + // open the jpeg image file. + FILE *infile = fopen(jpegpath, "rb"); + if (infile == NULL) + { + return CE_CANT_OPEN_SOURCE_FILE; + } + + // setup error to print to stderr. + jpegInfo.err = jpeg_std_error(&jerr.m_Base); + + jpegInfo.err->error_exit = &ValveJpegErrorHandler; + + // create the decompress struct. + jpeg_create_decompress(&jpegInfo); + + if ( setjmp( jerr.m_ErrorContext ) ) + { + // Get here if there is any error + jpeg_destroy_decompress( &jpegInfo ); + + fclose(infile); + + return CE_ERROR_PARSING_SOURCE; + } + + jpeg_stdio_src(&jpegInfo, infile); + + // read in the jpeg header and make sure that's all good. + if (jpeg_read_header(&jpegInfo, TRUE) != JPEG_HEADER_OK) + { + fclose(infile); + return CE_ERROR_PARSING_SOURCE; + } + + // start the decompress with the jpeg engine. + if ( !jpeg_start_decompress(&jpegInfo) ) + { + jpeg_destroy_decompress(&jpegInfo); + fclose(infile); + return CE_ERROR_PARSING_SOURCE; + } + + // Check for valid width and height (ie. power of 2 and print out an error and exit if not). + if ( ( bRequirePowerOfTwo && ( !IsPowerOfTwo(jpegInfo.image_height) || !IsPowerOfTwo(jpegInfo.image_width) ) ) + || jpegInfo.output_components != 3 ) + { + jpeg_destroy_decompress(&jpegInfo); + fclose( infile ); + return CE_SOURCE_FILE_SIZE_NOT_SUPPORTED; + } + + // now that we've started the decompress with the jpeg lib, we have the attributes of the + // image ready to be read out of the decompress struct. + row_stride = jpegInfo.output_width * jpegInfo.output_components; + image_height = jpegInfo.image_height; + image_width = jpegInfo.image_width; + int mem_required = jpegInfo.image_height * jpegInfo.image_width * jpegInfo.output_components; + + // allocate the memory to read the image data into. + unsigned char *buf = (unsigned char *)malloc(mem_required); + if (buf == NULL) + { + jpeg_destroy_decompress(&jpegInfo); + fclose(infile); + return CE_MEMORY_ERROR; + } + + // read in all the scan lines of the image into our image data buffer. + bool working = true; + while (working && (jpegInfo.output_scanline < jpegInfo.output_height)) + { + row_pointer[0] = &(buf[cur_row * row_stride]); + if ( !jpeg_read_scanlines(&jpegInfo, row_pointer, 1) ) + { + working = false; + } + ++cur_row; + } + + if (!working) + { + free(buf); + jpeg_destroy_decompress(&jpegInfo); + fclose(infile); + return CE_ERROR_PARSING_SOURCE; + } + + jpeg_finish_decompress(&jpegInfo); + + fclose(infile); + + // ok, at this point we have read in the JPEG image to our buffer, now we need to write it out as a TGA file. + CUtlBuffer outBuf; + bool bRetVal = TGAWriter::WriteToBuffer( buf, outBuf, image_width, image_height, IMAGE_FORMAT_RGB888, IMAGE_FORMAT_RGB888 ); + if ( bRetVal ) + { + if ( !g_pFullFileSystem->WriteFile( tgaPath, NULL, outBuf ) ) + { + bRetVal = false; + } + } + + free(buf); + return bRetVal ? CE_SUCCESS : CE_ERROR_WRITING_OUTPUT_FILE; + +#else + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; +#endif +} + +// convert the bmp file given to a TGA file at the given destination path. +ConversionErrorType ImgUtl_ConvertBMPToTGA(const char *bmpPath, const char *tgaPath) +{ + if ( !IsPC() ) + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + +#ifdef WIN32 + + int nWidth, nHeight; + ConversionErrorType result; + unsigned char *pBufRGBA = ImgUtl_ReadBMPAsRGBA( bmpPath, nWidth, nHeight, result ); + if ( result != CE_SUCCESS) + { + Assert( !pBufRGBA ); + free( pBufRGBA ); + return result; + } + Assert( pBufRGBA ); + + // write out the TGA file using the RGB data buffer. + CUtlBuffer outBuf; + bool retval = TGAWriter::WriteToBuffer(pBufRGBA, outBuf, nWidth, nHeight, IMAGE_FORMAT_RGBA8888, IMAGE_FORMAT_RGB888); + free( pBufRGBA ); + + if ( retval ) + { + if ( !g_pFullFileSystem->WriteFile( tgaPath, NULL, outBuf ) ) + { + retval = false; + } + } + + return retval ? CE_SUCCESS : CE_ERROR_WRITING_OUTPUT_FILE; + +#else // WIN32 + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; +#endif +} + +unsigned char *ImgUtl_ReadVTFAsRGBA( const char *vtfPath, int &width, int &height, ConversionErrorType &errcode ) +{ + // Just load the whole file into a memory buffer + CUtlBuffer bufFileContents; + if ( !g_pFullFileSystem->ReadFile( vtfPath, NULL, bufFileContents ) ) + { + errcode = CE_CANT_OPEN_SOURCE_FILE; + return NULL; + } + + IVTFTexture *pVTFTexture = CreateVTFTexture(); + if ( !pVTFTexture->Unserialize( bufFileContents ) ) + { + DestroyVTFTexture( pVTFTexture ); + errcode = CE_ERROR_PARSING_SOURCE; + return NULL; + } + + width = pVTFTexture->Width(); + height = pVTFTexture->Height(); + pVTFTexture->ConvertImageFormat( IMAGE_FORMAT_RGBA8888, false ); + + int nMemSize = ImageLoader::GetMemRequired( width, height, 1, IMAGE_FORMAT_RGBA8888, false ); + unsigned char *pMemImage = (unsigned char *)malloc(nMemSize); + if ( pMemImage == NULL ) + { + DestroyVTFTexture( pVTFTexture ); + errcode = CE_MEMORY_ERROR; + return NULL; + } + Q_memcpy( pMemImage, pVTFTexture->ImageData(), nMemSize ); + + DestroyVTFTexture( pVTFTexture ); + + errcode = CE_SUCCESS; + return pMemImage; +} + +// read a TGA header from the current point in the file stream. +static void ImgUtl_ReadTGAHeader(FILE *infile, TGAHeader &header) +{ + if (infile == NULL) + { + return; + } + + fread(&header.identsize, sizeof(header.identsize), 1, infile); + fread(&header.colourmaptype, sizeof(header.colourmaptype), 1, infile); + fread(&header.imagetype, sizeof(header.imagetype), 1, infile); + fread(&header.colourmapstart, sizeof(header.colourmapstart), 1, infile); + fread(&header.colourmaplength, sizeof(header.colourmaplength), 1, infile); + fread(&header.colourmapbits, sizeof(header.colourmapbits), 1, infile); + fread(&header.xstart, sizeof(header.xstart), 1, infile); + fread(&header.ystart, sizeof(header.ystart), 1, infile); + fread(&header.width, sizeof(header.width), 1, infile); + fread(&header.height, sizeof(header.height), 1, infile); + fread(&header.bits, sizeof(header.bits), 1, infile); + fread(&header.descriptor, sizeof(header.descriptor), 1, infile); +} + +// write a TGA header to the current point in the file stream. +static void WriteTGAHeader(FILE *outfile, TGAHeader &header) +{ + if (outfile == NULL) + { + return; + } + + fwrite(&header.identsize, sizeof(header.identsize), 1, outfile); + fwrite(&header.colourmaptype, sizeof(header.colourmaptype), 1, outfile); + fwrite(&header.imagetype, sizeof(header.imagetype), 1, outfile); + fwrite(&header.colourmapstart, sizeof(header.colourmapstart), 1, outfile); + fwrite(&header.colourmaplength, sizeof(header.colourmaplength), 1, outfile); + fwrite(&header.colourmapbits, sizeof(header.colourmapbits), 1, outfile); + fwrite(&header.xstart, sizeof(header.xstart), 1, outfile); + fwrite(&header.ystart, sizeof(header.ystart), 1, outfile); + fwrite(&header.width, sizeof(header.width), 1, outfile); + fwrite(&header.height, sizeof(header.height), 1, outfile); + fwrite(&header.bits, sizeof(header.bits), 1, outfile); + fwrite(&header.descriptor, sizeof(header.descriptor), 1, outfile); +} + +// reads in a TGA file and converts it to 32 bit RGBA color values in a memory buffer. +unsigned char * ImgUtl_ReadTGAAsRGBA(const char *tgaPath, int &width, int &height, ConversionErrorType &errcode, TGAHeader &tgaHeader ) +{ + FILE *tgaFile = fopen(tgaPath, "rb"); + if (tgaFile == NULL) + { + errcode = CE_CANT_OPEN_SOURCE_FILE; + return NULL; + } + + // read header for TGA file. + ImgUtl_ReadTGAHeader(tgaFile, tgaHeader); + + if ( + ( tgaHeader.imagetype != 2 ) // image type 2 is uncompressed RGB, other types not supported. + || ( tgaHeader.descriptor & 0x10 ) // Origin on righthand side (flipped horizontally from common sense) --- nobody ever uses this + || ( tgaHeader.bits != 24 && tgaHeader.bits != 32 ) // Must be 24- ot 32-bit + ) + { + fclose(tgaFile); + + errcode = CE_SOURCE_FILE_TGA_FORMAT_NOT_SUPPORTED; + return NULL; + } + + int tgaDataSize = tgaHeader.width * tgaHeader.height * tgaHeader.bits / 8; + unsigned char *tgaData = (unsigned char *)malloc(tgaDataSize); + if (tgaData == NULL) + { + fclose(tgaFile); + + errcode = CE_MEMORY_ERROR; + return NULL; + } + + fread(tgaData, 1, tgaDataSize, tgaFile); + + fclose(tgaFile); + + width = tgaHeader.width; + height = tgaHeader.height; + int numPixels = tgaHeader.width * tgaHeader.height; + + if (tgaHeader.bits == 24) + { + // image needs to be converted to a 32-bit image. + + unsigned char *retBuf = (unsigned char *)malloc(numPixels * 4); + if (retBuf == NULL) + { + free(tgaData); + + errcode = CE_MEMORY_ERROR; + return NULL; + } + + // convert from BGR to RGBA color format. + for (int index = 0; index < numPixels; ++index) + { + retBuf[index * 4] = tgaData[index * 3 + 2]; + retBuf[index * 4 + 1] = tgaData[index * 3 + 1]; + retBuf[index * 4 + 2] = tgaData[index * 3]; + retBuf[index * 4 + 3] = 0xff; + } + + free(tgaData); + tgaData = retBuf; + tgaHeader.bits = 32; + } + else if (tgaHeader.bits == 32) + { + // Swap blue and red to convert BGR -> RGB + for (int index = 0; index < numPixels; ++index) + { + V_swap( tgaData[index*4], tgaData[index*4 + 2] ); + } + } + + // Flip image vertically if necessary + if ( !( tgaHeader.descriptor & 0x20 ) ) + { + int y0 = 0; + int y1 = height-1; + int iStride = width*4; + while ( y0 < y1 ) + { + unsigned char *ptr0 = tgaData + y0*iStride; + unsigned char *ptr1 = tgaData + y1*iStride; + for ( int i = 0 ; i < iStride ; ++i ) + { + V_swap( ptr0[i], ptr1[i] ); + } + ++y0; + --y1; + } + tgaHeader.descriptor |= 0x20; + } + + errcode = CE_SUCCESS; + return tgaData; +} + +unsigned char *ImgUtl_ReadJPEGAsRGBA( const char *jpegPath, int &width, int &height, ConversionErrorType &errcode ) +{ +#if !defined( _X360 ) + struct jpeg_decompress_struct jpegInfo; + struct ValveJpegErrorHandler_t jerr; + JSAMPROW row_pointer[1]; + int row_stride; + int cur_row = 0; + + // image attributes + int image_height; + int image_width; + + // open the jpeg image file. + FILE *infile = fopen(jpegPath, "rb"); + if (infile == NULL) + { + errcode = CE_CANT_OPEN_SOURCE_FILE; + return NULL; + } + + //CJpegSourceMgr src; + //FileHandle_t fileHandle = g_pFullFileSystem->Open( jpegPath, "rb" ); + //if ( fileHandle == FILESYSTEM_INVALID_HANDLE ) + //{ + // errcode = CE_CANT_OPEN_SOURCE_FILE; + // return NULL; + //} + //if ( !src.Init( g_pFullFileSystem, fileHandle ) ) { + // errcode = CE_CANT_OPEN_SOURCE_FILE; + // g_pFullFileSystem->Close( fileHandle ); + // return NULL; + //} + + // setup error to print to stderr. + memset( &jpegInfo, 0, sizeof( jpegInfo ) ); + jpegInfo.err = jpeg_std_error(&jerr.m_Base); + + jpegInfo.err->error_exit = &ValveJpegErrorHandler; + + // create the decompress struct. + jpeg_create_decompress(&jpegInfo); + + if ( setjmp( jerr.m_ErrorContext ) ) + { + // Get here if there is any error + jpeg_destroy_decompress( &jpegInfo ); + + fclose( infile ); + //g_pFullFileSystem->Close( fileHandle ); + + errcode = CE_ERROR_PARSING_SOURCE; + return NULL; + } + + jpeg_stdio_src(&jpegInfo, infile); + //jpegInfo.src = &src; + + // read in the jpeg header and make sure that's all good. + if (jpeg_read_header(&jpegInfo, TRUE) != JPEG_HEADER_OK) + { + fclose( infile ); + //g_pFullFileSystem->Close( fileHandle ); + errcode = CE_ERROR_PARSING_SOURCE; + return NULL; + } + + // start the decompress with the jpeg engine. + if ( !jpeg_start_decompress(&jpegInfo) ) + { + jpeg_destroy_decompress(&jpegInfo); + fclose( infile ); + //g_pFullFileSystem->Close( fileHandle ); + errcode = CE_ERROR_PARSING_SOURCE; + return NULL; + } + + // We only support 24-bit JPEG's + if ( jpegInfo.out_color_space != JCS_RGB || jpegInfo.output_components != 3 ) + { + jpeg_destroy_decompress(&jpegInfo); + fclose( infile ); + //g_pFullFileSystem->Close( fileHandle ); + errcode = CE_SOURCE_FILE_SIZE_NOT_SUPPORTED; + return NULL; + } + + // now that we've started the decompress with the jpeg lib, we have the attributes of the + // image ready to be read out of the decompress struct. + row_stride = jpegInfo.output_width * 4; + image_height = jpegInfo.image_height; + image_width = jpegInfo.image_width; + int mem_required = jpegInfo.image_height * row_stride; + + // allocate the memory to read the image data into. + unsigned char *buf = (unsigned char *)malloc(mem_required); + if (buf == NULL) + { + jpeg_destroy_decompress(&jpegInfo); + fclose( infile ); + //g_pFullFileSystem->Close( fileHandle ); + errcode = CE_MEMORY_ERROR; + return NULL; + } + + // read in all the scan lines of the image into our image data buffer. + bool working = true; + while (working && (jpegInfo.output_scanline < jpegInfo.output_height)) + { + unsigned char *pRow = &(buf[cur_row * row_stride]); + row_pointer[0] = pRow; + if ( !jpeg_read_scanlines(&jpegInfo, row_pointer, 1) ) + { + working = false; + } + + // Expand the row RGB -> RGBA + for ( int x = image_width-1 ; x >= 0 ; --x ) + { + pRow[x*4+3] = 0xff; + pRow[x*4+2] = pRow[x*3+2]; + pRow[x*4+1] = pRow[x*3+1]; + pRow[x*4] = pRow[x*3]; + } + + ++cur_row; + } + + // Clean up + fclose( infile ); + //g_pFullFileSystem->Close( fileHandle ); + jpeg_destroy_decompress(&jpegInfo); + + // Check success status + if (!working) + { + free(buf); + errcode = CE_ERROR_PARSING_SOURCE; + return NULL; + } + + // OK! + width = image_width; + height = image_height; + errcode = CE_SUCCESS; + return buf; + +#else + errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + return NULL; +#endif +} + +static void ReadPNGData( png_structp png_ptr, png_bytep outBytes, png_size_t byteCountToRead ) +{ + + // Cast pointer + CUtlBuffer *pBuf = (CUtlBuffer *)png_get_io_ptr( png_ptr ); + Assert( pBuf ); + + // Check for IO error + if ( pBuf->TellGet() + (int)byteCountToRead > pBuf->TellPut() ) + { + // Attempt to read past the end of the buffer. + // Use longjmp to report the error + png_longjmp( png_ptr, 1 ); + } + + // Read the bytes + pBuf->Get( outBytes, byteCountToRead ); +} + + +unsigned char *ImgUtl_ReadPNGAsRGBA( const char *pngPath, int &width, int &height, ConversionErrorType &errcode ) +{ +#if !defined( _X360 ) + + // Just load the whole file into a memory buffer + CUtlBuffer bufFileContents; + if ( !g_pFullFileSystem->ReadFile( pngPath, NULL, bufFileContents ) ) + { + errcode = CE_CANT_OPEN_SOURCE_FILE; + return NULL; + } + + // Load it + return ImgUtl_ReadPNGAsRGBAFromBuffer( bufFileContents, width, height, errcode ); + +#else + errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + return NULL; +#endif +} + +unsigned char *ImgUtl_ReadPNGAsRGBAFromBuffer( CUtlBuffer &buffer, int &width, int &height, ConversionErrorType &errcode ) +{ +#if !defined( _X360 ) + + png_const_bytep pngData = (png_const_bytep)buffer.Base(); + if (png_sig_cmp( pngData, 0, 8)) + { + errcode = CE_ERROR_PARSING_SOURCE; + return NULL; + } + + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + + /* could pass pointers to user-defined error handlers instead of NULLs: */ + + png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); + if (!png_ptr) + { + errcode = CE_MEMORY_ERROR; + return NULL; + } + + unsigned char *pResultData = NULL; + png_bytepp row_pointers = NULL; + + info_ptr = png_create_info_struct( png_ptr ); + if ( !info_ptr ) + { + errcode = CE_MEMORY_ERROR; +fail: + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + if ( row_pointers ) + { + free( row_pointers ); + } + if ( pResultData ) + { + free( pResultData ); + } + return NULL; + } + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function */ + + if ( setjmp( png_jmpbuf(png_ptr) ) ) + { + errcode = CE_ERROR_PARSING_SOURCE; + goto fail; + } + + png_set_read_fn( png_ptr, &buffer, ReadPNGData ); + png_read_info( png_ptr, info_ptr ); /* read all PNG info up to image data */ + + + /* alternatively, could make separate calls to png_get_image_width(), + * etc., but want bit_depth and color_type for later [don't care about + * compression_type and filter_type => NULLs] */ + + int bit_depth; + int color_type; + uint32 png_width; + uint32 png_height; + + png_get_IHDR( png_ptr, info_ptr, &png_width, &png_height, &bit_depth, &color_type, NULL, NULL, NULL ); + + width = png_width; + height = png_height; + + png_uint_32 rowbytes; + + /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, + * transparency chunks to full alpha channel; strip 16-bit-per-sample + * images to 8 bits per sample; and convert grayscale to RGB[A] */ + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand( png_ptr ); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand( png_ptr ); + if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) + png_set_expand( png_ptr ); + if (bit_depth == 16) + png_set_strip_16( png_ptr ); + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb( png_ptr ); + + // Force in an alpha channel + if ( !( color_type & PNG_COLOR_MASK_ALPHA ) ) + { + png_set_add_alpha(png_ptr, 255, PNG_FILLER_AFTER); + } + + /* + double gamma; + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, display_exponent, gamma); + +*/ + /* all transformations have been registered; now update info_ptr data, + * get rowbytes and channels, and allocate image memory */ + + png_read_update_info( png_ptr, info_ptr ); + + rowbytes = png_get_rowbytes( png_ptr, info_ptr ); + png_byte channels = (int)png_get_channels( png_ptr, info_ptr ); + if ( channels != 4 ) + { + Assert( channels == 4 ); + errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + goto fail; + } + + row_pointers = (png_bytepp)malloc( height*sizeof(png_bytep) ); + pResultData = (unsigned char *)malloc( rowbytes*height ); + + if ( row_pointers == NULL || pResultData == NULL ) + { + errcode = CE_MEMORY_ERROR; + goto fail; + } + + /* set the individual row_pointers to point at the correct offsets */ + + for ( int i = 0; i < height; ++i) + row_pointers[i] = pResultData + i*rowbytes; + + /* now we can go ahead and just read the whole image */ + + png_read_image( png_ptr, row_pointers ); + + png_read_end(png_ptr, NULL); + + free( row_pointers ); + row_pointers = NULL; + + // Clean up + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + + // OK! + width = png_width; + height = png_height; + errcode = CE_SUCCESS; + return pResultData; + +#else + errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + return NULL; +#endif +} + +unsigned char *ImgUtl_ReadBMPAsRGBA( const char *bmpPath, int &width, int &height, ConversionErrorType &errcode ) +{ +#ifdef WIN32 + // Load up bitmap + HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, bmpPath, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE | LR_DEFAULTSIZE); + + // Handle failure + if ( hBitmap == NULL) + { + + // !KLUDGE! Try to detect what went wrong + FILE *fp = fopen( bmpPath, "rb" ); + if (fp == NULL) + { + errcode = CE_CANT_OPEN_SOURCE_FILE; + } + else + { + errcode = CE_ERROR_PARSING_SOURCE; + } + return NULL; + } + + BITMAP bitmap; + + GetObject(hBitmap, sizeof(bitmap), &bitmap); + + BITMAPINFO *bitmapInfo; + + bool bUseColorTable = false; + if (bitmap.bmBitsPixel == 24 || bitmap.bmBitsPixel == 32) + { + bitmapInfo = (BITMAPINFO *)malloc(sizeof(BITMAPINFO)); + } + else if (bitmap.bmBitsPixel == 8 || bitmap.bmBitsPixel == 4 || bitmap.bmBitsPixel == 1) + { + int colorsUsed = 1 << bitmap.bmBitsPixel; + bitmapInfo = (BITMAPINFO *)malloc(colorsUsed * sizeof(RGBQUAD) + sizeof(BITMAPINFO)); + bUseColorTable = true; + } + else + { + DeleteObject(hBitmap); + errcode = CE_SOURCE_FILE_BMP_FORMAT_NOT_SUPPORTED; + return NULL; + } + + memset(bitmapInfo, 0, sizeof(BITMAPINFO)); + bitmapInfo->bmiHeader.biSize = sizeof(bitmapInfo->bmiHeader); + if (bUseColorTable) + { + bitmapInfo->bmiHeader.biBitCount = bitmap.bmBitsPixel; // need to specify the bits per pixel so GDI will generate a color table for us. + } + + HDC dc = CreateCompatibleDC(NULL); + + int retcode = GetDIBits(dc, hBitmap, 0, bitmap.bmHeight, NULL, bitmapInfo, DIB_RGB_COLORS); + + DeleteDC(dc); + + if (retcode == 0) + { + // error getting the bitmap info for some reason. + free(bitmapInfo); + errcode = CE_SOURCE_FILE_BMP_FORMAT_NOT_SUPPORTED; + return NULL; + } + + int nDestStride = 4 * bitmap.bmWidth; + int mem_required = nDestStride * bitmap.bmHeight; // mem required for copying the data out into RGBA format. + + unsigned char *buf = (unsigned char *)malloc(mem_required); + if (buf == NULL) + { + free(bitmapInfo); + errcode = CE_MEMORY_ERROR; + return NULL; + } + + if (bitmapInfo->bmiHeader.biBitCount == 32) + { + for (int y = 0; y < bitmap.bmHeight; ++y) + { + unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down + const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes); + + for (int x = 0; x < bitmap.bmWidth; ++x) + { + + // Swap BGR -> RGB while copying data + pDest[0] = pSrc[2]; // R + pDest[1] = pSrc[1]; // G + pDest[2] = pSrc[0]; // B + pDest[3] = pSrc[3]; // A + + pSrc += 4; + pDest += 4; + } + } + } + else if (bitmapInfo->bmiHeader.biBitCount == 24) + { + for (int y = 0; y < bitmap.bmHeight; ++y) + { + unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down + const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes); + + for (int x = 0; x < bitmap.bmWidth; ++x) + { + + // Swap BGR -> RGB while copying data + pDest[0] = pSrc[2]; // R + pDest[1] = pSrc[1]; // G + pDest[2] = pSrc[0]; // B + pDest[3] = 0xff; // A + + pSrc += 3; + pDest += 4; + } + } + } + else if (bitmapInfo->bmiHeader.biBitCount == 8) + { + // 8-bit 256 color bitmap. + for (int y = 0; y < bitmap.bmHeight; ++y) + { + unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down + const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes); + + for (int x = 0; x < bitmap.bmWidth; ++x) + { + + // compute the color map entry for this pixel + int colorTableEntry = *pSrc; + + // get the color for this color map entry. + RGBQUAD *rgbQuad = &(bitmapInfo->bmiColors[colorTableEntry]); + + // copy the color values for this pixel to the destination buffer. + pDest[0] = rgbQuad->rgbRed; + pDest[1] = rgbQuad->rgbGreen; + pDest[2] = rgbQuad->rgbBlue; + pDest[3] = 0xff; + + ++pSrc; + pDest += 4; + } + } + } + else if (bitmapInfo->bmiHeader.biBitCount == 4) + { + // 4-bit 16 color bitmap. + for (int y = 0; y < bitmap.bmHeight; ++y) + { + unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down + const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes); + + // Two pixels at a time + for (int x = 0; x < bitmap.bmWidth; x += 2) + { + + // get the color table entry for this pixel + int colorTableEntry = (0xf0 & *pSrc) >> 4; + + // get the color values for this pixel's color table entry. + RGBQUAD *rgbQuad = &(bitmapInfo->bmiColors[colorTableEntry]); + + // copy the pixel's color values to the destination buffer. + pDest[0] = pSrc[2]; // R + pDest[1] = pSrc[1]; // G + pDest[2] = pSrc[0]; // B + pDest[3] = 0xff; // A + + // make sure we haven't reached the end of the row. + if ((x + 1) > bitmap.bmWidth) + { + break; + } + + pDest += 4; + + // get the color table entry for this pixel. + colorTableEntry = 0x0f & *pSrc; + + // get the color values for this pixel's color table entry. + rgbQuad = &(bitmapInfo->bmiColors[colorTableEntry]); + + // copy the pixel's color values to the destination buffer. + pDest[0] = pSrc[2]; // R + pDest[1] = pSrc[1]; // G + pDest[2] = pSrc[0]; // B + pDest[3] = 0xff; // A + + ++pSrc; + pDest += 4; + } + } + } + else if (bitmapInfo->bmiHeader.biBitCount == 1) + { + // 1-bit monochrome bitmap. + for (int y = 0; y < bitmap.bmHeight; ++y) + { + unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down + const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes); + + // Eight pixels at a time + int x = 0; + while (x < bitmap.bmWidth) + { + + RGBQUAD *rgbQuad = NULL; + int bitMask = 0x80; + + // go through all 8 bits in this byte to get all 8 pixel colors. + do + { + // get the value of the bit for this pixel. + int bit = *pSrc & bitMask; + + // bit will either be 0 or non-zero since there are only two colors. + if (bit == 0) + { + rgbQuad = &(bitmapInfo->bmiColors[0]); + } + else + { + rgbQuad = &(bitmapInfo->bmiColors[1]); + } + + // copy this pixel's color values into the destination buffer. + pDest[0] = pSrc[2]; // R + pDest[1] = pSrc[1]; // G + pDest[2] = pSrc[0]; // B + pDest[3] = 0xff; // A + pDest += 4; + + // go to the next pixel. + ++x; + bitMask = bitMask >> 1; + } while ((x < bitmap.bmWidth) && (bitMask > 0)); + + ++pSrc; + } + } + } + else + { + free(bitmapInfo); + free(buf); + DeleteObject(hBitmap); + errcode = CE_SOURCE_FILE_BMP_FORMAT_NOT_SUPPORTED; + return NULL; + } + + free(bitmapInfo); + DeleteObject(hBitmap); + + // OK! + width = bitmap.bmWidth; + height = bitmap.bmHeight; + errcode = CE_SUCCESS; + return buf; +#else + errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + return NULL; +#endif +} + +unsigned char *ImgUtl_ReadImageAsRGBA( const char *path, int &width, int &height, ConversionErrorType &errcode ) +{ + + // Split out the file extension + const char *pExt = V_GetFileExtension( path ); + if ( pExt ) + { + if ( !Q_stricmp(pExt, "vtf") ) + { + return ImgUtl_ReadVTFAsRGBA( path, width, height, errcode ); + } + if ( !Q_stricmp(pExt, "bmp") ) + { + return ImgUtl_ReadBMPAsRGBA( path, width, height, errcode ); + } + if ( !Q_stricmp(pExt, "jpg") || !Q_stricmp(pExt, "jpeg") ) + { + return ImgUtl_ReadJPEGAsRGBA( path, width, height, errcode ); + } + if ( !Q_stricmp(pExt, "png") ) + { + return ImgUtl_ReadPNGAsRGBA( path, width, height, errcode ); + } + if ( !Q_stricmp(pExt, "tga") ) + { + TGAHeader header; + return ImgUtl_ReadTGAAsRGBA( path, width, height, errcode, header ); + } + } + + errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + return NULL; +} + +// resizes the file specified by tgaPath so that it has dimensions that are +// powers-of-two and is equal to or smaller than (nMaxWidth)x(nMaxHeight). +// also converts from 24-bit RGB to 32-bit RGB (with 8-bit alpha) +ConversionErrorType ImgUtl_ConvertTGA(const char *tgaPath, int nMaxWidth/*=-1*/, int nMaxHeight/*=-1*/) +{ + int tgaWidth = 0, tgaHeight = 0; + ConversionErrorType errcode; + TGAHeader tgaHeader; + unsigned char *srcBuffer = ImgUtl_ReadTGAAsRGBA(tgaPath, tgaWidth, tgaHeight, errcode, tgaHeader); + + if (srcBuffer == NULL) + { + return errcode; + } + + int paddedImageWidth, paddedImageHeight; + + if ((tgaWidth <= 0) || (tgaHeight <= 0)) + { + free(srcBuffer); + return CE_ERROR_PARSING_SOURCE; + } + + // get the nearest power of two that is greater than the width of the image. + paddedImageWidth = tgaWidth; + if (!IsPowerOfTwo(paddedImageWidth)) + { + // width is not a power of two, calculate the next highest power of two value. + int i = 1; + while (paddedImageWidth > 1) + { + paddedImageWidth = paddedImageWidth >> 1; + ++i; + } + + paddedImageWidth = paddedImageWidth << i; + } + + // make sure the width is less than or equal to nMaxWidth + if (nMaxWidth != -1 && paddedImageWidth > nMaxWidth) + { + paddedImageWidth = nMaxWidth; + } + + // get the nearest power of two that is greater than the height of the image + paddedImageHeight = tgaHeight; + if (!IsPowerOfTwo(paddedImageHeight)) + { + // height is not a power of two, calculate the next highest power of two value. + int i = 1; + while (paddedImageHeight > 1) + { + paddedImageHeight = paddedImageHeight >> 1; + ++i; + } + + paddedImageHeight = paddedImageHeight << i; + } + + // make sure the height is less than or equal to nMaxHeight + if (nMaxHeight != -1 && paddedImageHeight > nMaxHeight) + { + paddedImageHeight = nMaxHeight; + } + + // compute the amount of stretching that needs to be done to both width and height to get the image to fit. + float widthRatio = (float)paddedImageWidth / tgaWidth; + float heightRatio = (float)paddedImageHeight / tgaHeight; + + int finalWidth; + int finalHeight; + + // compute the final dimensions of the stretched image. + if (widthRatio < heightRatio) + { + finalWidth = paddedImageWidth; + finalHeight = (int)(tgaHeight * widthRatio + 0.5f); + // i.e. for 1x1 size pixels in the resized image we will take color from sourceRatio x sourceRatio sized pixels in the source image. + } + else if (heightRatio < widthRatio) + { + finalHeight = paddedImageHeight; + finalWidth = (int)(tgaWidth * heightRatio + 0.5f); + } + else + { + finalHeight = paddedImageHeight; + finalWidth = paddedImageWidth; + } + + unsigned char *resizeBuffer = (unsigned char *)malloc(finalWidth * finalHeight * 4); + + // do the actual stretching + ImgUtl_StretchRGBAImage(srcBuffer, tgaWidth, tgaHeight, resizeBuffer, finalWidth, finalHeight); + + free(srcBuffer); // don't need this anymore. + + /////////////////////////////////////////////////////////////////////// + ///// need to pad the image so both dimensions are power of two's ///// + /////////////////////////////////////////////////////////////////////// + unsigned char *finalBuffer = (unsigned char *)malloc(paddedImageWidth * paddedImageHeight * 4); + ImgUtl_PadRGBAImage(resizeBuffer, finalWidth, finalHeight, finalBuffer, paddedImageWidth, paddedImageHeight); + + FILE *outfile = fopen(tgaPath, "wb"); + if (outfile == NULL) + { + free(resizeBuffer); + free(finalBuffer); + + return CE_ERROR_WRITING_OUTPUT_FILE; + } + + tgaHeader.width = paddedImageWidth; + tgaHeader.height = paddedImageHeight; + + WriteTGAHeader(outfile, tgaHeader); + + // Write the image data --- remember that TGA uses BGRA data + int numPixels = paddedImageWidth * paddedImageHeight; + for (int i = 0 ; i < numPixels ; ++i ) + { + fputc( finalBuffer[i*4 + 2], outfile ); // B + fputc( finalBuffer[i*4 + 1], outfile ); // G + fputc( finalBuffer[i*4 ], outfile ); // R + fputc( finalBuffer[i*4 + 3], outfile ); // A + } + + fclose(outfile); + + free(resizeBuffer); + free(finalBuffer); + + return CE_SUCCESS; +} + +// resize by stretching (or compressing) an RGBA image pointed to by srcBuf into the buffer pointed to by destBuf. +// the buffers are assumed to be sized appropriately to accomidate RGBA images of the given widths and heights. +ConversionErrorType ImgUtl_StretchRGBAImage(const unsigned char *srcBuf, const int srcWidth, const int srcHeight, + unsigned char *destBuf, const int destWidth, const int destHeight) +{ + if ((srcBuf == NULL) || (destBuf == NULL)) + { + return CE_CANT_OPEN_SOURCE_FILE; + } + + int destRow,destColumn; + + float ratioX = (float)srcWidth / (float)destWidth; + float ratioY = (float)srcHeight / (float)destHeight; + + // loop through all the pixels in the destination image. + for (destRow = 0; destRow < destHeight; ++destRow) + { + for (destColumn = 0; destColumn < destWidth; ++destColumn) + { + // calculate the center of the pixel in the source image. + float srcCenterX = ratioX * (destColumn + 0.5f); + float srcCenterY = ratioY * (destRow + 0.5f); + + // calculate the starting and ending coords for this destination pixel in the source image. + float srcStartX = srcCenterX - (ratioX / 2.0f); + if (srcStartX < 0.0f) + { + srcStartX = 0.0f; // this should never happen, but just in case. + } + + float srcStartY = srcCenterY - (ratioY / 2.0f); + if (srcStartY < 0.0f) + { + srcStartY = 0.0f; // this should never happen, but just in case. + } + + float srcEndX = srcCenterX + (ratioX / 2.0f); + if (srcEndX > srcWidth) + { + srcEndX = srcWidth; // this should never happen, but just in case. + } + + float srcEndY = srcCenterY + (ratioY / 2.0f); + if (srcEndY > srcHeight) + { + srcEndY = srcHeight; // this should never happen, but just in case. + } + + // Calculate the percentage of each source pixels' contribution to the destination pixel color. + + float srcCurrentX; // initialized at the start of the y loop. + float srcCurrentY = srcStartY; + + float destRed = 0.0f; + float destGreen = 0.0f; + float destBlue = 0.0f; + float destAlpha = 0.0f; + + //// loop for the parts of the source image that will contribute color to the destination pixel. + while (srcCurrentY < srcEndY) + { + float srcCurrentEndY = (float)((int)srcCurrentY + 1); + if (srcCurrentEndY > srcEndY) + { + srcCurrentEndY = srcEndY; + } + + float srcCurrentHeight = srcCurrentEndY - srcCurrentY; + + srcCurrentX = srcStartX; + + while (srcCurrentX < srcEndX) + { + float srcCurrentEndX = (float)((int)srcCurrentX + 1); + if (srcCurrentEndX > srcEndX) + { + srcCurrentEndX = srcEndX; + } + float srcCurrentWidth = srcCurrentEndX - srcCurrentX; + + // compute the percentage of the destination pixel's color this source pixel will contribute. + float srcColorPercentage = (srcCurrentWidth / ratioX) * (srcCurrentHeight / ratioY); + + int srcCurrentPixelX = (int)srcCurrentX; + int srcCurrentPixelY = (int)srcCurrentY; + + // get the color values for this source pixel. + unsigned char srcCurrentRed = srcBuf[(srcCurrentPixelY * srcWidth * 4) + (srcCurrentPixelX * 4)]; + unsigned char srcCurrentGreen = srcBuf[(srcCurrentPixelY * srcWidth * 4) + (srcCurrentPixelX * 4) + 1]; + unsigned char srcCurrentBlue = srcBuf[(srcCurrentPixelY * srcWidth * 4) + (srcCurrentPixelX * 4) + 2]; + unsigned char srcCurrentAlpha = srcBuf[(srcCurrentPixelY * srcWidth * 4) + (srcCurrentPixelX * 4) + 3]; + + // add the color contribution from this source pixel to the destination pixel. + destRed += srcCurrentRed * srcColorPercentage; + destGreen += srcCurrentGreen * srcColorPercentage; + destBlue += srcCurrentBlue * srcColorPercentage; + destAlpha += srcCurrentAlpha * srcColorPercentage; + + srcCurrentX = srcCurrentEndX; + } + + srcCurrentY = srcCurrentEndY; + } + + // assign the computed color to the destination pixel, round to the nearest value. Make sure the value doesn't exceed 255. + destBuf[(destRow * destWidth * 4) + (destColumn * 4)] = min((int)(destRed + 0.5f), 255); + destBuf[(destRow * destWidth * 4) + (destColumn * 4) + 1] = min((int)(destGreen + 0.5f), 255); + destBuf[(destRow * destWidth * 4) + (destColumn * 4) + 2] = min((int)(destBlue + 0.5f), 255); + destBuf[(destRow * destWidth * 4) + (destColumn * 4) + 3] = min((int)(destAlpha + 0.5f), 255); + } // column loop + } // row loop + + return CE_SUCCESS; +} + +ConversionErrorType ImgUtl_PadRGBAImage(const unsigned char *srcBuf, const int srcWidth, const int srcHeight, + unsigned char *destBuf, const int destWidth, const int destHeight) +{ + if ((srcBuf == NULL) || (destBuf == NULL)) + { + return CE_CANT_OPEN_SOURCE_FILE; + } + + memset(destBuf, 0, destWidth * destHeight * 4); + + if ((destWidth < srcWidth) || (destHeight < srcHeight)) + { + return CE_ERROR_PARSING_SOURCE; + } + + if ((srcWidth == destWidth) && (srcHeight == destHeight)) + { + // no padding is needed, just copy the buffer straight over and call it done. + memcpy(destBuf, srcBuf, destWidth * destHeight * 4); + return CE_SUCCESS; + } + + if (destWidth == srcWidth) + { + // only the top and bottom of the image need padding. + // do this separately since we can do this more efficiently than the other cases. + int numRowsToPad = (destHeight - srcHeight) / 2; + memcpy(destBuf + (numRowsToPad * destWidth * 4), srcBuf, srcWidth * srcHeight * 4); + } + else + { + int numColumnsToPad = (destWidth - srcWidth) / 2; + int numRowsToPad = (destHeight - srcHeight) / 2; + int lastRow = numRowsToPad + srcHeight; + int row; + for (row = numRowsToPad; row < lastRow; ++row) + { + unsigned char * destOffset = destBuf + (row * destWidth * 4) + (numColumnsToPad * 4); + const unsigned char * srcOffset = srcBuf + ((row - numRowsToPad) * srcWidth * 4); + memcpy(destOffset, srcOffset, srcWidth * 4); + } + } + + return CE_SUCCESS; +} + +// convert TGA file at the given location to a VTF file of the same root name at the same location. +ConversionErrorType ImgUtl_ConvertTGAToVTF(const char *tgaPath, int nMaxWidth/*=-1*/, int nMaxHeight/*=-1*/ ) +{ + FILE *infile = fopen(tgaPath, "rb"); + if (infile == NULL) + { + Msg( "Failed to open TGA: %s\n", tgaPath); + return CE_CANT_OPEN_SOURCE_FILE; + } + + // read out the header of the image. + TGAHeader header; + ImgUtl_ReadTGAHeader(infile, header); + + // check to make sure that the TGA has the proper dimensions and size. + if (!IsPowerOfTwo(header.width) || !IsPowerOfTwo(header.height)) + { + fclose(infile); + Msg( "Failed to open TGA - size dimensions (%d, %d) not power of 2: %s\n", header.width, header.height, tgaPath); + return CE_SOURCE_FILE_SIZE_NOT_SUPPORTED; + } + + // check to make sure that the TGA isn't too big, if we care. + if ( ( nMaxWidth != -1 && header.width > nMaxWidth ) || ( nMaxHeight != -1 && header.height > nMaxHeight ) ) + { + fclose(infile); + Msg( "Failed to open TGA - dimensions too large (%d, %d) (max: %d, %d): %s\n", header.width, header.height, nMaxWidth, nMaxHeight, tgaPath); + return CE_SOURCE_FILE_SIZE_NOT_SUPPORTED; + } + + int imageMemoryFootprint = header.width * header.height * header.bits / 8; + + CUtlBuffer inbuf(0, imageMemoryFootprint); + + // read in the image + int nBytesRead = fread(inbuf.Base(), imageMemoryFootprint, 1, infile); + + fclose(infile); + inbuf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead ); + + // load vtex_dll.dll and get the interface to it. + CSysModule *vtexmod = Sys_LoadModule("vtex_dll"); + if (vtexmod == NULL) + { + Msg( "Failed to open TGA conversion module vtex_dll: %s\n", tgaPath); + return CE_ERROR_LOADING_DLL; + } + + CreateInterfaceFn factory = Sys_GetFactory(vtexmod); + if (factory == NULL) + { + Sys_UnloadModule(vtexmod); + Msg( "Failed to open TGA conversion module vtex_dll Factory: %s\n", tgaPath); + return CE_ERROR_LOADING_DLL; + } + + IVTex *vtex = (IVTex *)factory(IVTEX_VERSION_STRING, NULL); + if (vtex == NULL) + { + Sys_UnloadModule(vtexmod); + Msg( "Failed to open TGA conversion module vtex_dll Factory (is null): %s\n", tgaPath); + return CE_ERROR_LOADING_DLL; + } + + char *vtfParams[4]; + + // the 0th entry is skipped cause normally thats the program name. + vtfParams[0] = ""; + vtfParams[1] = "-quiet"; + vtfParams[2] = "-dontusegamedir"; + vtfParams[3] = (char *)tgaPath; + + // call vtex to do the conversion. + vtex->VTex(4, vtfParams); // how do we know this works? + + Sys_UnloadModule(vtexmod); + + return CE_SUCCESS; +} + +static void DoCopyFile( const char *source, const char *destination ) +{ +#if defined( WIN32 ) + CopyFile( source, destination, true ); +#elif defined( OSX ) + copyfile( source, destination, NULL, COPYFILE_ALL ); +#elif defined( ENGINE_DLL ) + ::COM_CopyFile( source, destination ); +#elif REPLAY_DLL + g_pEngine->CopyFile( source, destination ); +#else + engine->CopyLocalFile( source, destination ); +#endif +} + +static void DoDeleteFile( const char *filename ) +{ +#ifdef WIN32 + DeleteFile( filename ); +#else + unlink( filename ); +#endif +} + +ConversionErrorType ImgUtl_ConvertToVTFAndDumpVMT( const char *pInPath, const char *pMaterialsSubDir, int nMaxWidth/*=-1*/, int nMaxHeight/*=-1*/ ) +{ +#ifndef _XBOX + if ((pInPath == NULL) || (pInPath[0] == 0)) + { + return CE_ERROR_PARSING_SOURCE; + } + + ConversionErrorType nErrorCode = CE_SUCCESS; + + // get the extension of the file we're to convert + char extension[MAX_PATH]; + const char *constchar = pInPath + strlen(pInPath); + while ((constchar > pInPath) && (*(constchar-1) != '.')) + { + --constchar; + } + Q_strncpy(extension, constchar, MAX_PATH); + + bool deleteIntermediateTGA = false; + bool deleteIntermediateVTF = false; + bool convertTGAToVTF = true; + char tgaPath[MAX_PATH*2]; + char *c; + bool failed = false; + + Q_strncpy(tgaPath, pInPath, sizeof(tgaPath)); + + // Construct a TGA version if necessary + if (stricmp(extension, "tga")) + { + // It is not a TGA file, so create a temporary file name for the TGA you have to create + + c = tgaPath + strlen(tgaPath); + while ((c > tgaPath) && (*(c-1) != '\\') && (*(c-1) != '/')) + { + --c; + } + *c = 0; + + char origpath[MAX_PATH*2]; + Q_strncpy(origpath, tgaPath, sizeof(origpath)); + + // Look for an empty temp file - find the first one that doesn't exist. + int index = 0; + do { + Q_snprintf(tgaPath, sizeof(tgaPath), "%stemp%d.tga", origpath, index); + ++index; + } while (_access(tgaPath, 0) != -1); + + + // Convert the other formats to TGA + + // jpeg files + // + if (!stricmp(extension, "jpg") || !stricmp(extension, "jpeg")) + { + // convert from the jpeg file format to the TGA file format + nErrorCode = ImgUtl_ConvertJPEGToTGA(pInPath, tgaPath, false); + if (nErrorCode == CE_SUCCESS) + { + deleteIntermediateTGA = true; + } + else + { + failed = true; + } + } + // bmp files + // + else if (!stricmp(extension, "bmp")) + { + // convert from the bmp file format to the TGA file format + nErrorCode = ImgUtl_ConvertBMPToTGA(pInPath, tgaPath); + + if (nErrorCode == CE_SUCCESS) + { + deleteIntermediateTGA = true; + } + else + { + failed = true; + } + } + // vtf files + // + else if (!stricmp(extension, "vtf")) + { + // if the file is already in the vtf format there's no need to convert it. + convertTGAToVTF = false; + + } + } + + // if we now have a TGA file, convert it to VTF + if (convertTGAToVTF && !failed) + { + nErrorCode = ImgUtl_ConvertTGA( tgaPath, nMaxWidth, nMaxHeight ); // resize TGA so that it has power-of-two dimensions with a max size of (nMaxWidth)x(nMaxHeight). + if (nErrorCode != CE_SUCCESS) + { + failed = true; + } + + if (!failed) + { + char tempPath[MAX_PATH*2]; + Q_strncpy(tempPath, tgaPath, sizeof(tempPath)); + + nErrorCode = ImgUtl_ConvertTGAToVTF( tempPath, nMaxWidth, nMaxHeight ); + if (nErrorCode == CE_SUCCESS) + { + deleteIntermediateVTF = true; + } + else + { + Msg( "Failed to convert TGA to VTF: %s\n", tempPath); + failed = true; + } + } + } + + // At this point everything should be a VTF file + + char finalPath[MAX_PATH*2]; + finalPath[0] = 0; + char vtfPath[MAX_PATH*2]; + vtfPath[0] = 0; + + + // If we haven't failed so far, create a VMT to go with this VTF + if (!failed) + { + + // If I had to convert from another filetype (i.e. the original was NOT a .vtf) + if ( convertTGAToVTF ) + { + + Q_strncpy(vtfPath, tgaPath, sizeof(vtfPath)); + + // rename the tga file to be a vtf file. + c = vtfPath + strlen(vtfPath); + while ((c > vtfPath) && (*(c-1) != '.')) + { + --c; + } + *c = 0; + Q_strncat(vtfPath, "vtf", sizeof(vtfPath), COPY_ALL_CHARACTERS); + + } + else + { + // We were handed a vtf file originally, so use it. + Q_strncpy(vtfPath, pInPath, sizeof(vtfPath)); + } + + // get the vtfFilename from the path. + const char *vtfFilename = pInPath + strlen(pInPath); + while ((vtfFilename > pInPath) && (*(vtfFilename-1) != '\\') && (*(vtfFilename-1) != '/')) + { + --vtfFilename; + } + + // Create a safe version of pOutDir with corrected slashes + char szOutDir[MAX_PATH*2]; + V_strcpy_safe( szOutDir, IsPosix() ? "/materials/" : "\\materials\\" ); + if ( pMaterialsSubDir[0] == '\\' || pMaterialsSubDir[0] == '/' ) + pMaterialsSubDir = pMaterialsSubDir + 1; + V_strcat_safe(szOutDir, pMaterialsSubDir, sizeof(szOutDir) ); + Q_StripTrailingSlash( szOutDir ); + Q_AppendSlash( szOutDir, sizeof(szOutDir) ); + Q_FixSlashes( szOutDir, CORRECT_PATH_SEPARATOR ); + +#ifdef ENGINE_DLL + Q_strncpy(finalPath, com_gamedir, sizeof(finalPath)); +#elif REPLAY_DLL + Q_strncpy(finalPath, g_pEngine->GetGameDir(), sizeof(finalPath)); +#else + Q_strncpy(finalPath, engine->GetGameDirectory(), sizeof(finalPath)); +#endif + Q_strncat(finalPath, szOutDir, sizeof(finalPath), COPY_ALL_CHARACTERS); + Q_strncat(finalPath, vtfFilename, sizeof(finalPath), COPY_ALL_CHARACTERS); + + c = finalPath + strlen(finalPath); + while ((c > finalPath) && (*(c-1) != '.')) + { + --c; + } + *c = 0; + Q_strncat(finalPath,"vtf", sizeof(finalPath), COPY_ALL_CHARACTERS); + + // make sure the directory exists before we try to copy the file. + g_pFullFileSystem->CreateDirHierarchy(szOutDir + 1, "GAME"); + //g_pFullFileSystem->CreateDirHierarchy("materials/VGUI/logos/", "GAME"); + + // write out the spray VMT file. + if ( strcmp(vtfPath, finalPath) ) // If they're not already the same + { + nErrorCode = ImgUtl_WriteGenericVMT(finalPath, pMaterialsSubDir); + if (nErrorCode != CE_SUCCESS) + { + failed = true; + } + + if (!failed) + { + // copy vtf file to the final location, only if we're not already in vtf + + DoCopyFile( vtfPath, finalPath ); + } + } + } + + // delete the intermediate VTF file if one was made. + if (deleteIntermediateVTF) + { + DoDeleteFile( vtfPath ); + + // the TGA->VTF conversion process generates a .txt file if one wasn't already there. + // in this case, delete the .txt file. + c = vtfPath + strlen(vtfPath); + while ((c > vtfPath) && (*(c-1) != '.')) + { + --c; + } + Q_strncpy(c, "txt", sizeof(vtfPath)-(c-vtfPath)); + + DoDeleteFile( vtfPath ); + } + + // delete the intermediate TGA file if one was made. + if (deleteIntermediateTGA) + { + DoDeleteFile( tgaPath ); + } + + return nErrorCode; +#endif +} + +ConversionErrorType ImgUtl_WriteGenericVMT( const char *vtfPath, const char *pMaterialsSubDir ) +{ + if (vtfPath == NULL || pMaterialsSubDir == NULL ) + { + return CE_ERROR_WRITING_OUTPUT_FILE; + } + + // make the vmt filename + char vmtPath[MAX_PATH*4]; + Q_strncpy(vmtPath, vtfPath, sizeof(vmtPath)); + char *c = vmtPath + strlen(vmtPath); + while ((c > vmtPath) && (*(c-1) != '.')) + { + --c; + } + Q_strncpy(c, "vmt", sizeof(vmtPath) - (c - vmtPath)); + + // get the root filename for the vtf file + char filename[MAX_PATH]; + while ((c > vmtPath) && (*(c-1) != '/') && (*(c-1) != '\\')) + { + --c; + } + + int i = 0; + while ((*c != 0) && (*c != '.')) + { + filename[i++] = *(c++); + } + filename[i] = 0; + + // create the vmt file. + FILE *vmtFile = fopen(vmtPath, "w"); + if (vmtFile == NULL) + { + return CE_ERROR_WRITING_OUTPUT_FILE; + } + + // make a copy of the subdir and remove any trailing slash + char szMaterialsSubDir[ MAX_PATH*2 ]; + V_strcpy_safe( szMaterialsSubDir, pMaterialsSubDir ); + V_StripTrailingSlash( szMaterialsSubDir ); + + // fix slashes + V_FixSlashes( szMaterialsSubDir ); + + // write the contents of the file. + fprintf(vmtFile, "\"UnlitGeneric\"\n{\n\t\"$basetexture\" \"%s%c%s\"\n\t\"$translucent\" \"1\"\n\t\"$ignorez\" \"1\"\n\t\"$vertexcolor\" \"1\"\n\t\"$vertexalpha\" \"1\"\n}\n", szMaterialsSubDir, CORRECT_PATH_SEPARATOR, filename); + + fclose(vmtFile); + + return CE_SUCCESS; +} + +static void WritePNGData( png_structp png_ptr, png_bytep inBytes, png_size_t byteCountToWrite ) +{ + + // Cast pointer + CUtlBuffer *pBuf = (CUtlBuffer *)png_get_io_ptr( png_ptr ); + Assert( pBuf ); + + // Write the bytes + pBuf->Put( inBytes, byteCountToWrite ); + + // What? Put() returns void. No way to detect error? +} + +static void FlushPNGData( png_structp png_ptr ) +{ + // We're writing to a memory buffer, it's a NOP +} + +ConversionErrorType ImgUtl_WriteRGBAAsPNGToBuffer( const unsigned char *pRGBAData, int nWidth, int nHeight, CUtlBuffer &bufOutData, int nStride ) +{ +#if !defined( _X360 ) + // Auto detect image stride + if ( nStride <= 0 ) + { + nStride = nWidth*4; + } + + /* could pass pointers to user-defined error handlers instead of NULLs: */ + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + if (png_ptr == NULL) + { + return CE_MEMORY_ERROR; + } + + ConversionErrorType errcode = CE_MEMORY_ERROR; + + png_bytepp row_pointers = NULL; + + png_infop info_ptr = png_create_info_struct(png_ptr); + if ( !info_ptr ) + { + errcode = CE_MEMORY_ERROR; +fail: + if ( row_pointers ) + { + free( row_pointers ); + } + png_destroy_write_struct( &png_ptr, &info_ptr ); + return errcode; + } + + // We'll use the default setjmp / longjmp error handling. + if ( setjmp( png_jmpbuf(png_ptr) ) ) + { + // Error "writing". But since we're writing to a memory bufferm, + // that just means we must have run out of memory + errcode = CE_MEMORY_ERROR; + goto fail; + } + + // Setup stream writing callbacks + png_set_write_fn(png_ptr, (void *)&bufOutData, WritePNGData, FlushPNGData); + + // Setup info structure + png_set_IHDR(png_ptr, info_ptr, nWidth, nHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + // !FIXME! Here we really should scan for the common case of + // an opaque image (all alpha=255) and strip the alpha channel + // in that case. + + // Write the file header information. + png_write_info(png_ptr, info_ptr); + + row_pointers = (png_bytepp)malloc( nHeight*sizeof(png_bytep) ); + if ( row_pointers == NULL ) + { + errcode = CE_MEMORY_ERROR; + goto fail; + } + + /* set the individual row_pointers to point at the correct offsets */ + for ( int i = 0; i < nHeight; ++i) + row_pointers[i] = const_cast(pRGBAData + i*nStride); + + // Write the image + png_write_image(png_ptr, row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + // Clean up, and we're done + free( row_pointers ); + row_pointers = NULL; + png_destroy_write_struct(&png_ptr, &info_ptr); + return CE_SUCCESS; +#else + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Initialize destination --- called by jpeg_start_compress +// before any data is actually written. +//----------------------------------------------------------------------------- +METHODDEF(void) init_destination (j_compress_ptr cinfo) +{ + JPEGDestinationManager_t *dest = ( JPEGDestinationManager_t *) cinfo->dest; + + // Allocate the output buffer --- it will be released when done with image + dest->buffer = (byte *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + JPEG_OUTPUT_BUF_SIZE * sizeof(byte)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = JPEG_OUTPUT_BUF_SIZE; +} + +//----------------------------------------------------------------------------- +// Purpose: Empty the output buffer --- called whenever buffer fills up. +// Input : boolean - +//----------------------------------------------------------------------------- +METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo) +{ + JPEGDestinationManager_t *dest = ( JPEGDestinationManager_t * ) cinfo->dest; + + CUtlBuffer *buf = dest->pBuffer; + + // Add some data + buf->Put( dest->buffer, JPEG_OUTPUT_BUF_SIZE ); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = JPEG_OUTPUT_BUF_SIZE; + + return TRUE; +} + +//----------------------------------------------------------------------------- +// Purpose: Terminate destination --- called by jpeg_finish_compress +// after all data has been written. Usually needs to flush buffer. +// +// NB: *not* called by jpeg_abort or jpeg_destroy; surrounding +// application must deal with any cleanup that should happen even +// for error exit. +//----------------------------------------------------------------------------- +METHODDEF(void) term_destination (j_compress_ptr cinfo) +{ + JPEGDestinationManager_t *dest = (JPEGDestinationManager_t *) cinfo->dest; + size_t datacount = JPEG_OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + CUtlBuffer *buf = dest->pBuffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) + { + buf->Put( dest->buffer, datacount ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Set up functions for writing data to a CUtlBuffer instead of FILE * +//----------------------------------------------------------------------------- +GLOBAL(void) jpeg_UtlBuffer_dest (j_compress_ptr cinfo, CUtlBuffer *pBuffer ) +{ + JPEGDestinationManager_t *dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof(JPEGDestinationManager_t)); + } + + dest = ( JPEGDestinationManager_t * ) cinfo->dest; + + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->pBuffer = pBuffer; +} + +//----------------------------------------------------------------------------- +// Purpose: Write three channel RGB data to a JPEG file +//----------------------------------------------------------------------------- +bool ImgUtl_WriteRGBToJPEG( unsigned char *pSrcBuf, unsigned int nSrcWidth, unsigned int nSrcHeight, const char *lpszFilename ) +{ + CUtlBuffer dstBuf; + + JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s] + int row_stride; // physical row width in image buffer + + // stderr handler + struct jpeg_error_mgr jerr; + + // compression data structure + struct jpeg_compress_struct cinfo; + + row_stride = nSrcWidth * 3; // JSAMPLEs per row in image_buffer + + // point at stderr + cinfo.err = jpeg_std_error(&jerr); + + // create compressor + jpeg_create_compress(&cinfo); + + // Hook CUtlBuffer to compression + jpeg_UtlBuffer_dest(&cinfo, &dstBuf ); + + // image width and height, in pixels + cinfo.image_width = nSrcWidth; + cinfo.image_height = nSrcHeight; + // RGB is 3 component + cinfo.input_components = 3; + // # of color components per pixel + cinfo.in_color_space = JCS_RGB; + + // Apply settings + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, 100, TRUE ); + + // Start compressor + jpeg_start_compress(&cinfo, TRUE); + + // Write scanlines + while ( cinfo.next_scanline < cinfo.image_height ) + { + row_pointer[ 0 ] = &pSrcBuf[ cinfo.next_scanline * row_stride ]; + jpeg_write_scanlines( &cinfo, row_pointer, 1 ); + } + + // Finalize image + jpeg_finish_compress(&cinfo); + + // Cleanup + jpeg_destroy_compress(&cinfo); + + return CE_SUCCESS; +} + +ConversionErrorType ImgUtl_WriteRGBAAsJPEGToBuffer( const unsigned char *pRGBAData, int nWidth, int nHeight, CUtlBuffer &bufOutData, int nStride ) +{ +#if !defined( _X360 ) + + JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s] + int row_stride; // physical row width in image buffer + + // stderr handler + struct jpeg_error_mgr jerr; + + // compression data structure + struct jpeg_compress_struct cinfo; + + row_stride = nWidth * 4; + + // point at stderr + cinfo.err = jpeg_std_error(&jerr); + + // create compressor + jpeg_create_compress(&cinfo); + + // Hook CUtlBuffer to compression + jpeg_UtlBuffer_dest(&cinfo, &bufOutData ); + + // image width and height, in pixels + cinfo.image_width = nWidth; + cinfo.image_height = nHeight; + // RGB is 3 component + cinfo.input_components = 3; + // # of color components per pixel + cinfo.in_color_space = JCS_RGB; + + // Apply settings + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, 100, TRUE ); + + // Start compressor + jpeg_start_compress(&cinfo, TRUE); + + // Write scanlines + unsigned char *pDstRow = (unsigned char *)malloc( sizeof(unsigned char) * nWidth * 4 ); + while ( cinfo.next_scanline < cinfo.image_height ) + { + const unsigned char *pSrcRow = &(pRGBAData[cinfo.next_scanline * row_stride]); + // convert row from RGBA to RGB + for ( int x = nWidth-1 ; x >= 0 ; --x ) + { + pDstRow[x*3+2] = pSrcRow[x*4+2]; + pDstRow[x*3+1] = pSrcRow[x*4+1]; + pDstRow[x*3] = pSrcRow[x*4]; + } + row_pointer[ 0 ] = pDstRow; + jpeg_write_scanlines( &cinfo, row_pointer, 1 ); + } + + // Finalize image + jpeg_finish_compress(&cinfo); + + // Cleanup + jpeg_destroy_compress(&cinfo); + + free( pDstRow ); + + return CE_SUCCESS; +#else + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; +#endif +} + +ConversionErrorType ImgUtl_LoadBitmap( const char *pszFilename, Bitmap_t &bitmap ) +{ + bitmap.Clear(); + ConversionErrorType nErrorCode; + int width, height; + unsigned char *buffer = ImgUtl_ReadImageAsRGBA( pszFilename, width, height, nErrorCode ); + if ( nErrorCode != CE_SUCCESS ) + { + return nErrorCode; + } + + // Install the buffer into the bitmap, and transfer ownership + bitmap.SetBuffer( width, height, IMAGE_FORMAT_RGBA8888, buffer, true, width*4 ); + return CE_SUCCESS; +} + +static ConversionErrorType ImgUtl_LoadJPEGBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap ) +{ + // @todo implement + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; +} + +static ConversionErrorType ImgUtl_SaveJPEGBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap ) +{ + if ( !bitmap.IsValid() ) + { + Assert( bitmap.IsValid() ); + return CE_CANT_OPEN_SOURCE_FILE; + } + + // Sorry, only RGBA8888 supported right now + if ( bitmap.Format() != IMAGE_FORMAT_RGBA8888 ) + { + Assert( bitmap.Format() == IMAGE_FORMAT_RGBA8888 ); + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + } + + // Do it + ConversionErrorType result = ImgUtl_WriteRGBAAsJPEGToBuffer( + bitmap.GetBits(), + bitmap.Width(), + bitmap.Height(), + fileData, + bitmap.Stride() + ); + return result; +} + +ConversionErrorType ImgUtl_LoadBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap, ImageFileFormat eImageFileFormat ) +{ + switch ( eImageFileFormat ) + { + case kImageFileFormat_PNG: + return ImgUtl_LoadPNGBitmapFromBuffer( fileData, bitmap ); + case kImageFileFormat_JPG: + return ImgUtl_LoadJPEGBitmapFromBuffer( fileData, bitmap ); + } + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; +} + +ConversionErrorType ImgUtl_SaveBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap, ImageFileFormat eImageFileFormat ) +{ + switch ( eImageFileFormat ) + { + case kImageFileFormat_PNG: + return ImgUtl_SavePNGBitmapToBuffer( fileData, bitmap ); + case kImageFileFormat_JPG: + return ImgUtl_SaveJPEGBitmapToBuffer( fileData, bitmap ); + } + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; +} + +ConversionErrorType ImgUtl_LoadPNGBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap ) +{ + bitmap.Clear(); + ConversionErrorType nErrorCode; + int width, height; + unsigned char *buffer = ImgUtl_ReadPNGAsRGBAFromBuffer( fileData, width, height, nErrorCode ); + if ( nErrorCode != CE_SUCCESS ) + { + return nErrorCode; + } + + // Install the buffer into the bitmap, and transfer ownership + bitmap.SetBuffer( width, height, IMAGE_FORMAT_RGBA8888, buffer, true, width*4 ); + return CE_SUCCESS; +} + +ConversionErrorType ImgUtl_SavePNGBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap ) +{ + if ( !bitmap.IsValid() ) + { + Assert( bitmap.IsValid() ); + return CE_CANT_OPEN_SOURCE_FILE; + } + + // Sorry, only RGBA8888 supported right now + if ( bitmap.Format() != IMAGE_FORMAT_RGBA8888 ) + { + Assert( bitmap.Format() == IMAGE_FORMAT_RGBA8888 ); + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + } + + // Do it + ConversionErrorType result = ImgUtl_WriteRGBAAsPNGToBuffer( + bitmap.GetBits(), + bitmap.Width(), + bitmap.Height(), + fileData, + bitmap.Stride() + ); + return result; +} + +ConversionErrorType ImgUtl_ResizeBitmap( Bitmap_t &destBitmap, int nWidth, int nHeight, const Bitmap_t *pImgSource ) +{ + + // Check for resizing in place, then save off data into a temp + Bitmap_t temp; + if ( pImgSource == NULL || pImgSource == &destBitmap ) + { + temp.MakeLogicalCopyOf( destBitmap, destBitmap.GetOwnsBuffer() ); + pImgSource = &temp; + } + + // No source image? + if ( !pImgSource->IsValid() ) + { + Assert( pImgSource->IsValid() ); + return CE_CANT_OPEN_SOURCE_FILE; + } + + // Sorry, we're using an existing rescaling routine that + // only withs for RGBA images with assumed stride + if ( + pImgSource->Format() != IMAGE_FORMAT_RGBA8888 + || pImgSource->Stride() != pImgSource->Width()*4 + ) { + Assert( pImgSource->Format() == IMAGE_FORMAT_RGBA8888 ); + Assert( pImgSource->Stride() == pImgSource->Width()*4 ); + return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED; + } + + // Allocate buffer + destBitmap.Init( nWidth, nHeight, IMAGE_FORMAT_RGBA8888 ); + + // Something wrong? + if ( !destBitmap.IsValid() ) + { + Assert( destBitmap.IsValid() ); + return CE_MEMORY_ERROR; + } + + // Do it + return ImgUtl_StretchRGBAImage( + pImgSource->GetBits(), pImgSource->Width(), pImgSource->Height(), + destBitmap.GetBits(), destBitmap.Width(), destBitmap.Height() + ); +} diff --git a/common/imageutils.h b/common/imageutils.h new file mode 100644 index 0000000..7ec0792 --- /dev/null +++ b/common/imageutils.h @@ -0,0 +1,99 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +//=======================================================================================// + +#ifndef IMAGECONVERSION_H +#define IMAGECONVERSION_H +#ifdef _WIN32 +#pragma once +#endif + +#include "tier0/basetypes.h" + +class CUtlBuffer; +struct Bitmap_t; + +enum ConversionErrorType +{ + CE_SUCCESS, + CE_MEMORY_ERROR, + CE_CANT_OPEN_SOURCE_FILE, + CE_ERROR_PARSING_SOURCE, + CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED, + CE_SOURCE_FILE_TGA_FORMAT_NOT_SUPPORTED, + CE_SOURCE_FILE_BMP_FORMAT_NOT_SUPPORTED, + CE_SOURCE_FILE_SIZE_NOT_SUPPORTED, + CE_ERROR_WRITING_OUTPUT_FILE, + CE_ERROR_LOADING_DLL +}; + +enum ImageFileFormat +{ + kImageFileFormat_PNG, + kImageFileFormat_JPG, +}; + +struct TGAHeader { + byte identsize; // size of ID field that follows 18 byte header (0 usually) + byte colourmaptype; // type of colour map 0=none, 1=has palette + byte imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed + + short colourmapstart; // first colour map entry in palette + short colourmaplength; // number of colours in palette + byte colourmapbits; // number of bits per palette entry 15,16,24,32 + + short xstart; // image x origin + short ystart; // image y origin + short width; // image width in pixels + short height; // image height in pixels + byte bits; // image bits per pixel 8,16,24,32 + byte descriptor; // image descriptor bits (vh flip bits) +}; + +ConversionErrorType ImgUtl_ConvertJPEGToTGA( const char *jpgPath, const char *tgaPath, bool bRequirePowerOfTwoSize = true ); +ConversionErrorType ImgUtl_ConvertBMPToTGA( const char *bmpPath, const char *tgaPath ); +ConversionErrorType ImgUtl_ConvertTGA( const char *tgaPath, int nMaxWidth = -1, int nMaxHeight = -1 ); +unsigned char *ImgUtl_ReadVTFAsRGBA( const char *vtfPath, int &width, int &height, ConversionErrorType &errcode ); +unsigned char *ImgUtl_ReadTGAAsRGBA( const char *tgaPath, int &width, int &height, ConversionErrorType &errcode, TGAHeader &tgaHeader ); +unsigned char *ImgUtl_ReadJPEGAsRGBA( const char *jpegPath, int &width, int &height, ConversionErrorType &errcode ); +unsigned char *ImgUtl_ReadBMPAsRGBA( const char *bmpPath, int &width, int &height, ConversionErrorType &errcode ); +unsigned char *ImgUtl_ReadPNGAsRGBA( const char *bmpPath, int &width, int &height, ConversionErrorType &errcode ); +unsigned char *ImgUtl_ReadPNGAsRGBAFromBuffer( CUtlBuffer &buffer, int &width, int &height, ConversionErrorType &errcode ); +unsigned char *ImgUtl_ReadImageAsRGBA( const char *path, int &width, int &height, ConversionErrorType &errcode ); +ConversionErrorType ImgUtl_StretchRGBAImage( const unsigned char *srcBuf, const int srcWidth, const int srcHeight, unsigned char *destBuf, const int destWidth, const int destHeight ); +ConversionErrorType ImgUtl_PadRGBAImage( const unsigned char *srcBuf, const int srcWidth, const int srcHeight, unsigned char *destBuf, const int destWidth, const int destHeight ); +ConversionErrorType ImgUtl_ConvertTGAToVTF( const char *tgaPath, int nMaxWidth = -1, int nMaxHeight = -1 ); +ConversionErrorType ImgUtl_WriteGenericVMT( const char *vtfPath, const char *pMaterialsSubDir ); +ConversionErrorType ImgUtl_WriteRGBAAsPNGToBuffer( const unsigned char *pRGBAData, int nWidth, int nHeight, CUtlBuffer &bufOutData, int nStride = 0 ); +ConversionErrorType ImgUtl_WriteRGBAAsJPEGToBuffer( const unsigned char *pRGBAData, int nWidth, int nHeight, CUtlBuffer &bufOutData, int nStride = 0 ); + +// +// Converts pInPath (which can be a TGA, BMP, or JPG file) to a VTF in pMaterialsSubDir, where +// pMaterialsSubDir is a directory located relative to the game/materials directory. If the +// output directory doesn't exist, it will be created. Dumps a generic VMT in pMaterialsSubDir +// as well. +// +ConversionErrorType ImgUtl_ConvertToVTFAndDumpVMT( const char *pInPath, const char *pMaterialsSubDir, + int nMaxWidth = -1, int nMaxHeight = -1 ); + + +/// Load from image file. We use the file extension to +/// decide what file format to use +ConversionErrorType ImgUtl_LoadBitmap( const char *pszFilename, Bitmap_t &bitmap ); + +/// Load an image direct from memory buffer +ConversionErrorType ImgUtl_LoadBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap, ImageFileFormat eImageFileFormat ); + +/// Save a bitmap to memory buffer +ConversionErrorType ImgUtl_SaveBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap, ImageFileFormat eImageFileFormat ); + +/// Load a PNG direct from memory buffer +ConversionErrorType ImgUtl_LoadPNGBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap ); + +/// Save a bitmap in PNG format to memory buffer +ConversionErrorType ImgUtl_SavePNGBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap ); + +/// Resize a bitmap. This currently only works for RGBA images! +ConversionErrorType ImgUtl_ResizeBitmap( Bitmap_t &destBitmap, int nWidth, int nHeight, const Bitmap_t *pImgSource = NULL ); + +#endif // IMAGECONVERSION_H diff --git a/gameui/GameUI.vpc b/gameui/GameUI.vpc index bf782c2..037f7d6 100644 --- a/gameui/GameUI.vpc +++ b/gameui/GameUI.vpc @@ -21,7 +21,8 @@ $Configuration $Linker { - $AdditionalDependencies "$BASE Ws2_32.lib odbc32.lib odbccp32.lib Shlwapi.lib" [$WIN32] + $AdditionalDependencies "$BASE Ws2_32.lib odbc32.lib odbccp32.lib Shlwapi.lib legacy_stdio_definitions.lib" [$WIN32] + $IgnoreSpecificDefaultLibraries "$BASE msvcrt.lib" $SystemLibraries "iconv;z" [$OSXALL] $SystemLibraries "rt" [$LINUXALL && !$DEDICATED] $GCC_ExtraLinkerFlags "-L/usr/lib32 -L/usr/lib" [$LINUXALL && !$DEDICATED] diff --git a/gameui/VGuiSystemModuleLoader.cpp b/gameui/VGuiSystemModuleLoader.cpp index 8078100..49e1550 100644 --- a/gameui/VGuiSystemModuleLoader.cpp +++ b/gameui/VGuiSystemModuleLoader.cpp @@ -9,7 +9,7 @@ #include "VGuiSystemModuleLoader.h" #include "Sys_Utils.h" #include "IVguiModule.h" -#include "ServerBrowser/IServerBrowser.h" +//#include "ServerBrowser/IServerBrowser.h" #include #include diff --git a/public/inputsystem/ButtonCode.h b/public/inputsystem/ButtonCode.h index 39dc7e0..88e3784 100644 --- a/public/inputsystem/ButtonCode.h +++ b/public/inputsystem/ButtonCode.h @@ -222,6 +222,50 @@ enum ButtonCode_t KEY_XSTICK2_LEFT, // UAXIS NEGATIVE KEY_XSTICK2_DOWN, // VAXIS POSITIVE KEY_XSTICK2_UP, // VAXIS NEGATIVE + + // stubs for Steam Controller + STEAMCONTROLLER_A, + STEAMCONTROLLER_B, + STEAMCONTROLLER_X, + STEAMCONTROLLER_Y, + STEAMCONTROLLER_DPAD_UP, + STEAMCONTROLLER_DPAD_RIGHT, + STEAMCONTROLLER_DPAD_DOWN, + STEAMCONTROLLER_DPAD_LEFT, + STEAMCONTROLLER_LEFT_BUMPER, + STEAMCONTROLLER_RIGHT_BUMPER, + STEAMCONTROLLER_LEFT_TRIGGER, + STEAMCONTROLLER_RIGHT_TRIGGER, + STEAMCONTROLLER_LEFT_GRIP, + STEAMCONTROLLER_RIGHT_GRIP, + STEAMCONTROLLER_LEFT_PAD_FINGERDOWN, + STEAMCONTROLLER_RIGHT_PAD_FINGERDOWN, + STEAMCONTROLLER_LEFT_PAD_CLICK, + STEAMCONTROLLER_RIGHT_PAD_CLICK, + STEAMCONTROLLER_LEFT_PAD_UP, + STEAMCONTROLLER_LEFT_PAD_RIGHT, + STEAMCONTROLLER_LEFT_PAD_DOWN, + STEAMCONTROLLER_LEFT_PAD_LEFT, + STEAMCONTROLLER_RIGHT_PAD_UP, + STEAMCONTROLLER_RIGHT_PAD_RIGHT, + STEAMCONTROLLER_RIGHT_PAD_DOWN, + STEAMCONTROLLER_RIGHT_PAD_LEFT, + STEAMCONTROLLER_SELECT, + STEAMCONTROLLER_START, + STEAMCONTROLLER_STEAM, + STEAMCONTROLLER_INACTIVE_START, + STEAMCONTROLLER_F1, + STEAMCONTROLLER_F2, + STEAMCONTROLLER_F3, + STEAMCONTROLLER_F4, + STEAMCONTROLLER_F5, + STEAMCONTROLLER_F6, + STEAMCONTROLLER_F7, + STEAMCONTROLLER_F8, + STEAMCONTROLLER_F9, + STEAMCONTROLLER_F10, + STEAMCONTROLLER_F11, + STEAMCONTROLLER_F12, }; inline bool IsAlpha( ButtonCode_t code ) diff --git a/public/libpng/png.h b/public/libpng/png.h new file mode 100644 index 0000000..ee080a0 --- /dev/null +++ b/public/libpng/png.h @@ -0,0 +1,2310 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +/* png.h - header file for PNG reference library + * + * libpng version 1.5.2 - March 31, 2011 + * Copyright (c) 1998-2011 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.5.2 - March 31, 2011: 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.1 14 10401 14.so.14.1[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * 1.4.4 14 10404 14.so.14.4[.0] + * 1.5.0beta01-58 15 10500 15.so.15.0[.0] + * 1.5.0rc01-07 15 10500 15.so.15.0[.0] + * 1.5.0 15 10500 15.so.15.0[.0] + * 1.5.1beta01-11 15 10501 15.so.15.1[.0] + * 1.5.1rc01-02 15 10501 15.so.15.1[.0] + * 1.5.1 15 10501 15.so.15.1[.0] + * 1.5.2beta01-03 15 10502 15.so.15.2[.0] + * 1.5.2rc01-03 15 10502 15.so.15.2[.0] + * 1.5.2 15 10502 15.so.15.2[.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-manual.txt or libpng.3 for more information. The PNG + * specification is available as a W3C Recommendation and as an ISO + * Specification, +# endif + + /* Need the time information for converting tIME chunks, it + * defines struct tm: + */ +# ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on all operating systems */ +# include +# endif +# endif + +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 2. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 3. Exported library functions. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ +/* Section 1: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 2: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_5_2; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color FAR * png_colorp; +typedef PNG_CONST png_color FAR * png_const_colorp; +typedef png_color FAR * FAR * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 FAR * png_color_16p; +typedef PNG_CONST png_color_16 FAR * png_const_color_16p; +typedef png_color_16 FAR * FAR * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 FAR * png_color_8p; +typedef PNG_CONST png_color_8 FAR * png_const_color_8p; +typedef png_color_8 FAR * FAR * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry FAR * png_sPLT_entryp; +typedef PNG_CONST png_sPLT_entry FAR * png_const_sPLT_entryp; +typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t FAR * png_sPLT_tp; +typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp; +typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text", "lang", and + * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. + * However, the * structure returned by png_get_text() will always contain + * regular zero-terminated C strings (possibly empty), never NULL pointers, + * so they can be safely used in printf() and other string-handling functions. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + png_size_t text_length; /* length of the text string */ + png_size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text FAR * png_textp; +typedef PNG_CONST png_text FAR * png_const_textp; +typedef png_text FAR * FAR * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time FAR * png_timep; +typedef PNG_CONST png_time FAR * png_const_timep; +typedef png_time FAR * FAR * png_timepp; + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* libpng-using applications should NOT directly modify this byte. */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; +typedef png_unknown_chunk FAR * png_unknown_chunkp; +typedef PNG_CONST png_unknown_chunk FAR * png_const_unknown_chunkp; +typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; +#endif + +typedef struct png_info_def png_info; +typedef png_info FAR * png_infop; +typedef PNG_CONST png_info FAR * png_const_infop; +typedef png_info FAR * FAR * png_infopp; + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((png_size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ 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. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef struct png_struct_def png_struct; +typedef PNG_CONST png_struct FAR * png_const_structp; +typedef png_struct FAR * png_structp; + +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (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. The function is required to be PNG_NORETURN. (Note that + * PNG_PTR_NORETURN is used here because current versions of the Microsoft + * C compiler do not support the PNG_NORETURN attribute on a pointer.) + * + * If you get a type warning from the compiler when linking against this line + * then your compiler has 'longjmp' that does not match the requirements of the + * compiler that built libpng. You will have to write a wrapper function for + * your compiler's longjmp and call png_set_longjmp_fn directly (not via the + * png_jmpbuf macro.) + * + * If you get a warning here while building the library you will need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +typedef PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), + PNG_PTR_NORETURN); +#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 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +typedef png_struct FAR * FAR * png_structpp; + +/* Section 3: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.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. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (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. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (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). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (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 */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, + (png_const_structp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (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. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (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), (png_longjmp_ptr)longjmp, sizeof (jmp_buf))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (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); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (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. */ +PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), + PNG_ALLOCATED); + +PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structp png_ptr, png_infop info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structp png_ptr, png_infop info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, + (png_structp png_ptr, + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + PNG_CONST struct tm FAR * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, + (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. */ +PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16 bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, + int error_action, double red, double green)); +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)); + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp + png_ptr)); +#endif + +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (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. */ +PNG_EXPORT(39, void, png_set_filler, (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. */ +PNG_EXPORT(40, void, png_set_add_alpha, + (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. */ +PNG_EXPORT(41, void, png_set_swap, (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. */ +PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_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. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)); +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# 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. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, + (png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +PNG_FP_EXPORT(50, void, png_set_gamma, + (png_structp png_ptr, double screen_gamma, + double default_file_gamma)); +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, + png_fixed_point screen_gamma, png_fixed_point default_file_gamma)); +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (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. */ +PNG_EXPORT(56, void, png_read_row, (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. */ +PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, + (png_structp png_ptr, png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, + (png_structp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (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 */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, + (png_structp png_ptr, int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() 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. + */ +PNG_EXPORT(67, void, png_set_filter, + (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. + */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)); +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_fixed_point_p + filter_weights, png_const_fixed_point_p filter_costs)); +#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. + */ +PNG_EXPORT(69, void, png_set_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, + int strategy)); + +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (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-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (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. + */ + +PNG_EXPORT(75, void, png_set_error_fn, + (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 */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_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. + */ +PNG_EXPORT(77, void, png_set_write_fn, (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. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (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). */ +PNG_EXPORT(82, void, png_set_mem_fn, (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 */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (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 */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_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. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (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 */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, + (png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +PNG_EXPORTA(94, png_voidp, png_malloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, + (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 */ +PNG_EXPORT(99, void, png_data_freer, + (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 +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, + (png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); +#endif + +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (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. */ +# undef png_benign_error +PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Same, chunk name is prepended to message. */ +# undef png_chunk_benign_error +PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#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. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, + png_const_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(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, + (png_const_structp png_ptr, png_const_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, + (png_const_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, + png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, + png_const_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)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */ +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structp png_ptr, + png_const_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 +PNG_FP_EXPORT(135, void, png_set_cHRM, + (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)); +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (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 + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, + (png_const_structp png_ptr, png_const_infop info_ptr, + double *file_gamma)); +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_file_gamma)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, + png_infop info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, + (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)); + +PNG_EXPORT(144, void, png_set_IHDR, + (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 +PNG_EXPORT(145, png_uint_32, png_get_oFFs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, + (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 +PNG_EXPORT(147, png_uint_32, png_get_pCAL, + (png_const_structp png_ptr, png_const_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 +PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr, + png_infop info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, + (png_structp png_ptr, png_infop info_ptr, + png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, + (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, + png_const_infop info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, + (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, + png_infop info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, png_bytepp profile, + png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, + (png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, png_const_bytep profile, + png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, png_uint_32, png_get_sPLT, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, + (png_structp png_ptr, png_infop info_ptr, + png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, png_uint_32, png_get_text, + (png_const_structp png_ptr, png_const_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 +PNG_EXPORT(163, void, png_set_text, + (png_structp png_ptr, png_infop info_ptr, + png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, + (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, + (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, + (png_const_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, + (png_structp png_ptr, png_infop info_ptr, + png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, double *width, double *height)); +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_structp png_ptr, png_const_infop info_ptr, int *unit, + png_fixed_point *width, + png_fixed_point *height)); +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, + (png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height)); +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, + png_infop info_ptr, int unit, png_fixed_point width, + png_fixed_point height)); +PNG_EXPORT(171, void, png_set_sCAL_s, + (png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight)); +#endif /* PNG_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 +*/ +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, + (png_structp png_ptr, int keep, + png_const_bytep chunk_list, int num_chunks)); +PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, + png_const_bytep chunk_name)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, + png_infop info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, + png_const_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); + */ +PNG_EXPORT(177, void, png_set_invalid, + (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. */ +PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (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 +PNG_EXPORT(185, void, png_set_strip_error_numbers, + (png_structp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structp png_ptr, png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, + png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, + png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr)); + +PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name, + (png_structp png_ptr), PNG_DEPRECATED); +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_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 */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ + (((yIn)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ + ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#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_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, + png_const_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). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* 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. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#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. + */ +# 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)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define png_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define png_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ + : (png_int_32)png_get_uint_32(buf))) +#endif + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) Maintainer, remember to add an entry to + * scripts/symbols.def as well. + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(221); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/public/libpng/pngconf.h b/public/libpng/pngconf.h new file mode 100644 index 0000000..e7e0cba --- /dev/null +++ b/public/libpng/pngconf.h @@ -0,0 +1,650 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.5.2 - March 31, 2011 + * + * Copyright (c) 1998-2011 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_BUILDING_SYMBOL_TABLE +/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C + * definition file for machine specific limits, this may impact the + * correctness of the definitons below (see uses of INT_MAX). + */ +# ifndef PNG_NO_LIMITS_H +# include +# endif + +/* For the memory copy APIs (i.e. the standard definitions of these), + * because this file defines png_memcpy and so on the base APIs must + * be defined here. + */ +# ifdef BSD +# include +# else +# include +# endif + +/* For png_FILE_p - this provides the standard definition of a + * FILE + */ +# ifdef PNG_STDIO_SUPPORTED +# include +# endif +#endif + +/* This controls optimization of the reading of 16 and 32 bit values + * from PNG files. It can be set on a per-app-file basis - it + * just changes whether a macro is used to the function is called. + * The library builder sets the default, if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG 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 */ + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows sytems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows/x86 systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\ + ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\ + defined(_M_X64) || defined(_M_IA64) ) + /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes + * builds under Cygwin or MinGW. Also includes Watcom builds but these need + * special treatment because they are not compatible with GCC or Visual C + * because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) + ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows/x86 */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* The default for PNG_IMPEXP depends on whether the library is + * being built or used. + */ +#ifndef PNG_IMPEXP +# ifdef PNGLIB_BUILD + /* Building the library */ +# if (defined(DLL_EXPORT)/*from libtool*/ ||\ + defined(_WINDLL) || defined(_DLL) || defined(__DLL__) ||\ + defined(_USRDLL) ||\ + defined(PNG_BUILD_DLL)) && defined(PNG_DLL_EXPORT) + /* Building a DLL. */ +# define PNG_IMPEXP PNG_DLL_EXPORT +# endif /* DLL */ +# else + /* Using the library */ +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ +#ifndef PNG_EXPORTA + +# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ + PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ + extern attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args)\ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#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. + */ +# if defined(__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_PTR_NORETURN + /* It's not enough to have the compiler be the correct compiler at + * this point - it's necessary for the library (which defines + * the type of the library longjmp) to also be the GNU library. + * This is because many systems use the GNU compiler with a + * non-GNU libc implementation. Min/GW headers are also compatible + * with GCC as well as uclibc, so it seems best to exclude known + * problem libcs here rather than just including known libcs. + * + * NOTE: this relies on the only use of PNG_PTR_NORETURN being with + * the system longjmp. If the same type is used elsewhere then this + * will need to be changed. + */ +# if !defined(__CYGWIN__) +# define PNG_PTR_NORETURN __attribute__((__noreturn__)) +# endif +# 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 PNGLIB_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 +# endif /* PNGLIB_BUILD */ +# endif /* __GNUC__ */ + +# if defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_PTR_NORETURN +# define PNG_PTR_NORETURN /* not supported */ +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __declspec(restrict) +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNGLIB_BUILD +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# endif /* PNGLIB_BUILD */ +# endif /* _MSC_VER */ +#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_PTR_NORETURN +# define PNG_PTR_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 +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#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. + * + * This should not change how the APIs are called, so it can be done + * on a per-file basis in the application. + */ +#ifndef PNG_CONST +# ifndef PNG_NO_CONST +# define PNG_CONST const +# else +# define PNG_CONST +# endif +#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 /* only used in build */ +# 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., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef PNG_CONST void FAR * png_const_voidp; +typedef png_byte FAR * png_bytep; +typedef PNG_CONST png_byte FAR * png_const_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef PNG_CONST png_int_32 FAR * png_const_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST png_int_16 FAR * png_const_int_16p; +typedef char FAR * png_charp; +typedef PNG_CONST char FAR * png_const_charp; +typedef png_fixed_point FAR * png_fixed_point_p; +typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p; +typedef png_size_t FAR * png_size_tp; +typedef PNG_CONST png_size_t FAR * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +typedef PNG_CONST double FAR * png_const_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; + +/* 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__) + typedef unsigned long png_alloc_size_t; +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + typedef unsigned long png_alloc_size_t; +# else + /* This is an attempt to detect an old Windows system where (int) is + * actually 16 bits, in that case png_malloc must have an argument with a + * bigger size to accomodate the requirements of the library. + */ +# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ + (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) + typedef DWORD png_alloc_size_t; +# else + typedef png_size_t png_alloc_size_t; +# endif +# endif +#endif + +#endif /* PNGCONF_H */ diff --git a/public/libpng/pnglibconf.h b/public/libpng/pnglibconf.h new file mode 100644 index 0000000..e14e794 --- /dev/null +++ b/public/libpng/pnglibconf.h @@ -0,0 +1,182 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +/* libpng STANDARD API DEFINITION */ + +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.5.0 - last changed on February 11, 2011 */ + +/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Derived from: scripts/pnglibconf.dfa */ +/* If you edit this file by hand you must obey the rules expressed in */ +/* pnglibconf.dfa with respect to the dependencies between the following */ +/* symbols. It is much better to generate a new file using */ +/* scripts/libpngconf.mak */ + +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* settings */ +#define PNG_API_RULE 0 +#define PNG_CALLOC_SUPPORTED +#define PNG_COST_SHIFT 3 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_sCAL_PRECISION 5 +#define PNG_USER_CHUNK_CACHE_MAX 0 +#define PNG_USER_CHUNK_MALLOC_MAX 0 +#define PNG_USER_HEIGHT_MAX 1000000L +#define PNG_USER_WIDTH_MAX 1000000L +#define PNG_WEIGHT_SHIFT 8 +#define PNG_ZBUF_SIZE 8192 +/* end of settings */ +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGN_MEMORY_SUPPORTED +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_CHECK_cHRM_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_16_TO_8_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_zTXt_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +/*#undef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED*/ +/* end of options */ +#endif /* PNGLCONF_H */ diff --git a/public/libpng/pngstruct.h b/public/libpng/pngstruct.h new file mode 100644 index 0000000..7807e06 --- /dev/null +++ b/public/libpng/pngstruct.h @@ -0,0 +1,309 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +/* pngstruct.h - header file for PNG reference library + * + * Copyright (c) 1998-2011 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.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* 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. + */ + +#ifndef PNGSTRUCT_H +#define PNGSTRUCT_H +/* zlib.h defines the structure z_stream, an instance of which is included + * in this structure and is required for decompressing the LZ compressed + * data in PNG files. + */ +#include "../zlib/zlib.h" + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf png_jmpbuf; /* used in png_error */ + png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ + png_error_ptr warning_fn; /* function for printing warnings */ + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn; /* 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; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + uInt zbuf_size; /* size of zbuf (typically 65536) */ + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_size_t rowbytes; /* size of row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ + png_row_info row_info; /* used for transformation routines */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif + +#ifdef PNG_bKGD_SUPPORTED + png_byte background_gamma_type; + png_fixed_point background_gamma; + png_color_16 background; /* background color in screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn; /* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ + png_fixed_point gamma; /* file gamma value */ + png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* 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; /* alpha values for paletted files */ + png_color_16 trans_color; /* transparent color for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# ifdef PNG_TEXT_SUPPORTED + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* 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_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup; /* lookup table for quantizing */ + png_bytep quantize_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_charp time_buffer; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int num_chunk_list; + png_bytep chunk_list; +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; +#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; +#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; +#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; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep quantize_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is + in the palette */ + png_bytep palette_to_index; /* 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; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; + + /* 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; + + /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. + */ + png_alloc_size_t user_chunk_malloc_max; +#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; +#endif + +/* New members added in libpng-1.2.26 */ + png_size_t old_big_row_buf_size; + png_size_t old_prev_row_size; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata; /* buffer for reading chunk data */ + +#ifdef PNG_IO_STATE_SUPPORTED +/* New member added in libpng-1.4.0 */ + png_uint_32 io_state; +#endif +}; +#endif /* PNGSTRUCT_H */ diff --git a/tracker/common/CompletionEvent.cpp b/tracker/common/CompletionEvent.cpp new file mode 100644 index 0000000..d2b16e0 --- /dev/null +++ b/tracker/common/CompletionEvent.cpp @@ -0,0 +1,37 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "CompletionEvent.h" +#include "winlite.h" + +//----------------------------------------------------------------------------- +// Purpose: creates an event +//----------------------------------------------------------------------------- +EventHandle_t Event_CreateEvent() +{ + return (EventHandle_t)::CreateEvent(NULL, false, false, NULL); +} + +//----------------------------------------------------------------------------- +// Purpose: sets the current thread to wait for either the event to be signalled, or the timeout to occur +//----------------------------------------------------------------------------- +void Event_WaitForEvent(EventHandle_t event, unsigned long timeoutMilliseconds) +{ + ::WaitForSingleObject((HANDLE)event, timeoutMilliseconds); +} + +//----------------------------------------------------------------------------- +// Purpose: signals an event to Activate +// Releases one thread waiting on the event. +// If the event has no threads waiting on it, the next thread to wait on it will be let right through +//----------------------------------------------------------------------------- +void Event_SignalEvent(EventHandle_t event) +{ + ::SetEvent((HANDLE)event); +} + + diff --git a/tracker/common/CompletionEvent.h b/tracker/common/CompletionEvent.h new file mode 100644 index 0000000..c16b2f3 --- /dev/null +++ b/tracker/common/CompletionEvent.h @@ -0,0 +1,32 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Wraps windows WaitForSingleEvent() calls +// +// $NoKeywords: $ +//============================================================================= + +#ifndef COMPLETIONEVENT_H +#define COMPLETIONEVENT_H +#ifdef _WIN32 +#pragma once +#endif + +// handle to an event +typedef unsigned long EventHandle_t; + +// creates an event +EventHandle_t Event_CreateEvent(); + +// sets the current thread to wait for either the event to be signalled, or the timeout to occur +void Event_WaitForEvent(EventHandle_t event, unsigned long timeoutMilliseconds); + +// set the timeout to this for it to never time out +#define TIMEOUT_INFINITE 0xFFFFFFFF + +// signals an event to Activate +// Releases one thread waiting on the event. +// If the event has no threads waiting on it, the next thread to wait on it will be let right through +void Event_SignalEvent(EventHandle_t event); + + +#endif // COMPLETIONEVENT_H diff --git a/tracker/common/DebugConsole_Interface.h b/tracker/common/DebugConsole_Interface.h new file mode 100644 index 0000000..c47c867 --- /dev/null +++ b/tracker/common/DebugConsole_Interface.h @@ -0,0 +1,30 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef DEBUGCONSOLE_INTERFACE_H +#define DEBUGCONSOLE_INTERFACE_H +#pragma once + +#include "interface.h" + +//----------------------------------------------------------------------------- +// Purpose: Debugging console interface +//----------------------------------------------------------------------------- +class IDebugConsole : public IBaseInterface +{ +public: + virtual void Initialize( const char *consoleName, int logLevel ) = 0; + virtual void Print( int severity, PRINTF_FORMAT_STRING const char *msgDescriptor, ... ) = 0; + + // gets a line of command input + // returns true if anything returned, false otherwise + virtual bool GetInput(char *buffer, int bufferSize) = 0; +}; + +#define DEBUGCONSOLE_INTERFACE_VERSION "DebugConsole001" + +#endif // DEBUGCONSOLE_INTERFACE_H diff --git a/tracker/common/DebugTimer.h b/tracker/common/DebugTimer.h new file mode 100644 index 0000000..be75eae --- /dev/null +++ b/tracker/common/DebugTimer.h @@ -0,0 +1,22 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef DEBUGTIMER_H +#define DEBUGTIMER_H +#ifdef _WIN32 +#pragma once +#endif + +// resets the timer +void Timer_Start(); + +// returns the time since Timer_Start() was called, in seconds +double Timer_End(); + + + +#endif // DEBUGTIMER_H diff --git a/tracker/common/IGameList.h b/tracker/common/IGameList.h new file mode 100644 index 0000000..6942c1d --- /dev/null +++ b/tracker/common/IGameList.h @@ -0,0 +1,69 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef IGAMELIST_H +#define IGAMELIST_H +#ifdef _WIN32 +#pragma once +#endif + +struct serveritem_t; +#include "FindSteamServers.h" + +#define EMPTY_SERVER_NAME "0.0.0.0:0" + +//----------------------------------------------------------------------------- +// Purpose: Interface to accessing a game list +//----------------------------------------------------------------------------- +class IGameList +{ +public: + + enum InterfaceItem_e + { + FILTERS, + GETNEWLIST, + ADDSERVER, + ADDCURRENTSERVER, + }; + + // returns true if the game list supports the specified ui elements + virtual bool SupportsItem(InterfaceItem_e item) = 0; + + // starts the servers refreshing + virtual void StartRefresh() = 0; + + // gets a new server list + virtual void GetNewServerList() = 0; + + // stops current refresh/GetNewServerList() + virtual void StopRefresh() = 0; + + // returns true if the list is currently refreshing servers + virtual bool IsRefreshing() = 0; + + // gets information about specified server + virtual serveritem_t &GetServer(unsigned int serverID) = 0; + + // adds a new server to list + virtual void AddNewServer(serveritem_t &server) = 0; + + // marks that server list has been fully received + virtual void ListReceived(bool moreAvailable, const char *lastUniqueIP, ESteamServerType serverType) = 0; + + // called when Connect button is pressed + virtual void OnBeginConnect() = 0; + + // reapplies filters + virtual void ApplyFilters() = 0; + + // invalid server index + virtual int GetInvalidServerListID() = 0; +}; + + +#endif // IGAMELIST_H diff --git a/tracker/common/IServerRefreshResponse.h b/tracker/common/IServerRefreshResponse.h new file mode 100644 index 0000000..5006dd2 --- /dev/null +++ b/tracker/common/IServerRefreshResponse.h @@ -0,0 +1,34 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef ISERVERREFRESHRESPONSE_H +#define ISERVERREFRESHRESPONSE_H +#ifdef _WIN32 +#pragma once +#endif + +struct serveritem_t; + +//----------------------------------------------------------------------------- +// Purpose: Callback interface for server updates +//----------------------------------------------------------------------------- +class IServerRefreshResponse +{ +public: + // called when the server has successfully responded + virtual void ServerResponded(serveritem_t &server) = 0; + + // called when a server response has timed out + virtual void ServerFailedToRespond(serveritem_t &server) = 0; + + // called when the current refresh list is complete + virtual void RefreshComplete() = 0; +}; + + + +#endif // ISERVERREFRESHRESPONSE_H diff --git a/tracker/common/IceKey.H b/tracker/common/IceKey.H new file mode 100644 index 0000000..308be69 --- /dev/null +++ b/tracker/common/IceKey.H @@ -0,0 +1,65 @@ +//========= Public Domain Code ================================================ +// +// Purpose: Header file for the C++ ICE encryption class. +// Taken from public domain code, as written by Matthew Kwan - July 1996 +// http://www.darkside.com.au/ice/ +//============================================================================= + +#ifndef _IceKey_H +#define _IceKey_H + +/* +The IceKey class is used for encrypting and decrypting 64-bit blocks of data +with the ICE (Information Concealment Engine) encryption algorithm. + +The constructor creates a new IceKey object that can be used to encrypt and decrypt data. +The level of encryption determines the size of the key, and hence its speed. +Level 0 uses the Thin-ICE variant, which is an 8-round cipher taking an 8-byte key. +This is the fastest option, and is generally considered to be at least as secure as DES, +although it is not yet certain whether it is as secure as its key size. + +For levels n greater than zero, a 16n-round cipher is used, taking 8n-byte keys. +Although not as fast as level 0, these are very very secure. + +Before an IceKey can be used to encrypt data, its key schedule must be set with the set() member function. +The length of the key required is determined by the level, as described above. + +The member functions encrypt() and decrypt() encrypt and decrypt respectively data +in blocks of eight chracters, using the specified key. + +Two functions keySize() and blockSize() are provided +which return the key and block size respectively, measured in bytes. +The key size is determined by the level, while the block size is always 8. + +The destructor zeroes out and frees up all memory associated with the key. +*/ + +class IceSubkey; + +class IceKey { + public: + IceKey (int n); + ~IceKey (); + + void set (const unsigned char *key); + + void encrypt (const unsigned char *plaintext, + unsigned char *ciphertext) const; + + void decrypt (const unsigned char *ciphertext, + unsigned char *plaintext) const; + + int keySize () const; + + int blockSize () const; + + private: + void scheduleBuild (unsigned short *k, int n, + const int *keyrot); + + int _size; + int _rounds; + IceSubkey *_keysched; +}; + +#endif diff --git a/tracker/common/IceKey.cpp b/tracker/common/IceKey.cpp new file mode 100644 index 0000000..af25dd9 --- /dev/null +++ b/tracker/common/IceKey.cpp @@ -0,0 +1,393 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +//========= Public Domain Code ================================================ +// +// Purpose: C++ implementation of the ICE encryption algorithm. +// Taken from public domain code, as written by Matthew Kwan - July 1996 +// http://www.darkside.com.au/ice/ +//============================================================================= + +#include "mathlib/IceKey.H" + +#pragma warning(disable: 4244) + + + /* Structure of a single round subkey */ +class IceSubkey { + public: + unsigned long val[3]; +}; + + + /* The S-boxes */ +static unsigned long ice_sbox[4][1024]; +static int ice_sboxes_initialised = 0; + + + /* Modulo values for the S-boxes */ +static const int ice_smod[4][4] = { + {333, 313, 505, 369}, + {379, 375, 319, 391}, + {361, 445, 451, 397}, + {397, 425, 395, 505}}; + + /* XOR values for the S-boxes */ +static const int ice_sxor[4][4] = { + {0x83, 0x85, 0x9b, 0xcd}, + {0xcc, 0xa7, 0xad, 0x41}, + {0x4b, 0x2e, 0xd4, 0x33}, + {0xea, 0xcb, 0x2e, 0x04}}; + + /* Permutation values for the P-box */ +static const unsigned long ice_pbox[32] = { + 0x00000001, 0x00000080, 0x00000400, 0x00002000, + 0x00080000, 0x00200000, 0x01000000, 0x40000000, + 0x00000008, 0x00000020, 0x00000100, 0x00004000, + 0x00010000, 0x00800000, 0x04000000, 0x20000000, + 0x00000004, 0x00000010, 0x00000200, 0x00008000, + 0x00020000, 0x00400000, 0x08000000, 0x10000000, + 0x00000002, 0x00000040, 0x00000800, 0x00001000, + 0x00040000, 0x00100000, 0x02000000, 0x80000000}; + + /* The key rotation schedule */ +static const int ice_keyrot[16] = { + 0, 1, 2, 3, 2, 1, 3, 0, + 1, 3, 2, 0, 3, 1, 0, 2}; + + +/* + * 8-bit Galois Field multiplication of a by b, modulo m. + * Just like arithmetic multiplication, except that additions and + * subtractions are replaced by XOR. + */ + +static unsigned int +gf_mult ( + register unsigned int a, + register unsigned int b, + register unsigned int m +) { + register unsigned int res = 0; + + while (b) { + if (b & 1) + res ^= a; + + a <<= 1; + b >>= 1; + + if (a >= 256) + a ^= m; + } + + return (res); +} + + +/* + * Galois Field exponentiation. + * Raise the base to the power of 7, modulo m. + */ + +static unsigned long +gf_exp7 ( + register unsigned int b, + unsigned int m +) { + register unsigned int x; + + if (b == 0) + return (0); + + x = gf_mult (b, b, m); + x = gf_mult (b, x, m); + x = gf_mult (x, x, m); + return (gf_mult (b, x, m)); +} + + +/* + * Carry out the ICE 32-bit P-box permutation. + */ + +static unsigned long +ice_perm32 ( + register unsigned long x +) { + register unsigned long res = 0; + register const unsigned long *pbox = ice_pbox; + + while (x) { + if (x & 1) + res |= *pbox; + pbox++; + x >>= 1; + } + + return (res); +} + + +/* + * Initialise the ICE S-boxes. + * This only has to be done once. + */ + +static void +ice_sboxes_init (void) +{ + register int i; + + for (i=0; i<1024; i++) { + int col = (i >> 1) & 0xff; + int row = (i & 0x1) | ((i & 0x200) >> 8); + unsigned long x; + + x = gf_exp7 (col ^ ice_sxor[0][row], ice_smod[0][row]) << 24; + ice_sbox[0][i] = ice_perm32 (x); + + x = gf_exp7 (col ^ ice_sxor[1][row], ice_smod[1][row]) << 16; + ice_sbox[1][i] = ice_perm32 (x); + + x = gf_exp7 (col ^ ice_sxor[2][row], ice_smod[2][row]) << 8; + ice_sbox[2][i] = ice_perm32 (x); + + x = gf_exp7 (col ^ ice_sxor[3][row], ice_smod[3][row]); + ice_sbox[3][i] = ice_perm32 (x); + } +} + + +/* + * Create a new ICE key. + */ + +IceKey::IceKey (int n) +{ + if (!ice_sboxes_initialised) { + ice_sboxes_init (); + ice_sboxes_initialised = 1; + } + + if (n < 1) { + _size = 1; + _rounds = 8; + } else { + _size = n; + _rounds = n * 16; + } + + _keysched = new IceSubkey[_rounds]; +} + + +/* + * Destroy an ICE key. + */ + +IceKey::~IceKey () +{ + int i, j; + + for (i=0; i<_rounds; i++) + for (j=0; j<3; j++) + _keysched[i].val[j] = 0; + + _rounds = _size = 0; + + delete[] _keysched; +} + + +/* + * The single round ICE f function. + */ + +static unsigned long +ice_f ( + register unsigned long p, + const IceSubkey *sk +) { + unsigned long tl, tr; /* Expanded 40-bit values */ + unsigned long al, ar; /* Salted expanded 40-bit values */ + + /* Left half expansion */ + tl = ((p >> 16) & 0x3ff) | (((p >> 14) | (p << 18)) & 0xffc00); + + /* Right half expansion */ + tr = (p & 0x3ff) | ((p << 2) & 0xffc00); + + /* Perform the salt permutation */ + // al = (tr & sk->val[2]) | (tl & ~sk->val[2]); + // ar = (tl & sk->val[2]) | (tr & ~sk->val[2]); + al = sk->val[2] & (tl ^ tr); + ar = al ^ tr; + al ^= tl; + + al ^= sk->val[0]; /* XOR with the subkey */ + ar ^= sk->val[1]; + + /* S-box lookup and permutation */ + return (ice_sbox[0][al >> 10] | ice_sbox[1][al & 0x3ff] + | ice_sbox[2][ar >> 10] | ice_sbox[3][ar & 0x3ff]); +} + + +/* + * Encrypt a block of 8 bytes of data with the given ICE key. + */ + +void +IceKey::encrypt ( + const unsigned char *ptext, + unsigned char *ctext +) const +{ + register int i; + register unsigned long l, r; + + l = (((unsigned long) ptext[0]) << 24) + | (((unsigned long) ptext[1]) << 16) + | (((unsigned long) ptext[2]) << 8) | ptext[3]; + r = (((unsigned long) ptext[4]) << 24) + | (((unsigned long) ptext[5]) << 16) + | (((unsigned long) ptext[6]) << 8) | ptext[7]; + + for (i = 0; i < _rounds; i += 2) { + l ^= ice_f (r, &_keysched[i]); + r ^= ice_f (l, &_keysched[i + 1]); + } + + for (i = 0; i < 4; i++) { + ctext[3 - i] = r & 0xff; + ctext[7 - i] = l & 0xff; + + r >>= 8; + l >>= 8; + } +} + + +/* + * Decrypt a block of 8 bytes of data with the given ICE key. + */ + +void +IceKey::decrypt ( + const unsigned char *ctext, + unsigned char *ptext +) const +{ + register int i; + register unsigned long l, r; + + l = (((unsigned long) ctext[0]) << 24) + | (((unsigned long) ctext[1]) << 16) + | (((unsigned long) ctext[2]) << 8) | ctext[3]; + r = (((unsigned long) ctext[4]) << 24) + | (((unsigned long) ctext[5]) << 16) + | (((unsigned long) ctext[6]) << 8) | ctext[7]; + + for (i = _rounds - 1; i > 0; i -= 2) { + l ^= ice_f (r, &_keysched[i]); + r ^= ice_f (l, &_keysched[i - 1]); + } + + for (i = 0; i < 4; i++) { + ptext[3 - i] = r & 0xff; + ptext[7 - i] = l & 0xff; + + r >>= 8; + l >>= 8; + } +} + + +/* + * Set 8 rounds [n, n+7] of the key schedule of an ICE key. + */ + +void +IceKey::scheduleBuild ( + unsigned short *kb, + int n, + const int *keyrot +) { + int i; + + for (i=0; i<8; i++) { + register int j; + register int kr = keyrot[i]; + IceSubkey *isk = &_keysched[n + i]; + + for (j=0; j<3; j++) + isk->val[j] = 0; + + for (j=0; j<15; j++) { + register int k; + unsigned long *curr_sk = &isk->val[j % 3]; + + for (k=0; k<4; k++) { + unsigned short *curr_kb = &kb[(kr + k) & 3]; + register int bit = *curr_kb & 1; + + *curr_sk = (*curr_sk << 1) | bit; + *curr_kb = (*curr_kb >> 1) | ((bit ^ 1) << 15); + } + } + } +} + + +/* + * Set the key schedule of an ICE key. + */ + +void +IceKey::set ( + const unsigned char *key +) { + int i; + + if (_rounds == 8) { + unsigned short kb[4]; + + for (i=0; i<4; i++) + kb[3 - i] = (key[i*2] << 8) | key[i*2 + 1]; + + scheduleBuild (kb, 0, ice_keyrot); + return; + } + + for (i=0; i<_size; i++) { + int j; + unsigned short kb[4]; + + for (j=0; j<4; j++) + kb[3 - j] = (key[i*8 + j*2] << 8) | key[i*8 + j*2 + 1]; + + scheduleBuild (kb, i*8, ice_keyrot); + scheduleBuild (kb, _rounds - 8 - i*8, &ice_keyrot[8]); + } +} + + +/* + * Return the key size, in bytes. + */ + +int +IceKey::keySize () const +{ + return (_size * 8); +} + + +/* + * Return the block size, in bytes. + */ + +int +IceKey::blockSize () const +{ + return (8); +} diff --git a/tracker/common/MasterMsgHandler.h b/tracker/common/MasterMsgHandler.h new file mode 100644 index 0000000..ea19429 --- /dev/null +++ b/tracker/common/MasterMsgHandler.h @@ -0,0 +1,32 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef MASTERMSGHANDLER_H +#define MASTERMSGHANDLER_H +#ifdef _WIN32 +#pragma once +#endif + +#include "Socket.h" + +//----------------------------------------------------------------------------- +// Purpose: Socket handler for lan broadcast pings +//----------------------------------------------------------------------------- +class CMasterMsgHandler : public CMsgHandler +{ +public: + CMasterMsgHandler( IGameList *baseobject, HANDLERTYPE type, void *typeinfo = NULL ); + + virtual bool Process( netadr_t *from, CMsgBuffer *msg ); + +private: + IGameList *m_pGameList; +}; + + + +#endif // MASTERMSGHANDLER_H diff --git a/tracker/common/Socket.cpp b/tracker/common/Socket.cpp new file mode 100644 index 0000000..1ce40f0 --- /dev/null +++ b/tracker/common/Socket.cpp @@ -0,0 +1,1035 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#if !defined( _X360 ) +#define FD_SETSIZE 1024 +#endif + +#include +#include "winlite.h" +#if !defined( _X360 ) +#include "winsock.h" +#else +#include "winsockx.h" +#endif +#include "msgbuffer.h" +#include "socket.h" +#include "inetapi.h" +#include "tier0/vcrmode.h" + +#include + +#if defined( _X360 ) +#include "xbox/xbox_win32stubs.h" +#endif + +//----------------------------------------------------------------------------- +// Purpose: All socket I/O occurs on a thread +//----------------------------------------------------------------------------- +class CSocketThread +{ +public: + typedef struct threadsocket_s + { + struct threadsocket_s *next; + CSocket *socket; + } threadsocket_t; + + // Construction + CSocketThread( void ); + virtual ~CSocketThread( void ); + + // Sockets add/remove themselves via their constructor + virtual void AddSocketToThread( CSocket *socket ); + virtual void RemoveSocketFromThread( CSocket *socket ); + + // Lock changes to socket list, etc. + virtual void Lock( void ); + // Unlock socket list, etc. + virtual void Unlock( void ); + + // Retrieve handle to shutdown event + virtual HANDLE GetShutdownHandle( void ); + // Get head of socket list + virtual threadsocket_t *GetSocketList( void ); + + // Sample clock for socket thread + virtual float GetClock( void ); + +private: + // Initialize the clock + void InitTimer( void ); + +private: + // Critical section used for synchronizing access to socket list + CRITICAL_SECTION cs; + // List of sockets we are listening on + threadsocket_t *m_pSocketList; + // Thread handle + HANDLE m_hThread; + // Thread id + DWORD m_nThreadId; + // Event to set when we want to tell the thread to shut itself down + HANDLE m_hShutdown; + + // High performance clock frequency + double m_dClockFrequency; + // Current accumulated time + double m_dCurrentTime; + // How many bits to shift raw 64 bit sample count by + int m_nTimeSampleShift; + // Previous 32 bit sample count + unsigned int m_uiPreviousTime; +}; + +// Singleton handler +static CSocketThread *GetSocketThread() +{ + static CSocketThread g_SocketThread; + return &g_SocketThread; +} + +//----------------------------------------------------------------------------- +// Purpose: Main winsock processing thread +// Input : threadobject - +// Output : static DWORD WINAPI +//----------------------------------------------------------------------------- +static DWORD WINAPI SocketThreadFunc( LPVOID threadobject ) +{ + // Get pointer to CSocketThread object + CSocketThread *socketthread = ( CSocketThread * )threadobject; + assert( socketthread ); + if ( !socketthread ) + { + return 0; + } + + // Keep looking for data until shutdown event is triggered + while ( 1 ) + { + // List of sockets + CSocketThread::threadsocket_t *sockets; + // file descriptor set for sockets + fd_set fdset; + // number of sockets with messages ready + int number; + // number of sockets added to fd_set + int count; + + // Check for shutdown event + if ( WAIT_OBJECT_0 == VCRHook_WaitForSingleObject( socketthread->GetShutdownHandle(), 0 ) ) + { + break; + } + + // Clear the set + FD_ZERO(&fdset); + + // No changes to list right now + socketthread->Lock(); + + // Add all active sockets to the fdset + count = 0; + for ( sockets = socketthread->GetSocketList(); sockets; sockets = sockets->next ) + { + FD_SET( static_cast( sockets->socket->GetSocketNumber() ), &fdset ); + count = max( count, sockets->socket->GetSocketNumber() ); + } + + // Done + socketthread->Unlock(); + + if ( count ) + { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100000; // 100 millisecond == 100000 usec + + // Block for 100000 usec, or until a message is in the queue + number = select( count + 1, &fdset, NULL, NULL, &tv ); +#if !defined( NO_VCR ) + VCRGenericValue( "", &number, sizeof( number ) ); +#endif + if ( number > 0 ) + { + // Iterate through socket list and see who has data waiting // + // No changes to list right now + socketthread->Lock(); + + // Check FD_SET for incoming network messages + for ( sockets = socketthread->GetSocketList(); sockets; sockets = sockets->next ) + { + bool bSet = FD_ISSET( sockets->socket->GetSocketNumber(), &fdset ); +#if !defined( NO_VCR ) + VCRGenericValue( "", &bSet, sizeof( bSet ) ); +#endif + if ( bSet ) + { + // keep reading as long as there is data on the socket + while (sockets->socket->ReceiveData()) + { + } + } + } + + // Done + socketthread->Unlock(); + } + } + + // no need to sleep here, much better let it sleep in the select + } + + ExitThread( 0 ); + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Construction +//----------------------------------------------------------------------------- +CSocketThread::CSocketThread( void ) +{ + InitTimer(); + + m_pSocketList = NULL; + + InitializeCriticalSection( &cs ); + + m_hShutdown = CreateEvent( NULL, TRUE, FALSE, NULL ); + assert( m_hShutdown ); + + m_hThread = 0; + m_nThreadId = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CSocketThread::~CSocketThread( void ) +{ + Lock(); + if ( m_hThread ) + { + SetEvent( m_hShutdown ); + Sleep( 2 ); + TerminateThread( m_hThread, 0 ); + } + Unlock(); + + // Kill the socket +//!! need to validate this line +// assert( !m_pSocketList ); + + if ( m_hThread ) + { + CloseHandle( m_hThread ); + } + + CloseHandle( m_hShutdown ); + + DeleteCriticalSection( &cs ); +} + +//----------------------------------------------------------------------------- +// Purpose: Initialize socket thread timer +//----------------------------------------------------------------------------- +void CSocketThread::InitTimer( void ) +{ + BOOL success; + LARGE_INTEGER PerformanceFreq; + unsigned int lowpart, highpart; + + // Start clock at zero + m_dCurrentTime = 0.0; + + success = QueryPerformanceFrequency( &PerformanceFreq ); + assert( success ); + + // get 32 out of the 64 time bits such that we have around + // 1 microsecond resolution + lowpart = (unsigned int)PerformanceFreq.LowPart; + highpart = (unsigned int)PerformanceFreq.HighPart; + + m_nTimeSampleShift = 0; + + while ( highpart || ( lowpart > 2000000.0 ) ) + { + m_nTimeSampleShift++; + lowpart >>= 1; + lowpart |= (highpart & 1) << 31; + highpart >>= 1; + } + + m_dClockFrequency = 1.0 / (double)lowpart; + + // Get initial sample + unsigned int temp; + LARGE_INTEGER PerformanceCount; + QueryPerformanceCounter( &PerformanceCount ); + if ( !m_nTimeSampleShift ) + { + temp = (unsigned int)PerformanceCount.LowPart; + } + else + { + // Rotate counter to right by m_nTimeSampleShift places + temp = ((unsigned int)PerformanceCount.LowPart >> m_nTimeSampleShift) | + ((unsigned int)PerformanceCount.HighPart << (32 - m_nTimeSampleShift)); + } + + // Set first time stamp + m_uiPreviousTime = temp; +} + +//----------------------------------------------------------------------------- +// Purpose: Thread local timer function +// Output : float +//----------------------------------------------------------------------------- +float CSocketThread::GetClock( void ) +{ + LARGE_INTEGER PerformanceCount; + unsigned int temp, t2; + double time; + + // Get sample counter + QueryPerformanceCounter( &PerformanceCount ); + + if ( !m_nTimeSampleShift ) + { + temp = (unsigned int)PerformanceCount.LowPart; + } + else + { + // Rotate counter to right by m_nTimeSampleShift places + temp = ((unsigned int)PerformanceCount.LowPart >> m_nTimeSampleShift) | + ((unsigned int)PerformanceCount.HighPart << (32 - m_nTimeSampleShift)); + } + + // check for turnover or backward time + if ( ( temp <= m_uiPreviousTime ) && + ( ( m_uiPreviousTime - temp ) < 0x10000000) ) + { + m_uiPreviousTime = temp; // so we can't get stuck + } + else + { + // gap in performance clocks + t2 = temp - m_uiPreviousTime; + + // Convert to time using frequencey of clock + time = (double)t2 * m_dClockFrequency; + + // Remember old time + m_uiPreviousTime = temp; + + // Increment clock + m_dCurrentTime += time; + } +#if !defined( NO_VCR ) + VCRGenericValue( "", &m_dCurrentTime, sizeof( m_dCurrentTime ) ); +#endif + // Convert to float + return (float)m_dCurrentTime; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns handle of shutdown event +// Output : HANDLE +//----------------------------------------------------------------------------- +HANDLE CSocketThread::GetShutdownHandle( void ) +{ + return m_hShutdown; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns head of socket list +// Output : CSocketThread::threadsocket_t +//----------------------------------------------------------------------------- +CSocketThread::threadsocket_t *CSocketThread::GetSocketList( void ) +{ + return m_pSocketList; +} + +int socketCount = 0; + +//----------------------------------------------------------------------------- +// Purpose: Locks object and adds socket to thread +//----------------------------------------------------------------------------- +void CSocketThread::AddSocketToThread( CSocket *socket ) +{ + // create the thread if it isn't there + if (!m_hThread) + { + m_hThread = VCRHook_CreateThread( NULL, 0, SocketThreadFunc, (void *)this, 0, &m_nThreadId ); + assert( m_hThread ); + } + + socketCount++; + + threadsocket_t *p = new threadsocket_t; + p->socket = socket; + + Lock(); + p->next = m_pSocketList; + m_pSocketList = p; + Unlock(); +} + +//----------------------------------------------------------------------------- +// Purpose: Locks list and removes specified socket from thread +//----------------------------------------------------------------------------- +void CSocketThread::RemoveSocketFromThread( CSocket *socket ) +{ + if (!m_hThread) + return; + + socketCount--; + + Lock(); + if ( m_pSocketList ) + { + threadsocket_t *p, *n; + p = m_pSocketList; + if ( p->socket == socket ) + { + m_pSocketList = m_pSocketList->next; + delete p; + } + else + { + while ( p->next ) + { + n = p->next; + if ( n->socket == socket ) + { + p->next = n->next; + delete n; + break; + } + p = n; + } + } + } + Unlock(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSocketThread::Lock( void ) +{ + VCRHook_EnterCriticalSection( &cs ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSocketThread::Unlock( void ) +{ + LeaveCriticalSection( &cs ); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructs a message handler for incoming socket messages +//----------------------------------------------------------------------------- +CMsgHandler::CMsgHandler( HANDLERTYPE type, void *typeinfo /*=NULL*/ ) +{ + m_Type = type; + m_pNext = NULL; + + // Assume no socket + SetSocket( NULL ); + + // Assume no special checking + m_ByteCode = 0; + m_szString[ 0 ] = 0; + + switch ( m_Type ) + { + default: + case MSGHANDLER_ALL: + break; + case MSGHANDLER_BYTECODE: + m_ByteCode = *(unsigned char *)typeinfo; + break; + case MSGHANDLER_STRING: + strcpy( m_szString, (char *)typeinfo ); + break; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CMsgHandler::~CMsgHandler( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Default message handler for received messages +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CMsgHandler::Process( netadr_t *from, CMsgBuffer *msg ) +{ + // Swallow message by default + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Check for special handling +// Input : *from - +// *msg - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CMsgHandler::ProcessMessage( netadr_t *from, CMsgBuffer *msg ) +{ + bool bret = false; + unsigned char ch; + const char *str; + + // Crack bytecode or string code + switch( m_Type ) + { + case MSGHANDLER_BYTECODE: + msg->Push(); + ch = (unsigned char)msg->ReadByte(); + msg->Pop(); + if ( ch == m_ByteCode ) + { + bret = Process( from, msg ); + } + break; + case MSGHANDLER_STRING: + msg->Push(); + str = msg->ReadString(); + msg->Pop(); + if ( str && str[ 0 ] && !stricmp( m_szString, str ) ) + { + bret = Process( from, msg ); + } + break; + default: + case MSGHANDLER_ALL: + bret = Process( from, msg ); + break; + } + + return bret; +} + +//----------------------------------------------------------------------------- +// Purpose: Get next in chain of handlers +//----------------------------------------------------------------------------- +CMsgHandler *CMsgHandler::GetNext( void ) const +{ + return m_pNext; +} + +//----------------------------------------------------------------------------- +// Purpose: Set next in handler chain +// Input : *next - +//----------------------------------------------------------------------------- +void CMsgHandler::SetNext( CMsgHandler *next ) +{ + m_pNext = next; +} + +//----------------------------------------------------------------------------- +// Purpose: Get underlying socket object +// Output : CSocket +//----------------------------------------------------------------------------- +CSocket *CMsgHandler::GetSocket( void ) const +{ + return m_pSocket; +} + +//----------------------------------------------------------------------------- +// Purpose: Set underlying socket object +// Input : *socket - +//----------------------------------------------------------------------------- +void CMsgHandler::SetSocket( CSocket *socket ) +{ + m_pSocket = socket; +} + +//----------------------------------------------------------------------------- +// Purpose: Creates a non-blocking, broadcast capable, UDP socket. If port is +// specified, binds it to listen on that port, otherwise, chooses a random port. +//----------------------------------------------------------------------------- +CSocket::CSocket( const char *socketname, int port /*= -1*/ ) : m_SendBuffer(socketname) +{ + struct sockaddr_in address; + unsigned long _true = 1; + int i = 1; + + m_pSocketName = socketname; + + m_bValid = false; + m_bResolved = false; + m_pMessageHandlers = NULL; + m_nUserData = 0; + m_bBroadcastSend = false; + m_iTotalPackets = 0; + m_iCurrentPackets = 0; + m_iRetries = 0; + + m_pBufferCS = new CRITICAL_SECTION; + InitializeCriticalSection((CRITICAL_SECTION *)m_pBufferCS); + + // ensure the socketthread singleton has been created + GetSocketThread(); + + // Set up the socket + m_Socket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ); + if ( m_Socket == -1 ) + { + //int err = WSAGetLastError(); + // WSANOTINITIALISED + return; + } + + // Set it to non-blocking + if ( ioctlsocket ( m_Socket, FIONBIO, &_true ) == -1 ) + { + closesocket( m_Socket ); + m_Socket = 0; + return; + } + + // Allow broadcast packets + if ( setsockopt( m_Socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == -1 ) + { + closesocket( m_Socket ); + m_Socket = 0; + return; + } + + // LATER: Support specifying interface name + //if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost")) + address.sin_addr.s_addr = INADDR_ANY; + //else + // NET_StringToSockaddr (net_interface, (struct sockaddr *)&address); + + if ( port == -1 ) + { + address.sin_port = 0; + } + else + { + address.sin_port = htons( (short)port ); + } + + address.sin_family = AF_INET; + + // only bind if we're required to be on a certain port + if ( address.sin_port > 0) + { + // Bind the socket to specified port + if ( bind( m_Socket, (struct sockaddr *)&address, sizeof(address) ) == -1 ) + { + closesocket (m_Socket); + m_Socket = 0; + return; + } + } + + // Mark as valid + m_bValid = true; + + // Only add valid sockets to thread + GetSocketThread()->AddSocketToThread( this ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CSocket::~CSocket( void ) +{ + DeleteCriticalSection((CRITICAL_SECTION *)m_pBufferCS); + delete (CRITICAL_SECTION *)m_pBufferCS; + + // Try to remove socket from thread + GetSocketThread()->RemoveSocketFromThread( this ); + + // Ask message handlers to remove selves? + if ( m_bValid ) + { + ::shutdown(m_Socket, 0x01); + ::shutdown(m_Socket, 0x02); + closesocket( m_Socket ); + m_Socket = 0; + } + + // Remove handlers + CMsgHandler *handler = m_pMessageHandlers; + while ( handler ) + { + RemoveMessageHandler( handler ); + delete handler; + handler = m_pMessageHandlers; + } + m_pMessageHandlers = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Add hander to head of chain +// Input : *handler - +//----------------------------------------------------------------------------- +void CSocket::AddMessageHandler( CMsgHandler *handler ) +{ + handler->SetNext( m_pMessageHandlers ); + m_pMessageHandlers = handler; + + // Set the socket pointer + handler->SetSocket( this ); +} + +//----------------------------------------------------------------------------- +// Purpose: Removed indicated handler +// Input : *handler - +//----------------------------------------------------------------------------- +void CSocket::RemoveMessageHandler( CMsgHandler *handler ) +{ + if ( !handler ) + { + return; + } + + CMsgHandler *list = m_pMessageHandlers; + if ( list == handler ) + { + m_pMessageHandlers = m_pMessageHandlers->GetNext(); + return; + } + + while ( list ) + { + if ( list->GetNext() == handler ) + { + list->SetNext( handler->GetNext() ); + handler->SetNext( NULL ); + return; + } + list = list->GetNext(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Send message to specified address +// Input : *to - +// Output : int - number of bytes sent +//----------------------------------------------------------------------------- +int CSocket::SendMessage( netadr_t *to, CMsgBuffer *msg /*= NULL*/ ) +{ + m_bBroadcastSend = false; + m_ToAddress = *to; + + if ( !m_bValid ) + { + return 0; + } + + if ( !msg ) + { + msg = GetSendBuffer(); + } + + struct sockaddr addr; + net->NetAdrToSockAddr ( to, &addr ); + + int bytessent = sendto( m_Socket, (const char *)msg->GetData(), msg->GetCurSize(), 0, &addr, sizeof( addr ) ); + if ( bytessent == msg->GetCurSize() ) + { + return bytessent; + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Send broadcast message on specified port +// Input : port - +// Output : int - number of bytes sent +//----------------------------------------------------------------------------- +int CSocket::Broadcast( int port, CMsgBuffer *msg /*= NULL*/ ) +{ + m_bBroadcastSend = true; + memset( &m_ToAddress, 0, sizeof( m_ToAddress ) ); + + if ( !m_bValid ) + { + return 0; + } + + if ( !msg ) + { + msg = GetSendBuffer(); + } + + struct sockaddr addr; + netadr_t to; + + to.port = (unsigned short)htons( (unsigned short)port ); + to.type = NA_BROADCAST; + + net->NetAdrToSockAddr ( &to, &addr ); + + int bytessent = sendto( m_Socket, (const char *)msg->GetData(), msg->GetCurSize(), 0, &addr, sizeof( addr ) ); + if ( bytessent == msg->GetCurSize() ) + { + return bytessent; + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Retrieve internal message buffer +// Output : CMsgBuffer +//----------------------------------------------------------------------------- +CMsgBuffer *CSocket::GetSendBuffer( void ) +{ + return &m_SendBuffer; +} + +//----------------------------------------------------------------------------- +// Purpose: Called once per frame (outside of the socket thread) to allow socket to receive incoming messages +// and route them as appropriate +//----------------------------------------------------------------------------- +void CSocket::Frame( void ) +{ + // No data waiting + if (!m_MsgBuffers.Size()) + return; + + VCRHook_EnterCriticalSection( (CRITICAL_SECTION *)m_pBufferCS ); + + // pass up all the receive buffers + for (int i = 0; i < m_MsgBuffers.Size(); i++) + { + // See if there's a handler for this message + CMsgHandler *handler = m_pMessageHandlers; + netadr_t addr = m_MsgBuffers[i].GetNetAddress(); + while ( handler ) + { + // Swallow message? + if ( handler->ProcessMessage( &addr, &m_MsgBuffers[i] ) ) + break; + + handler = handler->GetNext(); + } + } + + // free the buffer list + m_MsgBuffers.RemoveAll(); + + LeaveCriticalSection((CRITICAL_SECTION *)m_pBufferCS); +} + +//----------------------------------------------------------------------------- +// Purpose: Is socket set up correctly +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CSocket::IsValid( void ) const +{ + return m_bValid; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CSocket::GetClock( void ) +{ + return GetSocketThread()->GetClock(); +} + +//----------------------------------------------------------------------------- +// Purpose: Resolves the socket address +// Output : const netadr_t +//----------------------------------------------------------------------------- +const netadr_t *CSocket::GetAddress( void ) +{ + assert( m_bValid ); + + if ( !m_bResolved ) + { + m_bResolved = true; + // Determine resulting socket address + net->GetSocketAddress( m_Socket, &m_Address ); + } + + return &m_Address; +} + +//----------------------------------------------------------------------------- +// Purpose: Let the user store/retrieve a 32 bit value +// Input : userData - +//----------------------------------------------------------------------------- +void CSocket::SetUserData( unsigned int userData ) +{ + m_nUserData = userData; +} + +//----------------------------------------------------------------------------- +// Purpose: Let the user store/retrieve a 32 bit value +// Output : unsigned int +//----------------------------------------------------------------------------- +unsigned int CSocket::GetUserData(void ) const +{ + return m_nUserData; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the underlying socket id number for setting up the fd_set +//----------------------------------------------------------------------------- +int CSocket::GetSocketNumber( void ) const +{ + return m_Socket; +} + +//----------------------------------------------------------------------------- +// Purpose: Called once FD_ISSET is detected +//----------------------------------------------------------------------------- +bool CSocket::ReceiveData( void ) +{ + // Check for data + struct sockaddr from; + int fromlen; + int bytes; + unsigned char buffer[ CMsgBuffer::NET_MAXMESSAGE ]; + + fromlen = sizeof( from ); + bytes = VCRHook_recvfrom( m_Socket, (char *)buffer, CMsgBuffer::NET_MAXMESSAGE, 0, (struct sockaddr *)&from, &fromlen ); + + //int port = ntohs( ((struct sockaddr_in *)&from)->sin_port); + + // Socket error + if ( bytes == -1 ) + { + return false; + } + + // Too much data, ignore it + if ( bytes >= CMsgBuffer::NET_MAXMESSAGE ) + { + return false; + } + + // Packets must have -1 tag + if ( bytes < 4 ) + { + return false; + } + + // Mark the time no matter what since FD_SET said there was data and we should have it now + float recvTime = GetClock(); + + if( *(int *)&buffer[0] == -2 ) // its a split packet :) + { + int curPacket=0,offset=0; + SPLITPACKET *pak =reinterpret_cast(&buffer[0]); + + if(m_iTotalPackets==0) // this is the first in the series + { + m_iTotalPackets = (pak->packetID & 0x0f); + m_iSeqNo = pak->sequenceNumber; + m_iRetries=0; + + m_iCurrentPackets=1;// packet numbers start at zero, total is the total number (i.e =2 for packet 0,1) + curPacket= (pak->packetID & 0xf0)>>4; + } + else if (m_iSeqNo == pak->sequenceNumber) + { + m_iCurrentPackets++; + curPacket= (pak->packetID & 0xf0)>>4; + } + else + { + m_iRetries++; + if(m_iRetries>MAX_RETRIES) // make sure we give up eventually on fragments + { + m_iTotalPackets=0; + } + return false; // TODO: add support for multiple fragments at one time? + } + + + if(curPacket==0) + { + offset=4; // strip the "-1" at the front of the first packet + } + + if(curPacketSockAddrToNetAdr( &from, &addr ); + + // append to the receive buffer + int idx = m_MsgBuffers.AddToTail(); + CMsgBuffer &msgBuffer = m_MsgBuffers[idx]; + + msgBuffer.Clear(); + + // copy all our fragments together + for(int i=0;iSockAddrToNetAdr( &from, &addr ); + + // append to the receive buffer + int idx = m_MsgBuffers.AddToTail(); + CMsgBuffer &msgBuffer = m_MsgBuffers[idx]; + + // Copy payload minus the -1 tag + msgBuffer.Clear(); + msgBuffer.WriteBuf( bytes - 4, &buffer[ 4 ] ); + msgBuffer.SetTime(recvTime); + msgBuffer.SetNetAddress(addr); + + LeaveCriticalSection((CRITICAL_SECTION *)m_pBufferCS); + } + + return true; +} diff --git a/tracker/common/Socket.h b/tracker/common/Socket.h new file mode 100644 index 0000000..a3d019b --- /dev/null +++ b/tracker/common/Socket.h @@ -0,0 +1,162 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#if !defined( SOCKET_H ) +#define SOCKET_H +#ifdef _WIN32 +#pragma once +#endif + +#include "netadr.h" +#include "MsgBuffer.h" +#include "utlvector.h" + +#include + +class CMsgBuffer; +class CSocket; +class IGameList; + +// Use this to pick apart the network stream, must be packed +#pragma pack(1) +typedef struct +{ + int netID; + int sequenceNumber; + char packetID; +} SPLITPACKET; +#pragma pack() + +#define MAX_PACKETS 16 // 4 bits for the packet count, so only +#define MAX_RETRIES 2 // the number of fragments from other packets to drop before we declare the outstanding + // fragment lost :) + +//----------------------------------------------------------------------------- +// Purpose: Instances a message handler for incoming messages. +//----------------------------------------------------------------------------- +class CMsgHandler +{ +public: + enum + { + MAX_HANDLER_STRING = 64 + }; + + typedef enum + { + MSGHANDLER_ALL = 0, + MSGHANDLER_BYTECODE, + MSGHANDLER_STRING + } HANDLERTYPE; + + // Construction + CMsgHandler( HANDLERTYPE type, void *typeinfo = 0 ); + virtual ~CMsgHandler( void ); + + // Message received, process it + virtual bool Process( netadr_t *from, CMsgBuffer *msg ) = 0; + + // For linking togethr handler chains + virtual CMsgHandler *GetNext( void ) const; + virtual void SetNext( CMsgHandler *next ); + + // Access/set associated socket + virtual CSocket *GetSocket( void ) const; + virtual void SetSocket( CSocket *socket ); + +private: + // Internal message received, crack type info and check it before calling process + bool ProcessMessage( netadr_t *from, CMsgBuffer *msg ); + + // Opaque pointer to underlying recipient class + IGameList *m_pBaseObject; + + // Next handler in chain + HANDLERTYPE m_Type; + unsigned char m_ByteCode; + char m_szString[ MAX_HANDLER_STRING ]; + + // Next handler in chain + CMsgHandler *m_pNext; + // Associated socket + CSocket *m_pSocket; + + friend CSocket; +}; + +//----------------------------------------------------------------------------- +// Purpose: Creates a non-blocking, broadcast capable, UDP socket. If port is +// specified, binds it to listen on that port, otherwise, chooses a random port. +//----------------------------------------------------------------------------- +class CSocket +{ +public: + // Construction/destruction + CSocket( const char *socketname, int port = -1 ); + virtual ~CSocket( void ); + + // Adds the message hander to the head of the sockets handler chain + virtual void AddMessageHandler( CMsgHandler *handler ); + // Removes the specified message handler + virtual void RemoveMessageHandler( CMsgHandler *handler ); + + // Send the message to the recipient, if msg == NULL, use the internal message buffer + virtual int SendMessage( netadr_t *to, CMsgBuffer *msg = NULL ); + // Broadcast the message on the specified port, if msg == NULL use the internal message buffer + virtual int Broadcast( int port, CMsgBuffer *msg = NULL ); + // Get access to the internal message buffer + virtual CMsgBuffer *GetSendBuffer( void ); + // Called once per frame to check for new data + virtual void Frame( void ); + // Check whether the socket was created and set up properly + virtual bool IsValid( void ) const; + // Get the address this socket is bound to + virtual const netadr_t *GetAddress( void ); + + // Allow creating object to store a 32 bit value and retrieve it + virtual void SetUserData( unsigned int userData ); + virtual unsigned int GetUserData(void ) const; + + // Allow other objects to get the raw socket interger + virtual int GetSocketNumber( void ) const; + // Called when FD_ISSET noted that the socket has incoming data + virtual bool ReceiveData( void ); + // Called to get current time + static float GetClock( void ); + +private: + const char *m_pSocketName; + // Socket listen address + bool m_bValid; + // Socket IP address + netadr_t m_Address; + // Has the IP address been resolved + bool m_bResolved; + // Internal message buffers + CUtlVector m_MsgBuffers; + CMsgBuffer m_SendBuffer; + // critical section for accessing buffers + void *m_pBufferCS; + // One or more listeners for the incoming message + CMsgHandler *m_pMessageHandlers; + // Winsock socket number + int m_Socket; + // User 32 bit value + unsigned int m_nUserData; + // Socket to which non Broadcast SendMessage was directed. The socket will wait for a response + // from that exact address + netadr_t m_ToAddress; + // Set to true if the send was a Broadcast, and therefore from != to address is okay + bool m_bBroadcastSend; + + int m_iTotalPackets; // total number of packets in a fragment + int m_iCurrentPackets; // current packet count + int m_iSeqNo; // the sequence number of the packet + int m_iRetries; + CMsgBuffer m_CurPacket[MAX_PACKETS]; // store for the packet +}; + +#endif // SOCKET_H \ No newline at end of file diff --git a/tracker/common/TrackerMessageFlags.h b/tracker/common/TrackerMessageFlags.h new file mode 100644 index 0000000..152539c --- /dev/null +++ b/tracker/common/TrackerMessageFlags.h @@ -0,0 +1,22 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef TRACKERMESSAGEFLAGS_H +#define TRACKERMESSAGEFLAGS_H +#pragma once + +//----------------------------------------------------------------------------- +// Purpose: the set of flags that can modify a message +//----------------------------------------------------------------------------- +enum TrackerMessageFlags_e +{ + MESSAGEFLAG_SYSTEM = 1<<2, // message is from the tracker system + MESSAGEFLAG_MARKETING = 1<<3, // message is from the tracker system +}; + + +#endif // TRACKERMESSAGEFLAGS_H diff --git a/tracker/common/TrackerProtocol.h b/tracker/common/TrackerProtocol.h new file mode 100644 index 0000000..864dd73 --- /dev/null +++ b/tracker/common/TrackerProtocol.h @@ -0,0 +1,161 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Holds all the protocol bits and defines used in tracker networking +// +// $NoKeywords: $ +//============================================================================= + +#ifndef TRACKERPROTOCOL_H +#define TRACKERPROTOCOL_H +#ifdef _WIN32 +#pragma once +#endif + +// failed return versions of the messages are the TMSG_FAIL_OFFSET + 10000 +#define TMSG_FAIL_OFFSET 10000 + +//----------------------------------------------------------------------------- +// Purpose: List of all the tracker messages used +// msgID's are 32bits big +//----------------------------------------------------------------------------- +enum TrackerMsgID_t +{ + // generic messages + TMSG_NONE = 0, // no message id + TMSG_ACK = 1, // packet acknowledgement + + // server -> Client messages + TSVC_BASE = 1000, + + TSVC_CHALLENGE, + TSVC_LOGINOK, + TSVC_LOGINFAIL, + TSVC_DISCONNECT, + TSVC_FRIENDS, + TSVC_FRIENDUPDATE, + TSVC_HEARTBEAT, + TSVC_PINGACK, // acknowledgement of TCLS_PING packet + TSVC_FRIENDINFO, + TSVC_USERVALID, + TSVC_FRIENDSFOUND, + TSVC_NOFRIENDS, + TSVC_MESSAGE, // message passed through from another client + TSVC_GAMEINFO, // information about a friends' game + TSVC_AUTHREQUEST, // a user requesting auth from the receiving user + TSVC_CONNECTIONKEEPALIVE, // information that an attemption connect is taking time, and the user should wait + TSVC_ROUTEMESSAGEFAILED, // chat message failed to be routed through the servers + TSVC_REDIRECTLOGIN, // tells the client to redirect their login attempt to a different server + + // Client -> server messages + TCLS_BASE = 2000, + + TCLS_LOGIN, // login message + TCLS_RESPONSE, // response to login challenge + TCLS_PING, + TCLS_FRIENDSEARCH, + TCLS_HEARTBEAT, + TCLS_AUTHUSER, + TCLS_REQAUTH, + TCLS_FRIENDINFO, // friend info request + TCLS_SETINFO, + TCLS_ROUTETOFRIEND, // generic reroute of a message to a friend + + // Client -> Client messages + TCL_BASE = 3000, + TCL_MESSAGE, // chat text message + TCL_USERBLOCK, // soon to be obselete + TCL_ADDEDTOCHAT, + TCL_CHATADDUSER, + TCL_CHATUSERLEAVE, + TCL_TYPINGMESSAGE, + TCL_FRIENDNETMESSAGE, + + // server -> server messages + TSV_BASE = 4000, + + TSV_WHOISPRIMARY, + TSV_PRIMARYSRV, + TSV_REQUESTINFO, + TSV_TOPOLOGYINFO, + TSV_REQUESTTOPOLOGYINFO, + TSV_SERVERPING, + TSV_MONITORINFO, + TSV_LOCKUSERRANGE, + TSV_UNLOCKUSERRANGE, + TSV_REDIRECTTOUSER, + TSV_FORCEDISCONNECTUSER, + TSV_USERCHECKMESSAGES, + TSV_USERAUTHREQUEST, + TSV_USERSTATUSCHANGED, + TSV_USERRELOADFRIENDSLIST, + TSV_REGISTERSERVERINNETWORK, + TSV_SERVERSHUTTINGDOWN, + TSV_UPDATEACTIVEUSERRANGESTATUS, + + // game server -> Client + TCLG_BASE = 5000, + + // common msg failed ID's + TSVC_HEARTBEAT_FAIL = TSVC_HEARTBEAT + TMSG_FAIL_OFFSET, + + TCLS_HEARTBEAT_FAIL = TCLS_HEARTBEAT + TMSG_FAIL_OFFSET, + + TCL_MESSAGE_FAIL = TCL_MESSAGE + TMSG_FAIL_OFFSET, + +}; + +//----------------------------------------------------------------------------- +// Purpose: List of reasons explaining to user why they have been disconnected +// from the friends network +//----------------------------------------------------------------------------- +enum TrackerLogoffReason_t +{ + TRACKER_LOGOFF_NOREASON, + + // server reasons for disconnecting user + TRACKER_LOGOFF_LOGGEDINELSEWHERE, // user has logged into friends at a different location + TRACKER_LOGOFF_SERVERWORK, // server needs to do work (like lock the user range) + TRACKER_LOGOFF_SERVERSHUTDOWN, // server has been shutdown + TRACKER_LOGOFF_TIMEDOUT, // user hasn't heartbeat'd to server recently enough + TRACKER_LOGOFF_REQUESTED, // user has requested to logoff + TRACKER_LOGOFF_FIREWALL, // users' firewall won't allow enough packets through + TRACKER_LOGOFF_NOTCONNECTED, // user sent server a packet that implied they think they're logged in but they're not + TRACKER_LOGOFF_INVALIDSTEAMTICKET, // users steam ticket is invalid + + // client reasons for being disconnected + TRACKER_LOGOFF_JOINEDGAME, // user has logged off because they joined a game + TRACKER_LOGOFF_CONNECTIONTIMEOUT, // user connection has timed out + TRACKER_LOGOFF_SERVERMESSAGEFAIL, // a message to the server was not successfully transmitted + + TRACKER_LOGOFF_TOOMANYATTEMPTS, // too many login attempts have been performed + TRACKER_LOGOFF_OFFLINE, // steam is in offline mode so don't try to connect +}; + + +//----------------------------------------------------------------------------- +// Purpose: List of all the reasons a login attempt may fail +//----------------------------------------------------------------------------- +enum TrackerLoginFailReason_t +{ + TRACKER_LOGINFAIL_NOREASON = 0, + TRACKER_LOGINFAIL_NOSUCHUSER = -2, + TRACKER_LOGINFAIL_ALREADLOGGEDIN = -3, + TRACKER_LOGINFAIL_INVALIDSTEAMTICKET = -4, + TRACKER_LOGINFAIL_BUILDOUTOFDATE = -5, + TRACKER_LOGINFAIL_PLATFORMOUTOFDATE = -6, +}; + +//----------------------------------------------------------------------------- +// Purpose: Holds basic status for a friend +//----------------------------------------------------------------------------- +struct FriendStatus_t +{ + unsigned int friendID; + int status; + unsigned int sessionID; + unsigned int ip; + unsigned int port; + unsigned int serverID; +}; + +#endif // TRACKERPROTOCOL_H diff --git a/tracker/common/UtlMsgBuffer.cpp b/tracker/common/UtlMsgBuffer.cpp new file mode 100644 index 0000000..7b343bd --- /dev/null +++ b/tracker/common/UtlMsgBuffer.cpp @@ -0,0 +1,332 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "UtlMsgBuffer.h" + +#include + +//----------------------------------------------------------------------------- +// Purpose: bitfields for use in variable descriptors +//----------------------------------------------------------------------------- +enum +{ + PACKBIT_CONTROLBIT = 0x01, // this must always be set + PACKBIT_INTNAME = 0x02, // if this is set then it's an int named variable, instead of a string + PACKBIT_BINARYDATA = 0x04, // signifies the data in this variable is binary, it's not a string +}; + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CUtlMsgBuffer::CUtlMsgBuffer(unsigned short msgID, int initialSize) : m_Memory(0, initialSize) +{ + m_iMsgID = msgID; + m_iWritePos = 0; + m_iReadPos = 0; + m_iNextVarPos = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor, takes initial data +//----------------------------------------------------------------------------- +CUtlMsgBuffer::CUtlMsgBuffer(unsigned short msgID, void const *data, int dataSize) : m_Memory(0, dataSize) +{ + m_iMsgID = msgID; + m_iWritePos = (short)dataSize; + m_iReadPos = 0; + m_iNextVarPos = 0; + + memcpy(Base(), data, dataSize); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CUtlMsgBuffer::~CUtlMsgBuffer() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Copy +//----------------------------------------------------------------------------- +CUtlMsgBuffer &CUtlMsgBuffer::Copy(const CUtlMsgBuffer &rhs) +{ + m_iWritePos = rhs.m_iWritePos; + m_iReadPos = rhs.m_iReadPos; + m_iNextVarPos = rhs.m_iNextVarPos; + + m_Memory.EnsureCapacity(rhs.m_Memory.NumAllocated()); + if ( rhs.m_Memory.NumAllocated() > 0 ) + { + memcpy(Base(), rhs.Base(), rhs.m_Memory.NumAllocated()); + } + return *this; +} + +//----------------------------------------------------------------------------- +// Purpose: Writes string data to the message +// Input : *name - name of the variable +// *data - pointer to the string data to write +//----------------------------------------------------------------------------- +void CUtlMsgBuffer::WriteString(const char *name, const char *data) +{ + // write out the variable type + unsigned char vtype = PACKBIT_CONTROLBIT; // stringname var, string data + Write(&vtype, 1); + + // write out the variable name + Write(name, strlen(name) + 1); + + // write out the size of the data + unsigned short size = (unsigned short)(strlen(data) + 1); + Write(&size, 2); + + // write out the data itself + Write(data, size); +} + +//----------------------------------------------------------------------------- +// Purpose: Writes out a named block of data +//----------------------------------------------------------------------------- +void CUtlMsgBuffer::WriteBlob(const char *name, const void *data, int dataSize) +{ + // write out the variable type + unsigned char vtype = PACKBIT_CONTROLBIT | PACKBIT_BINARYDATA; // stringname var, binary data + Write(&vtype, 1); + + // write out the variable name + Write(name, strlen(name) + 1); + + // write out the size of the data + unsigned short size = (unsigned short)dataSize; + Write(&size, 2); + + // write out the data itself + Write(data, dataSize); +} + +//----------------------------------------------------------------------------- +// Purpose: Writes out another UtlMsgBuffer as an element of this one +//----------------------------------------------------------------------------- +void CUtlMsgBuffer::WriteBuffer(const char *name, const CUtlMsgBuffer *buffer) +{ + // write out the variable type + unsigned char vtype = PACKBIT_CONTROLBIT | PACKBIT_BINARYDATA; // stringname var, binary data + Write(&vtype, 1); + + // write out the variable name + Write(name, strlen(name) + 1); + + // write out the size of the data + unsigned short size = (unsigned short) buffer->DataSize(); + Write(&size, 2); + + // write out the data itself + Write(buffer->Base(), size); +} + +//----------------------------------------------------------------------------- +// Purpose: Reads from the buffer, increments read position +// returns false if past end of buffer +//----------------------------------------------------------------------------- +bool CUtlMsgBuffer::Read(void *buffer, int readAmount) +{ + if (m_iReadPos + readAmount >= m_iWritePos) + return false; + + memcpy(buffer, &m_Memory[m_iReadPos], readAmount); + m_iReadPos += readAmount; + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Reads characterse from the buffer until a null is hit +//----------------------------------------------------------------------------- +bool CUtlMsgBuffer::ReadUntilNull(void *buffer, int bufferSize) +{ + int nullPos = m_iReadPos; + + // look through the buffer for the null terminator + while (nullPos < m_Memory.NumAllocated() && m_Memory[nullPos] != 0) + { + nullPos++; + } + + if (nullPos >= m_Memory.NumAllocated()) + { + // never found a null terminator + ((char *)buffer)[0] = 0; + return false; + } + + // copy from the null terminator + int copySize = nullPos - m_iReadPos; + if (copySize > bufferSize) + { + copySize = bufferSize - 1; + } + + // copy out the data and return + memcpy(buffer, &m_Memory[m_iReadPos], copySize); + ((char *)buffer)[copySize] = 0; + m_iReadPos += (copySize+1); + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Writes to the buffer, incrementing the write position +// assumes enough space has already been allocated for the write +//----------------------------------------------------------------------------- +void CUtlMsgBuffer::Write(void const *data, int size) +{ + // make sure it will fit + m_Memory.EnsureCapacity(m_iWritePos + size); + + // normal write + memcpy(&m_Memory[m_iWritePos], data, size); + + // increment write position + m_iWritePos += size; +} + +//----------------------------------------------------------------------------- +// Purpose: Reads in a named variable length data blob +// returns number of bytes read, 0 on failure +//----------------------------------------------------------------------------- +int CUtlMsgBuffer::ReadBlob(const char *name, void *data, int dataBufferSize) +{ + int dataSize = 0; + char *readData = (char *)FindVar(name, dataSize); + if (!readData) + { + memset(data, 0, dataBufferSize); + return 0; + } + + // ensure against buffer overflow + if (dataSize > dataBufferSize) + dataSize = dataBufferSize; + + // copy out data + memcpy(data, readData, dataSize); + return dataSize; +} + +//----------------------------------------------------------------------------- +// Purpose: Reads a blob of binary data into it's own buffer +//----------------------------------------------------------------------------- +bool CUtlMsgBuffer::ReadBuffer(const char *name, CUtlMsgBuffer &buffer) +{ + int dataSize = 0; + char *readData = (char *)FindVar(name, dataSize); + if (!readData) + { + return false; + } + + buffer.m_Memory.EnsureCapacity(dataSize); + memcpy(&buffer.m_Memory[0], readData, dataSize); + buffer.m_iReadPos = 0; + buffer.m_iWritePos = (short)dataSize; + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: reads out the next variable available in the buffer +// fills out parameters with var details and data +// returns false if no more vars available +//----------------------------------------------------------------------------- +bool CUtlMsgBuffer::ReadNextVar(char varname[32], bool &stringData, void *data, int &dataSize) +{ + // read the type + unsigned char vtype = 1; + if (!Read(&vtype, 1)) + return false; + + // check for null-termination type + if (vtype == 0) + return false; + + stringData = !(vtype & PACKBIT_BINARYDATA); + + // read the variable name + if (!ReadUntilNull(varname, 31)) + return false; + + // read the data size + unsigned short size = 0; + if (!Read(&size, 2)) + return false; + + // ensure against buffer overflows + if (dataSize > size) + dataSize = size; + + // copy data + memcpy(data, &m_Memory[m_iReadPos], dataSize); + + // store of the next position, since that is probably where the next read needs to occur + m_iReadPos += size; + m_iNextVarPos = m_iReadPos; + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: sets the read/write position to be at the specified variable +// returns pointer to buffer position on success, NULL if not found +//----------------------------------------------------------------------------- +void *CUtlMsgBuffer::FindVar(const char *name, int &dataSize) +{ + // reset to where we Think the next var will be read from + m_iReadPos = m_iNextVarPos; + int loopCount = 2; + + // loop through looking for the specified variable + while (loopCount--) + { + unsigned char vtype = 1; + while (Read(&vtype, 1)) + { + // check for null-termination type + if (vtype == 0) + break; + + // read the variable name + char varname[32]; + if (!ReadUntilNull(varname, 31)) + break; + + // read the data size + unsigned short size = 0; + if (!Read(&size, 2)) + break; + + // is this our variable? + if (!stricmp(varname, name)) + { + dataSize = size; + void *data = &m_Memory[m_iReadPos]; + + // store of the next position, since that is probably where the next read needs to occur + m_iReadPos += size; + m_iNextVarPos = m_iReadPos; + return data; + } + + // skip over the data block to the next variable + m_iReadPos += size; + if (m_iReadPos >= m_iWritePos) + break; + } + + // we haven't found the data yet, Start again + m_iReadPos = 0; + } + + return NULL; +} diff --git a/tracker/common/UtlMsgBuffer.h b/tracker/common/UtlMsgBuffer.h new file mode 100644 index 0000000..0f4e555 --- /dev/null +++ b/tracker/common/UtlMsgBuffer.h @@ -0,0 +1,198 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Generic named data buffer, declaration and implementation +// +//============================================================================= + +#ifndef UTLMSGBUFFER_H +#define UTLMSGBUFFER_H +#ifdef _WIN32 +#pragma once +#endif + +#include "UtlMemory.h" + +#pragma warning(disable: 4244) // warning C4244: '=' : conversion from 'int' to 'short', possible loss of data + +//----------------------------------------------------------------------------- +// Purpose: Generic named data buffer +//----------------------------------------------------------------------------- +class CUtlMsgBuffer +{ +public: + CUtlMsgBuffer(unsigned short msgID, int initialSize); + CUtlMsgBuffer(unsigned short msgID, void const *data, int dataSize); + ~CUtlMsgBuffer(); + + unsigned short GetMsgID() const { return m_iMsgID; } + void SetMsgID(unsigned short msgID) { m_iMsgID = msgID; } + + // read functions + bool ReadInt(const char *name, int &data); + bool ReadUInt(const char *name, unsigned int &data); + bool ReadString(const char *name, char *data, int dataBufferSize); + bool ReadBuffer(const char *name, CUtlMsgBuffer &buffer); + // returns number of bytes read, 0 on failure + int ReadBlob(const char *name, void *data, int dataBufferSize); + + // reads out the next variable available in the buffer + // fills out parameters with var details and data + // returns false if no more vars available + bool ReadNextVar(char name[32], bool &stringData, void *data, int &dataSize); + + // write functions + void WriteInt(const char *name, int data); + void WriteUInt(const char *name, unsigned int data); + void WriteString(const char *name, const char *data); + void WriteBlob(const char *name, const void *data, int dataSize); + void WriteBuffer(const char *name, const CUtlMsgBuffer *buffer); + + // returns a pointer to the data buffer, and its size, of the specified variable + void *FindVar(const char *name, int &dataSizeOut); + + // pads the buffer to the specified boundary (in bytes) + void PadBuffer(int boundary); + + // makes sure the message has this much space allocated + void EnsureCapacity(int dataSize); + + // returns the number of bytes used by the message + int DataSize() const; + + // returns a pointer to the base data + void *Base(); + + // returns a const pointer to the base data + const void *Base() const; + + // advances the write pointer - used when you write directly into the buffer + void SetWritePos(int size); + + CUtlMsgBuffer& Copy(const CUtlMsgBuffer &rhs); + + // copy constructor + CUtlMsgBuffer(const CUtlMsgBuffer &rhs) + { + m_iMsgID = rhs.m_iMsgID; + m_iWritePos = rhs.m_iWritePos; + m_iReadPos = rhs.m_iReadPos; + m_iNextVarPos = rhs.m_iNextVarPos; + + m_Memory.EnsureCapacity(rhs.m_Memory.NumAllocated()); + if ( rhs.m_Memory.NumAllocated() > 0 ) + { + memcpy(Base(), rhs.Base(), rhs.m_Memory.NumAllocated()); + } + } + +private: + + bool Read(void *buffer, int readAmount); + bool ReadUntilNull(void *buffer, int bufferSize); + void Write(void const *data, int size); + + CUtlMemory m_Memory; + + unsigned short m_iMsgID; + short m_iWritePos; // position in buffer we are currently writing to + short m_iReadPos; // current reading position + short m_iNextVarPos; // a guess at which variable is most likely to be read next +}; + +//----------------------------------------------------------------------------- +// Purpose: returns the number of bytes used by the message +//----------------------------------------------------------------------------- +inline int CUtlMsgBuffer::DataSize() const +{ + // return the highest read/write mark + if (m_iWritePos > m_iReadPos) + return m_iWritePos; + + return m_iReadPos; +} + +//----------------------------------------------------------------------------- +// Purpose: returns a pointer to the base data +//----------------------------------------------------------------------------- +inline void *CUtlMsgBuffer::Base() +{ + return &m_Memory[0]; +} + +//----------------------------------------------------------------------------- +// Purpose: returns a pointer to the base data +//----------------------------------------------------------------------------- +inline const void *CUtlMsgBuffer::Base() const +{ + return &m_Memory[0]; +} + +//----------------------------------------------------------------------------- +// Purpose: ensures capacity +//----------------------------------------------------------------------------- +inline void CUtlMsgBuffer::EnsureCapacity(int dataSize) +{ + m_Memory.EnsureCapacity(dataSize); +} + +//----------------------------------------------------------------------------- +// Purpose: pads the buffer to the specified boundary (in bytes) +//----------------------------------------------------------------------------- +inline void CUtlMsgBuffer::PadBuffer(int boundary) +{ + // pad the buffer to be the right size for encryption + int pad = (boundary - (DataSize() % boundary)); + Write("\0\0\0\0\0\0\0\0\0\0\0\0", pad); +} + +//----------------------------------------------------------------------------- +// Purpose: Reads in a named 4-byte int, returns true on sucess, false on failure +//----------------------------------------------------------------------------- +inline bool CUtlMsgBuffer::ReadInt(const char *name, int &data) +{ + return (ReadBlob(name, &data, 4) == 4); +} + +//----------------------------------------------------------------------------- +// Purpose: Reads in a named 4-byte unsigned int, returns true on sucess, false on failure +//----------------------------------------------------------------------------- +inline bool CUtlMsgBuffer::ReadUInt(const char *name, unsigned int &data) +{ + return (ReadBlob(name, &data, 4) == 4); +} + +//----------------------------------------------------------------------------- +// Purpose: Reads in a named variable length character string +// returns true on sucess, false on failure +//----------------------------------------------------------------------------- +inline bool CUtlMsgBuffer::ReadString(const char *name, char *data, int dataBufferSize) +{ + return (ReadBlob(name, data, dataBufferSize) > 0); +} + +//----------------------------------------------------------------------------- +// Purpose: Writes out an integer to the message +//----------------------------------------------------------------------------- +inline void CUtlMsgBuffer::WriteInt(const char *name, int data) +{ + WriteBlob(name, &data, 4); +} + +//----------------------------------------------------------------------------- +// Purpose: Writes out an unsigned integer to the message +//----------------------------------------------------------------------------- +inline void CUtlMsgBuffer::WriteUInt(const char *name, unsigned int data) +{ + WriteBlob(name, &data, 4); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline void CUtlMsgBuffer::SetWritePos(int size) +{ + m_iWritePos = size; +} + + +#endif // UTLMSGBUFFER_H diff --git a/tracker/common/inetapi.h b/tracker/common/inetapi.h new file mode 100644 index 0000000..80575a7 --- /dev/null +++ b/tracker/common/inetapi.h @@ -0,0 +1,42 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#if !defined( INETAPI_H ) +#define INETAPI_H +#ifdef _WIN32 +#pragma once +#endif + +#include "netadr.h" + +//----------------------------------------------------------------------------- +// Purpose: Internal winsock helpers for launcher +//----------------------------------------------------------------------------- +class INetAPI +{ +public: + // Convert a netadr_t to sockaddr + virtual void NetAdrToSockAddr( netadr_t *a, struct sockaddr *s ) = 0; + // Convert a sockaddr to netadr_t + virtual void SockAddrToNetAdr( struct sockaddr *s, netadr_t *a ) = 0; + + // Convert a netadr_t to a string + virtual char *AdrToString( netadr_t *a ) = 0; + // Convert a string address to a netadr_t, doing DNS if needed + virtual bool StringToAdr( const char *s, netadr_t *a ) = 0; + // Look up IP address for socket + virtual void GetSocketAddress( int socket, netadr_t *a ) = 0; + + virtual bool CompareAdr( netadr_t *a, netadr_t *b ) =0; + + // return the IP of the local host + virtual void GetLocalIP(netadr_t *a)=0; + +}; + +extern INetAPI *net; + +#endif // INETAPI_H \ No newline at end of file diff --git a/tracker/common/msgbuffer.cpp b/tracker/common/msgbuffer.cpp new file mode 100644 index 0000000..d7cf40a --- /dev/null +++ b/tracker/common/msgbuffer.cpp @@ -0,0 +1,421 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#include +#include +#include "msgbuffer.h" +// memdbgon must be the last include file in a .cpp file!!! +#include + +#pragma warning(disable: 4244) // warning C4244: '=' : conversion from 'int' to 'unsigned char', possible loss of data + +//----------------------------------------------------------------------------- +// Purpose: Allocate message buffer +// Input : *buffername - +// *ef - +//----------------------------------------------------------------------------- +CMsgBuffer::CMsgBuffer( const char *buffername, void (*ef)( const char *fmt, ... ) /*= NULL*/ ) +{ + m_pszBufferName = buffername; + m_pfnErrorFunc = ef; + m_bAllowOverflow = false; // if false, Error + m_bOverFlowed = false; // set to true if the buffer size failed + m_nMaxSize = NET_MAXMESSAGE; + m_nPushedCount = 0; + m_bPushed = false; + m_nReadCount = 0; + m_bBadRead = false; + + Clear(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CMsgBuffer::~CMsgBuffer( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Temporarily remember the read position so we can reset it +//----------------------------------------------------------------------------- +void CMsgBuffer::Push( void ) +{ + // ??? Allow multiple pushes without matching pops ??? + assert( !m_bPushed ); + + m_nPushedCount = m_nReadCount; + m_bPushed = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMsgBuffer::Pop( void ) +{ + assert( m_bPushed ); + + m_nReadCount = m_nPushedCount; + m_bPushed = false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : allowed - +//----------------------------------------------------------------------------- +void CMsgBuffer::SetOverflow( bool allowed ) +{ + m_bAllowOverflow = allowed; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CMsgBuffer::GetMaxSize( void ) +{ + return m_nMaxSize; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : void * +//----------------------------------------------------------------------------- +void * CMsgBuffer::GetData( void ) +{ + return m_rgData; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CMsgBuffer::GetCurSize( void ) +{ + return m_nCurSize; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CMsgBuffer::GetReadCount( void ) +{ + return m_nReadCount; +} + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +void CMsgBuffer::SetTime(float time) +{ + m_fRecvTime = time; +} + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +float CMsgBuffer::GetTime() +{ + return m_fRecvTime; +} + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +void CMsgBuffer::SetNetAddress(netadr_t &adr) +{ + m_NetAddr = adr; +} + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +netadr_t &CMsgBuffer::GetNetAddress() +{ + return m_NetAddr; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMsgBuffer::WriteByte( int c ) +{ + unsigned char *buf; + buf = (unsigned char *)GetSpace( 1 ); + buf[0] = c; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : c - +//----------------------------------------------------------------------------- +void CMsgBuffer::WriteShort ( int c ) +{ + unsigned char *buf; + buf = (unsigned char *)GetSpace( 2 ); + buf[0] = c&0xff; + buf[1] = c>>8; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : c - +//----------------------------------------------------------------------------- +void CMsgBuffer::WriteLong (int c) +{ + unsigned char *buf; + + buf = (unsigned char *)GetSpace( 4 ); + buf[0] = c&0xff; + buf[1] = (c>>8)&0xff; + buf[2] = (c>>16)&0xff; + buf[3] = c>>24; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : f - +//----------------------------------------------------------------------------- +void CMsgBuffer::WriteFloat (float f) +{ + union + { + float f; + int l; + } dat; + + dat.f = f; + Write( &dat.l, 4 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *s - +//----------------------------------------------------------------------------- +void CMsgBuffer::WriteString (const char *s) +{ + if ( !s ) + { + Write ("", 1); + } + else + { + Write ( s, strlen( s ) + 1 ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : iSize - +// *buf - +//----------------------------------------------------------------------------- +void CMsgBuffer::WriteBuf( int iSize, void *buf ) +{ + if ( !buf ) + { + return; + } + + Write( buf, iSize ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMsgBuffer::BeginReading (void) +{ + m_nReadCount = 0; + m_bBadRead = false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int CMsgBuffer::ReadByte +//----------------------------------------------------------------------------- +int CMsgBuffer::ReadByte (void) +{ + int c; + + if ( m_nReadCount + 1 > m_nCurSize ) + { + m_bBadRead = true; + return -1; + } + + c = ( unsigned char )m_rgData[ m_nReadCount ]; + m_nReadCount++; + return c; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int CMsgBuffer::ReadShort +//----------------------------------------------------------------------------- +int CMsgBuffer::ReadShort (void) +{ + int c; + + if ( m_nReadCount + 2 > m_nCurSize ) + { + m_bBadRead = true; + return -1; + } + + c = (short)(m_rgData[m_nReadCount] + (m_rgData[m_nReadCount+1]<<8)); + m_nReadCount += 2; + + return c; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int CMsgBuffer::ReadLong +//----------------------------------------------------------------------------- +int CMsgBuffer::ReadLong (void) +{ + int c; + + if (m_nReadCount+4 > m_nCurSize) + { + m_bBadRead = true; + return -1; + } + + c = m_rgData[m_nReadCount] + + (m_rgData[m_nReadCount+1]<<8) + + (m_rgData[m_nReadCount+2]<<16) + + (m_rgData[m_nReadCount+3]<<24); + + m_nReadCount += 4; + + return c; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float CMsgBuffer::ReadFloat +//----------------------------------------------------------------------------- +float CMsgBuffer::ReadFloat (void) +{ + union + { + unsigned char b[4]; + float f; + } dat; + + dat.b[0] = m_rgData[m_nReadCount]; + dat.b[1] = m_rgData[m_nReadCount+1]; + dat.b[2] = m_rgData[m_nReadCount+2]; + dat.b[3] = m_rgData[m_nReadCount+3]; + m_nReadCount += 4; + return dat.f; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : iSize - +// *pbuf - +// Output : int +//----------------------------------------------------------------------------- +int CMsgBuffer::ReadBuf( int iSize, void *pbuf ) +{ + if (m_nReadCount + iSize > m_nCurSize) + { + m_bBadRead = true; + return -1; + } + + memcpy( pbuf, &m_rgData[m_nReadCount], iSize ); + m_nReadCount += iSize; + + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : char * +//----------------------------------------------------------------------------- +char *CMsgBuffer::ReadString (void) +{ + static char string[ NET_MAXMESSAGE ]; + int l,c; + + l = 0; + do + { + c = (char)ReadByte(); + if ( c == -1 || c == 0 ) + break; + string[l] = c; + l++; + } while ( l < sizeof(string)-1 ); + + string[ l ] = 0; + + return string; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMsgBuffer::Clear( void ) +{ + m_nCurSize = 0; + m_bOverFlowed = false; + m_nReadCount = 0; + m_bBadRead = false; + memset( m_rgData, 0, sizeof( m_rgData ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : length - +//----------------------------------------------------------------------------- +void *CMsgBuffer::GetSpace( int length ) +{ + void *d; + + if (m_nCurSize + length > m_nMaxSize) + { + if ( !m_bAllowOverflow ) + { + if ( m_pfnErrorFunc ) + { + ( *m_pfnErrorFunc )( "CMsgBuffer(%s), no room for %i bytes, %i / %i already in use\n", + m_pszBufferName, length, m_nCurSize, m_nMaxSize ); + } + return NULL; + } + + if (length > m_nMaxSize) + { + if ( m_pfnErrorFunc ) + { + ( *m_pfnErrorFunc )( "CMsgBuffer(%s), no room for %i bytes, %i is max\n", + m_pszBufferName, length, m_nMaxSize ); + } + return NULL; + } + + m_bOverFlowed = true; + Clear(); + } + + d = m_rgData + m_nCurSize; + m_nCurSize += length; + return d; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *m_rgData - +// length - +//----------------------------------------------------------------------------- +void CMsgBuffer::Write(const void *m_rgData, int length) +{ + memcpy( GetSpace(length), m_rgData, length ); +} \ No newline at end of file diff --git a/tracker/common/msgbuffer.h b/tracker/common/msgbuffer.h new file mode 100644 index 0000000..b039ec6 --- /dev/null +++ b/tracker/common/msgbuffer.h @@ -0,0 +1,108 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#if !defined( MSGBUFFER_H ) +#define MSGBUFFER_H +#ifdef _WIN32 +#pragma once +#endif + +#include "netadr.h" + +//----------------------------------------------------------------------------- +// Purpose: Generic byte level message buffer with read/write support +//----------------------------------------------------------------------------- +class CMsgBuffer +{ +public: + enum + { + NET_MAXMESSAGE = 8192 + }; + + // Buffers must be named + CMsgBuffer( const char *buffername = "unnamed", void (*ef)( PRINTF_FORMAT_STRING const char *fmt, ... ) = 0 ); + virtual ~CMsgBuffer( void ); + + // Reset the buffer for writing + void Clear( void ); + // Get current # of bytes + int GetCurSize( void ); + // Get max # of bytes + int GetMaxSize( void ); + // Get pointer to raw data + void *GetData( void ); + // Set/unset the allow overflow flag + void SetOverflow( bool allowed ); + // Start reading from buffer + void BeginReading( void ); + // Get current read byte + int GetReadCount( void ); + + // Push read count ( to peek at data ) + void Push( void ); + void Pop( void ); + + // Writing functions + void WriteByte(int c); + void WriteShort(int c); + void WriteLong(int c); + void WriteFloat(float f); + void WriteString(const char *s); + void WriteBuf( int iSize, void *buf ); + + // Reading functions + int ReadByte( void ); + int ReadShort( void ); + int ReadLong( void ); + float ReadFloat( void ); + char *ReadString( void ); + int ReadBuf( int iSize, void *pbuf ); + + // setting and storing time received + void SetTime(float time); + float GetTime(); + + // net address received from + void SetNetAddress(netadr_t &adr); + netadr_t &GetNetAddress(); + +private: + // Ensures sufficient space to append an object of length + void *GetSpace( int length ); + // Copy buffer in at current writing point + void Write( const void *data, int length ); + +private: + // Name of buffer in case of debugging/errors + const char *m_pszBufferName; + // Optional error callback + void ( *m_pfnErrorFunc )( PRINTF_FORMAT_STRING const char *fmt, ... ); + + // Current read pointer + int m_nReadCount; + // Push/pop read state + int m_nPushedCount; + bool m_bPushed; + // Did we hit the end of the read buffer? + bool m_bBadRead; + // Max size of buffer + int m_nMaxSize; + // Current bytes written + int m_nCurSize; + // if false, call m_pfnErrorFunc + bool m_bAllowOverflow; + // set to true when buffer hits end + bool m_bOverFlowed; + // Internal storage + unsigned char m_rgData[ NET_MAXMESSAGE ]; + // time received + float m_fRecvTime; + // address received from + netadr_t m_NetAddr; +}; + +#endif // !MSGBUFFER_H \ No newline at end of file diff --git a/tracker/common/netapi.cpp b/tracker/common/netapi.cpp new file mode 100644 index 0000000..5373571 --- /dev/null +++ b/tracker/common/netapi.cpp @@ -0,0 +1,277 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#include +#include +#if defined( WIN32 ) +#if !defined( _X360 ) +#include "winsock.h" +#else +#include "winsockx.h" +#endif +#elif defined( POSIX ) +#include +#include +#include +#include +#include +#else +#error +#endif +#include "inetapi.h" + +#if defined( _X360 ) +#include "xbox/xbox_win32stubs.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include +#pragma warning(disable: 4706) // warning C4706: assignment within conditional expression + +//----------------------------------------------------------------------------- +// Purpose: Implements INetAPI +//----------------------------------------------------------------------------- +class CNetAPI : public INetAPI +{ +public: + virtual void NetAdrToSockAddr( netadr_t *a, struct sockaddr *s ); + virtual void SockAddrToNetAdr( struct sockaddr *s, netadr_t *a ); + + virtual char *AdrToString( netadr_t *a ); + virtual bool StringToAdr( const char *s, netadr_t *a ); + + virtual void GetSocketAddress( int socket, netadr_t *a ); + + virtual bool CompareAdr( netadr_t *a, netadr_t *b ); + + virtual void GetLocalIP(netadr_t *a); +}; + +// Expose interface +static CNetAPI g_NetAPI; +INetAPI *net = ( INetAPI * )&g_NetAPI; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *a - +// *s - +//----------------------------------------------------------------------------- +void CNetAPI::NetAdrToSockAddr (netadr_t *a, struct sockaddr *s) +{ + memset (s, 0, sizeof(*s)); + + if (a->type == NA_BROADCAST) + { + ((struct sockaddr_in *)s)->sin_family = AF_INET; + ((struct sockaddr_in *)s)->sin_port = a->port; + ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; + } + else if (a->type == NA_IP) + { + ((struct sockaddr_in *)s)->sin_family = AF_INET; + ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip; + ((struct sockaddr_in *)s)->sin_port = a->port; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *s - +// *a - +//----------------------------------------------------------------------------- +void CNetAPI::SockAddrToNetAdr( struct sockaddr *s, netadr_t *a ) +{ + if (s->sa_family == AF_INET) + { + a->type = NA_IP; + *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr; + a->port = ((struct sockaddr_in *)s)->sin_port; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *a - +// Output : char +//----------------------------------------------------------------------------- +char *CNetAPI::AdrToString( netadr_t *a ) +{ + static char s[64]; + + memset(s, 0, 64); + + if ( a ) + { + if ( a->type == NA_LOOPBACK ) + { + sprintf (s, "loopback"); + } + else if ( a->type == NA_IP ) + { + sprintf(s, "%i.%i.%i.%i:%i", a->ip[0], a->ip[1], a->ip[2], a->ip[3], ntohs( a->port ) ); + } + } + return s; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *s - +// *sadr - +// Output : static bool +//----------------------------------------------------------------------------- +static bool StringToSockaddr( const char *s, struct sockaddr *sadr ) +{ + struct hostent *h; + char *colon; + char copy[128]; + struct sockaddr_in *p; + + memset (sadr, 0, sizeof(*sadr)); + + p = ( struct sockaddr_in * )sadr; + p->sin_family = AF_INET; + p->sin_port = 0; + + strcpy (copy, s); + + // strip off a trailing :port if present + for ( colon = copy ; *colon ; colon++ ) + { + if (*colon == ':') + { + // terminate + *colon = 0; + // Start at next character + p->sin_port = htons( ( short )atoi( colon + 1 ) ); + } + } + + // Numeric IP, no DNS + if ( copy[0] >= '0' && copy[0] <= '9' && strstr( copy, "." ) ) + { + *(int *)&p->sin_addr = inet_addr( copy ); + } + else + { + // DNS it + if ( !( h = gethostbyname( copy ) ) ) + { + return false; + } + // Use first result + *(int *)&p->sin_addr = *(int *)h->h_addr_list[0]; + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *s - +// *a - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CNetAPI::StringToAdr( const char *s, netadr_t *a ) +{ + struct sockaddr sadr; + + if ( !strcmp ( s, "localhost" ) ) + { + memset ( a, 0, sizeof( *a ) ); + a->type = NA_LOOPBACK; + return true; + } + + if ( !StringToSockaddr (s, &sadr) ) + { + return false; + } + + SockAddrToNetAdr( &sadr, a ); + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Lookup the IP address for the specified IP socket +// Input : socket - +// *a - +//----------------------------------------------------------------------------- +void CNetAPI::GetSocketAddress( int socket, netadr_t *a ) +{ + char buff[512]; + struct sockaddr_in address; + int namelen; +// int net_error = 0; + + memset( a, 0, sizeof( *a ) ); + gethostname(buff, 512); + // Ensure that it doesn't overrun the buffer + buff[512-1] = 0; + + StringToAdr(buff, a ); + + namelen = sizeof(address); + if ( getsockname( socket, (struct sockaddr *)&address, (int *)&namelen) == 0 ) + { + a->port = address.sin_port; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Full IP address compare +// Input : *a - +// *b - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CNetAPI::CompareAdr( netadr_t *a, netadr_t *b ) +{ + if ( a->type != b->type ) + { + return false; + } + + if ( a->type == NA_LOOPBACK ) + { + return true; + } + + if ( a->type == NA_IP && + a->ip[0] == b->ip[0] && + a->ip[1] == b->ip[1] && + a->ip[2] == b->ip[2] && + a->ip[3] == b->ip[3] && + a->port == b->port ) + { + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Full IP address compare +// Input : *a - +// *b - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- + +void CNetAPI::GetLocalIP(netadr_t *a) +{ + char s[64]; + + if(!::gethostname(s,64)) + { + struct hostent *localip = ::gethostbyname(s); + if(localip) + { + a->type=NA_IP; + a->port=0; + memcpy(a->ip,localip->h_addr_list[0],4); + } + } +} diff --git a/tracker/common/server.h b/tracker/common/server.h new file mode 100644 index 0000000..255197c --- /dev/null +++ b/tracker/common/server.h @@ -0,0 +1,51 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef SERVER_H +#define SERVER_H + +#ifdef _WIN32 +#pragma once +#endif + +//----------------------------------------------------------------------------- +// Purpose: Data describing a single server +//----------------------------------------------------------------------------- +struct serveritem_t +{ + serveritem_t() + { + pings[0] = 0; + pings[1] = 0; + pings[2] = 0; + } + + unsigned char ip[4]; + int port; + int received; + float time; + int ping; // current ping time, derived from pings[] + int pings[3]; // last 3 ping times + bool hadSuccessfulResponse; // server has responded successfully in the past + bool doNotRefresh; // server is marked as not responding and should no longer be refreshed + char gameDir[32]; // current game directory + char map[32]; // current map + char gameDescription[64]; // game description + char name[64]; // server name + int players; + int maxPlayers; + int botPlayers; + bool proxy; + bool password; + unsigned int serverID; + int listEntryID; + char rconPassword[64]; // the rcon password for this server + bool loadedFromFile; // true if this entry was loaded from file rather than comming from the master +}; + + +#endif // SERVER_H diff --git a/tracker/common/util.cpp b/tracker/common/util.cpp new file mode 100644 index 0000000..8b73f67 --- /dev/null +++ b/tracker/common/util.cpp @@ -0,0 +1,70 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "util.h" +#include + +#define NUM_BUFFERS 4 +#define MAX_INFO_TOKEN_LENGTH 512 +const char *CUtil::InfoGetValue( const char *s, const char *key ) +{ + char pkey[MAX_INFO_TOKEN_LENGTH]; + // Use multiple buffers so compares + // work without stomping on each other + static char value[NUM_BUFFERS][MAX_INFO_TOKEN_LENGTH]; + static int valueindex; + char *o; + + valueindex = (valueindex + 1) % NUM_BUFFERS; + + if (*s == '\\') + s++; + while (1) + { + o = pkey; + while (*s != '\\') + { + if (!*s) + return ""; + *o++ = *s++; + } + *o = 0; + s++; + + o = value[valueindex]; + + while (*s != '\\' && *s) + { + if (!*s) + return ""; + *o++ = *s++; + } + *o = 0; + + if (!strcmp (key, pkey) ) + return value[valueindex]; + + if (!*s) + return ""; + s++; + } +} + +//----------------------------------------------------------------------------- +// Purpose: This function is supposed to localise the strings, but for now just return internal value +// Input : *stringName - +// Output : const char +//----------------------------------------------------------------------------- +const char *CUtil::GetString(const char *stringName) +{ + return stringName; +} + +static CUtil g_Util; +CUtil *util = &g_Util; + + diff --git a/tracker/common/util.h b/tracker/common/util.h new file mode 100644 index 0000000..24d04ee --- /dev/null +++ b/tracker/common/util.h @@ -0,0 +1,29 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef UTIL_H +#define UTIL_H +#ifdef _WIN32 +#pragma once +#endif + +//----------------------------------------------------------------------------- +// Purpose: Utility function for the server browser +//----------------------------------------------------------------------------- +class CUtil +{ +public: + const char *InfoGetValue(const char *s, const char *key); + const char *GetString(const char *stringName); + +}; + +extern CUtil *util; + + + +#endif // UTIL_H diff --git a/vpc_scripts/groups.vgc b/vpc_scripts/groups.vgc index da0e250..f89cfea 100644 --- a/vpc_scripts/groups.vgc +++ b/vpc_scripts/groups.vgc @@ -25,6 +25,9 @@ $Group "game" "engine" "materialsystem" "particles" + "launcher" + "launcher_main" + "gameui" "scenefilecache" "studiorender" "shaderapidx9" @@ -71,6 +74,9 @@ $Group "everything" "particles" "raytrace" "qc_eyes" + "launcher" + "launcher_main" + "gameui" "server" "serverplugin_empty" "scenefilecache" diff --git a/vpc_scripts/projects.vgc b/vpc_scripts/projects.vgc index 702601b..6c3a70c 100644 --- a/vpc_scripts/projects.vgc +++ b/vpc_scripts/projects.vgc @@ -37,11 +37,21 @@ $Project "glview" "utils\glview\glview.vpc" [$WIN32] } -$Project "coolsource" //this is the launcher +$Project "launcher" { "launcher\launcher.vpc" } +$Project "launcher_main" +{ + "launcher_main\launcher_main.vpc" +} + +$Project "gameui" +{ + "gameui\gameui.vpc" +} + $Project "height2normal" { "utils\height2normal\height2normal.vpc" [$WIN32] diff --git a/vpc_scripts/source_saxxyawards.vpc b/vpc_scripts/source_saxxyawards.vpc new file mode 100644 index 0000000..53e80e8 --- /dev/null +++ b/vpc_scripts/source_saxxyawards.vpc @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// SOURCE_SAXXYAWARDS.VPC +// +// Turn the macro on to enable the Saxxy awards main menu UI and music. +// +//----------------------------------------------------------------------------- + +$Macro SAXXYAWARDS_ENABLE 0 + +//----------------------------------------------------------------------------- + +$Configuration +{ + $Compiler + { + $PreprocessorDefinitions "$BASE;SAXXYMAINMENU_ENABLED" [$SAXXYAWARDS_ENABLE] + } +}