From: ShadowFlare Date: Wed, 29 Mar 2006 19:26:45 +0000 (+0000) Subject: (no commit message) X-Git-Url: https://sfsrealm.hopto.org/projects/gitweb.cgi?a=commitdiff_plain;h=14362b19599627313cd243bdbc404dc2087d4422;p=grpapi.git --- 14362b19599627313cd243bdbc404dc2087d4422 diff --git a/LoadStorm/Storm.cpp b/LoadStorm/Storm.cpp new file mode 100644 index 0000000..264914d --- /dev/null +++ b/LoadStorm/Storm.cpp @@ -0,0 +1,114 @@ +/* + Storm.cpp +*/ + +#include "storm.h" + +struct STORMMODULE { + STORMMODULE(); + ~STORMMODULE(); +} Storm; + +HINSTANCE hStorm = 0; +BOOL AlreadyLoaded = FALSE; + +// Storm Function Names +funcSFileCloseArchive SFileCloseArchive = 0; +funcSFileCloseFile SFileCloseFile = 0; +funcSFileDestroy SFileDestroy = 0; +funcSFileGetFileArchive SFileGetFileArchive = 0; +funcSFileGetFileSize SFileGetFileSize = 0; +funcSFileOpenArchive SFileOpenArchive = 0; +funcSFileOpenFile SFileOpenFile = 0; +funcSFileOpenFileEx SFileOpenFileEx = 0; +funcSFileReadFile SFileReadFile = 0; +funcSFileSetBasePath SFileSetBasePath = 0; +funcSFileSetFilePointer SFileSetFilePointer = 0; +funcSFileSetLocale SFileSetLocale = 0; +funcSFileGetBasePath SFileGetBasePath = 0; +funcSFileGetArchiveName SFileGetArchiveName = 0; +funcSFileGetFileName SFileGetFileName = 0; + +STORMMODULE::STORMMODULE() +{ + if (hStorm!=0) return; + const char STORM_DLL[] = "Storm.dll"; + hStorm = GetModuleHandle(STORM_DLL); + if (hStorm == NULL) hStorm = LoadLibrary(STORM_DLL); + else AlreadyLoaded=TRUE; + + if (hStorm != NULL) + { + SFileCloseArchive = (funcSFileCloseArchive)GetProcAddress(hStorm, (LPCSTR)0xFC); + SFileCloseFile = (funcSFileCloseFile)GetProcAddress(hStorm, (LPCSTR)0xFD); + SFileDestroy = (funcSFileDestroy)GetProcAddress(hStorm, (LPCSTR)0x106); + SFileGetFileArchive = (funcSFileGetFileArchive)GetProcAddress(hStorm, (LPCSTR)0x108); + SFileGetFileSize = (funcSFileGetFileSize)GetProcAddress(hStorm, (LPCSTR)0x109); + SFileOpenArchive = (funcSFileOpenArchive)GetProcAddress(hStorm, (LPCSTR)0x10A); + SFileOpenFile = (funcSFileOpenFile)GetProcAddress(hStorm, (LPCSTR)0x10B); + SFileOpenFileEx = (funcSFileOpenFileEx)GetProcAddress(hStorm, (LPCSTR)0x10C); + SFileReadFile = (funcSFileReadFile)GetProcAddress(hStorm, (LPCSTR)0x10D); + SFileSetBasePath = (funcSFileSetBasePath)GetProcAddress(hStorm, (LPCSTR)0x10E); + SFileSetFilePointer = (funcSFileSetFilePointer)GetProcAddress(hStorm, (LPCSTR)0x10F); + SFileSetLocale = (funcSFileSetLocale)GetProcAddress(hStorm, (LPCSTR)0x110); + SFileGetBasePath = (funcSFileGetBasePath)GetProcAddress(hStorm, (LPCSTR)0x111); + SFileGetArchiveName = (funcSFileGetArchiveName)GetProcAddress(hStorm, (LPCSTR)0x113); + SFileGetFileName = (funcSFileGetFileName)GetProcAddress(hStorm, (LPCSTR)0x114); + } + if (SFileDestroy && !AlreadyLoaded) SFileDestroy(); +} + +STORMMODULE::~STORMMODULE() +{ + SFileCloseArchive = 0; + SFileCloseFile = 0; + SFileDestroy = 0; + SFileGetFileArchive = 0; + SFileGetFileSize = 0; + SFileOpenArchive = 0; + SFileOpenFile = 0; + SFileOpenFileEx = 0; + SFileReadFile = 0; + SFileSetBasePath = 0; + SFileSetFilePointer = 0; + SFileSetLocale = 0; + SFileGetBasePath = 0; + SFileGetArchiveName = 0; + SFileGetFileName = 0; + + if (hStorm==0) return; + + if (AlreadyLoaded==FALSE) FreeLibrary(hStorm); + hStorm = 0; +} + +HINSTANCE LoadStorm(char * DllFileName) +{ + if (hStorm!=0) return 0; + hStorm = GetModuleHandle(DllFileName); + if (hStorm == NULL) hStorm = LoadLibrary(DllFileName); + else AlreadyLoaded=TRUE; + + if (hStorm != NULL) + { + SFileCloseArchive = (funcSFileCloseArchive)GetProcAddress(hStorm, (LPCSTR)0xFC); + SFileCloseFile = (funcSFileCloseFile)GetProcAddress(hStorm, (LPCSTR)0xFD); + SFileDestroy = (funcSFileDestroy)GetProcAddress(hStorm, (LPCSTR)0x106); + SFileGetFileArchive = (funcSFileGetFileArchive)GetProcAddress(hStorm, (LPCSTR)0x108); + SFileGetFileSize = (funcSFileGetFileSize)GetProcAddress(hStorm, (LPCSTR)0x109); + SFileOpenArchive = (funcSFileOpenArchive)GetProcAddress(hStorm, (LPCSTR)0x10A); + SFileOpenFile = (funcSFileOpenFile)GetProcAddress(hStorm, (LPCSTR)0x10B); + SFileOpenFileEx = (funcSFileOpenFileEx)GetProcAddress(hStorm, (LPCSTR)0x10C); + SFileReadFile = (funcSFileReadFile)GetProcAddress(hStorm, (LPCSTR)0x10D); + SFileSetBasePath = (funcSFileSetBasePath)GetProcAddress(hStorm, (LPCSTR)0x10E); + SFileSetFilePointer = (funcSFileSetFilePointer)GetProcAddress(hStorm, (LPCSTR)0x10F); + SFileSetLocale = (funcSFileSetLocale)GetProcAddress(hStorm, (LPCSTR)0x110); + SFileGetBasePath = (funcSFileGetBasePath)GetProcAddress(hStorm, (LPCSTR)0x111); + SFileGetArchiveName = (funcSFileGetArchiveName)GetProcAddress(hStorm, (LPCSTR)0x113); + SFileGetFileName = (funcSFileGetFileName)GetProcAddress(hStorm, (LPCSTR)0x114); + } + if (SFileDestroy && !AlreadyLoaded) SFileDestroy(); + if (AlreadyLoaded==TRUE) return 0; + return hStorm; +} + diff --git a/LoadStorm/Storm.h b/LoadStorm/Storm.h new file mode 100644 index 0000000..31a5eac --- /dev/null +++ b/LoadStorm/Storm.h @@ -0,0 +1,59 @@ +#ifndef STORM_H_INCLUDED +#define STORM_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// This no longer needs to be called +extern HINSTANCE LoadStorm(char * DllFileName); + +#define SFILE_OPEN_HARD_DISK_FILE 0x0000 //Open archive without regard to the drive type it resides on +#define SFILE_OPEN_CD_ROM_FILE 0x0001 //Open the archive only if it is on a CD-ROM + +#define SFILE_SEARCH_CURRENT_ONLY 0x00 //Used with SFileOpenFileEx; only the archive with the handle specified will be searched for the file +#define SFILE_SEARCH_ALL_OPEN 0x01 //SFileOpenFileEx will look through all open archives for the file + +#define MPQHANDLE HANDLE + +// Storm Function Prototypes +typedef BOOL (WINAPI* funcSFileOpenArchive)(LPCSTR lpFilename, DWORD dwPriority, DWORD dwFlags, MPQHANDLE *hMPQ); +typedef BOOL (WINAPI* funcSFileCloseArchive)(MPQHANDLE hMPQ); +typedef BOOL (WINAPI* funcSFileOpenFile)(LPCSTR lpFileName, MPQHANDLE *hFile); +typedef BOOL (WINAPI* funcSFileOpenFileEx)(MPQHANDLE hMPQ, LPCSTR lpFileName, DWORD dwSearchScope, MPQHANDLE *hFile); +typedef BOOL (WINAPI* funcSFileCloseFile)(MPQHANDLE hFile); +typedef DWORD (WINAPI* funcSFileGetFileSize)(MPQHANDLE hFile, LPDWORD lpFileSizeHigh); +typedef DWORD (WINAPI* funcSFileSetFilePointer)(MPQHANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod); +typedef BOOL (WINAPI* funcSFileReadFile)(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped); +typedef LCID (WINAPI* funcSFileSetLocale)(LCID nNewLocale); +typedef BOOL (WINAPI* funcSFileDestroy)(); +typedef BOOL (WINAPI* funcSFileGetArchiveName)(MPQHANDLE hMPQ, LPCSTR lpBuffer, DWORD dwBufferLength); +typedef BOOL (WINAPI* funcSFileGetFileName)(MPQHANDLE hFile, LPCSTR lpBuffer, DWORD dwBufferLength); +typedef BOOL (WINAPI* funcSFileGetFileArchive)(MPQHANDLE hFile, MPQHANDLE *hMPQ); +typedef BOOL (WINAPI* funcSFileGetBasePath)(LPCSTR lpBuffer, DWORD dwBufferLength); +typedef BOOL (WINAPI* funcSFileSetBasePath)(LPCSTR lpNewBasePath); + +// Storm Function Names +extern funcSFileCloseArchive SFileCloseArchive; +extern funcSFileCloseFile SFileCloseFile; +extern funcSFileDestroy SFileDestroy; +extern funcSFileGetFileArchive SFileGetFileArchive; +extern funcSFileGetFileSize SFileGetFileSize; +extern funcSFileOpenArchive SFileOpenArchive; +extern funcSFileOpenFile SFileOpenFile; +extern funcSFileOpenFileEx SFileOpenFileEx; +extern funcSFileReadFile SFileReadFile; +extern funcSFileSetBasePath SFileSetBasePath; +extern funcSFileSetFilePointer SFileSetFilePointer; +extern funcSFileSetLocale SFileSetLocale; +extern funcSFileGetBasePath SFileGetBasePath; +extern funcSFileGetArchiveName SFileGetArchiveName; +extern funcSFileGetFileName SFileGetFileName; + +#ifdef __cplusplus +}; // extern "C" +#endif + +#endif diff --git a/drawgrp/ReadMe.txt b/drawgrp/ReadMe.txt new file mode 100644 index 0000000..d071da0 --- /dev/null +++ b/drawgrp/ReadMe.txt @@ -0,0 +1,34 @@ +======================================================================== + CONSOLE APPLICATION : drawgrp +======================================================================== + + +AppWizard has created this drawgrp application for you. + +This file contains a summary of what you will find in each of the files that +make up your drawgrp application. + +drawgrp.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +drawgrp.cpp + This is the main application source file. + + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named drawgrp.pch and a precompiled types file named StdAfx.obj. + + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/drawgrp/StdAfx.cpp b/drawgrp/StdAfx.cpp new file mode 100644 index 0000000..a6251b8 --- /dev/null +++ b/drawgrp/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// drawgrp.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/drawgrp/StdAfx.h b/drawgrp/StdAfx.h new file mode 100644 index 0000000..8ca678f --- /dev/null +++ b/drawgrp/StdAfx.h @@ -0,0 +1,22 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__6C8ACA66_6D98_11D6_9E06_00A0C9199875__INCLUDED_) +#define AFX_STDAFX_H__6C8ACA66_6D98_11D6_9E06_00A0C9199875__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// TODO: reference additional headers your program requires here +#include "..\\grpapi\\grpapi_no-lib.h" +#include "..\\storm.h" +#include + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__6C8ACA66_6D98_11D6_9E06_00A0C9199875__INCLUDED_) diff --git a/drawgrp/drawgrp.cpp b/drawgrp/drawgrp.cpp new file mode 100644 index 0000000..9adc351 --- /dev/null +++ b/drawgrp/drawgrp.cpp @@ -0,0 +1,65 @@ +// drawgrp.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" + + +/*int qmain(int argc, char* argv[]); + +int main(int argc, char* argv[]) +{ + HINSTANCE hStorm = LoadStorm("Storm.dll"); + if (SFileDestroy!=0) SFileDestroy(); + LoadGrpApi(); + int RetVal = qmain(argc,argv); + FreeGrpApi(); + if (hStorm!=0) FreeLibrary(hStorm); + return RetVal; +}*/ + +int main(int argc, char* argv[]) +{ + HANDLE hMPQ=0,hMPQ2=0,hMPQ3=0; + DWORD *dwPalette = (DWORD *)_alloca(1024); + memset(dwPalette,0,1024); + if (SFileOpenArchive!=0) { + char *buffer = (char *)_alloca(13); + memcpy(buffer,"StarDat.mpq",12); + if (SFileOpenArchive(buffer,1000,0,&hMPQ)==0) return 0; + memcpy(buffer,"BrooDat.mpq",12); + SFileOpenArchive(buffer,2000,0,&hMPQ2); + memcpy(buffer,"Patch_rt.mpq",13); + SFileOpenArchive(buffer,3000,0,&hMPQ3); + } + LoadPalette("tileset\\Jungle.wpe",dwPalette); + HANDLE hGrp; + if (argc>1) + hGrp = LoadGrp(argv[1]); + else + hGrp = LoadGrp("unit\\zerg\\ultra.grp"); + HDC hDC = GetDC(0); + GRPHEADER GrpInfo; + if (GetGrpInfo(hGrp,&GrpInfo)==0) {GrpInfo.nFrames=0;GrpInfo.wMaxWidth=0;GrpInfo.wMaxHeight=0;} + //for (DWORD j=0;j<16;j++){ + /*for (WORD i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/drawgrp/drawgrp.vcproj.vspscc b/drawgrp/drawgrp.vcproj.vspscc new file mode 100644 index 0000000..5d67725 --- /dev/null +++ b/drawgrp/drawgrp.vcproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "relative:drawgrp" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" +} diff --git a/grpapi/grp_static.h b/grpapi/grp_static.h new file mode 100644 index 0000000..5e7cc77 --- /dev/null +++ b/grpapi/grp_static.h @@ -0,0 +1,17 @@ +/* + + ShadowFlare GRP Static Library. (c) ShadowFlare Software 2002 + +*/ + +#ifndef GRPLIB_INCLUDED +#define GRPLIB_INCLUDED + +#ifndef GRPAPI_STATIC +#define GRPAPI_STATIC +#endif + +#include "grpapi.h" + +#endif + diff --git a/grpapi/grpapi.cpp b/grpapi/grpapi.cpp new file mode 100644 index 0000000..f746120 --- /dev/null +++ b/grpapi/grpapi.cpp @@ -0,0 +1,298 @@ +#include "grpapi.h" +#include "..\\LoadStorm\\storm.h" +#include + +#ifdef GRPAPI_STATIC +#define DllMain GrpMain + +#include "grp_static.h" + +struct GRPLIBMODULE { + GRPLIBMODULE(); + ~GRPLIBMODULE(); +} GrpLib; + +BOOL APIENTRY DllMain(HINSTANCE hInstDLL, DWORD ul_reason_for_call, LPVOID lpReserved); + +GRPLIBMODULE::GRPLIBMODULE() +{ + GrpMain(0,DLL_PROCESS_ATTACH,0); +} + +GRPLIBMODULE::~GRPLIBMODULE() +{ + GrpMain(0,DLL_PROCESS_DETACH,0); +} + +#endif + +typedef struct { + BYTE Left; + BYTE Top; + BYTE Width; + BYTE Height; + DWORD Offset; +} FRAMEHEADER; + +void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD dwFlags, DWORD dwAlpha); + +extern HINSTANCE hStorm; + +BOOL APIENTRY DllMain( HINSTANCE hInstDLL, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} + +BOOL GRPAPI WINAPI LoadGrpApi() +{ + if (hStorm==0) return FALSE; + else return TRUE; +} + +void GRPAPI WINAPI FreeGrpApi() +{ +} + +BOOL GRPAPI WINAPI LoadPalette(LPCSTR lpFileName, DWORD *dwPaletteBuffer) +{ + if (lpFileName==0 || dwPaletteBuffer==0) return FALSE; + HANDLE hFile; + if (SFileOpenFileEx!=0 && SFileGetFileSize!=0 + && SFileSetFilePointer!=0 && SFileReadFile!=0 + && SFileCloseFile!=0) { + if (SFileOpenFileEx(0,lpFileName,1,&hFile)==0) return FALSE; + DWORD fsz = SFileGetFileSize(hFile,0); + SFileSetFilePointer(hFile,0,0,FILE_BEGIN); + if (fsz>=1024) { + memset(dwPaletteBuffer,0,1024); + SFileReadFile(hFile,dwPaletteBuffer,1024,0,0); + } + else if (fsz==768) { + char *buffer = (char *)_alloca(768); + memset(buffer,0,768); + SFileReadFile(hFile,buffer,768,0,0); + for (DWORD i=0;i<256;i++) { + memcpy(&dwPaletteBuffer[i],buffer+i*3,3); + *(((char *)&dwPaletteBuffer[i])+3) = 0; + } + } + else { + memset(dwPaletteBuffer,0,1024); + SFileReadFile(hFile,dwPaletteBuffer,fsz,0,0); + } + SFileCloseFile(hFile); + } + else { + hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); + if (hFile==INVALID_HANDLE_VALUE) return FALSE; + DWORD fsz = GetFileSize(hFile,0),tsz; + SetFilePointer(hFile,0,0,FILE_BEGIN); + if (fsz>=1024) { + memset(dwPaletteBuffer,0,1024); + ReadFile(hFile,dwPaletteBuffer,1024,&tsz,0); + } + else if (fsz==768) { + char *buffer = (char *)_alloca(768); + memset(buffer,0,768); + ReadFile(hFile,buffer,768,&tsz,0); + for (DWORD i=0;i<256;i++) { + memcpy(&dwPaletteBuffer[i],buffer+i*3,3); + *(((char *)&dwPaletteBuffer[i])+3) = 0; + } + } + else { + memset(dwPaletteBuffer,0,1024); + ReadFile(hFile,dwPaletteBuffer,fsz,&tsz,0); + } + CloseHandle(hFile); + } + return TRUE; +} + +HANDLE GRPAPI WINAPI LoadGrp(LPCSTR lpFileName) +{ + if (lpFileName==0) return (HANDLE)-1; + HANDLE hFile; + char *GrpFile; + if (SFileOpenFileEx!=0 && SFileGetFileSize!=0 + && SFileSetFilePointer!=0 && SFileReadFile!=0 + && SFileCloseFile!=0) { + if (SFileOpenFileEx(0,lpFileName,1,&hFile)==0) return (HANDLE)-1; + DWORD fsz = SFileGetFileSize(hFile,0); + if (fsz<6) { + SFileCloseFile(hFile); + return (HANDLE)-1; + } + GrpFile = (char *)VirtualAlloc(0,fsz,MEM_COMMIT,PAGE_READWRITE); + if (GrpFile!=0) { + SFileSetFilePointer(hFile,0,0,FILE_BEGIN); + SFileReadFile(hFile,GrpFile,fsz,0,0); + } + else GrpFile=(char *)-1; + SFileCloseFile(hFile); + } + else { + hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); + if (hFile==INVALID_HANDLE_VALUE) return (HANDLE)-1; + DWORD fsz = GetFileSize(hFile,0),tsz; + if (fsz<6) { + CloseHandle(hFile); + return (HANDLE)-1; + } + GrpFile = (char *)VirtualAlloc(0,fsz,MEM_COMMIT,PAGE_READWRITE); + if (GrpFile!=0) { + SetFilePointer(hFile,0,0,FILE_BEGIN); + ReadFile(hFile,GrpFile,fsz,&tsz,0); + } + else GrpFile=(char *)-1; + CloseHandle(hFile); + } + return (HANDLE)GrpFile; +} + +BOOL GRPAPI WINAPI DestroyGrp(HANDLE hGrp) +{ + if (hGrp==0 || hGrp==INVALID_HANDLE_VALUE) return FALSE; + VirtualFree(hGrp,0,MEM_RELEASE); + return TRUE; +} + +BOOL GRPAPI WINAPI DrawGrp(HANDLE hGrp, HDC hdcDest, int nXDest, int nYDest, WORD nFrame, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha) +{ + if (hGrp==0 || hGrp==INVALID_HANDLE_VALUE || hdcDest==0 || dwPalette==0) return FALSE; + GRPHEADER *GrpFile = (GRPHEADER *)hGrp; + nFrame %= GrpFile->nFrames; + FRAMEHEADER *GrpFrame = &((FRAMEHEADER *)(((char *)GrpFile)+6))[nFrame]; + DWORD Right,Bottom; + if (dwFlags&HORIZONTAL_FLIP) Right = nXDest+GrpFile->wMaxWidth-1-GrpFrame->Left; + if (dwFlags&VERTICAL_FLIP) Bottom = nYDest+GrpFile->wMaxHeight-1-GrpFrame->Top; + nXDest += GrpFrame->Left; + nYDest += GrpFrame->Top; + WORD *GrpOffsets = ((WORD *)(((char *)GrpFile)+GrpFrame->Offset)); + for (DWORD y=0;yHeight;y++) { + BYTE *RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y])); + WORD x=0,ofs=0; + while (xWidth) { + if (RowData[ofs]<=64) { + if ((dwFlags&HORIZONTAL_FLIP)==0 && (dwFlags&VERTICAL_FLIP)==0) { + for (WORD i=1;i<=RowData[ofs] && xWidth;i++) { + SetPix(hdcDest,nXDest+x,nYDest+y,dwPalette[RowData[ofs+i]],dwFlags,dwAlpha); + x++; + } + } + else if (dwFlags&HORIZONTAL_FLIP && (dwFlags&VERTICAL_FLIP)==0) { + for (WORD i=1;i<=RowData[ofs] && xWidth;i++) { + SetPix(hdcDest,Right-x,nYDest+y,dwPalette[RowData[ofs+i]],dwFlags,dwAlpha); + x++; + } + } + else if ((dwFlags&HORIZONTAL_FLIP)==0 && dwFlags&VERTICAL_FLIP) { + for (WORD i=1;i<=RowData[ofs] && xWidth;i++) { + SetPix(hdcDest,nXDest+x,Bottom-y,dwPalette[RowData[ofs+i]],dwFlags,dwAlpha); + x++; + } + } + else { + for (WORD i=1;i<=RowData[ofs] && xWidth;i++) { + SetPix(hdcDest,Right-x,Bottom-y,dwPalette[RowData[ofs+i]],dwFlags,dwAlpha); + x++; + } + } + ofs+=RowData[ofs]+1; + } + else if (RowData[ofs]<=128) { + if ((dwFlags&HORIZONTAL_FLIP)==0 && (dwFlags&VERTICAL_FLIP)==0) { + for (WORD i=0;iWidth;i++) { + SetPix(hdcDest,nXDest+x,nYDest+y,dwPalette[RowData[ofs+1]],dwFlags,dwAlpha); + x++; + } + } + else if (dwFlags&HORIZONTAL_FLIP && (dwFlags&VERTICAL_FLIP)==0) { + for (WORD i=0;iWidth;i++) { + SetPix(hdcDest,Right-x,nYDest+y,dwPalette[RowData[ofs+1]],dwFlags,dwAlpha); + x++; + } + } + else if ((dwFlags&HORIZONTAL_FLIP)==0 && dwFlags&VERTICAL_FLIP) { + for (WORD i=0;iWidth;i++) { + SetPix(hdcDest,nXDest+x,Bottom-y,dwPalette[RowData[ofs+1]],dwFlags,dwAlpha); + x++; + } + } + else { + for (WORD i=0;iWidth;i++) { + SetPix(hdcDest,Right-x,Bottom-y,dwPalette[RowData[ofs+1]],dwFlags,dwAlpha); + x++; + } + } + ofs+=2; + } + else { + x+=RowData[ofs]-128; + ofs++; + } + } + } + return TRUE; +} + +BOOL GRPAPI WINAPI GetGrpInfo(HANDLE hGrp, GRPHEADER *GrpInfo) +{ + if (hGrp==0 || hGrp==INVALID_HANDLE_VALUE || GrpInfo==0) return FALSE; + memcpy(GrpInfo,hGrp,6); + return TRUE; +} + +void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD dwFlags, DWORD dwAlpha) +{ + if (dwFlags&SHADOW_COLOR) { + ((BYTE *)&clrColor)[0] = ((BYTE *)&dwFlags)[1]; + ((BYTE *)&clrColor)[1] = ((BYTE *)&dwFlags)[2]; + ((BYTE *)&clrColor)[2] = ((BYTE *)&dwFlags)[3]; + ((BYTE *)&clrColor)[3] = 0; + } + if (dwFlags&ALPHA_BLEND) { + DWORD dwColor = GetPixel(hDC,X,Y); + + // Old alpha + /*((BYTE *)&dwColor)[0]*=1-((float)((BYTE *)&dwAlpha)[0]/256); + ((BYTE *)&dwColor)[1]*=1-((float)((BYTE *)&dwAlpha)[1]/256); + ((BYTE *)&dwColor)[2]*=1-((float)((BYTE *)&dwAlpha)[2]/256); + ((BYTE *)&clrColor)[0]*=(float)((BYTE *)&dwAlpha)[0]/256; + ((BYTE *)&clrColor)[1]*=(float)((BYTE *)&dwAlpha)[1]/256; + ((BYTE *)&clrColor)[2]*=(float)((BYTE *)&dwAlpha)[2]/256; + ((BYTE *)&clrColor)[0]+=((BYTE *)&dwColor)[0]; + ((BYTE *)&clrColor)[1]+=((BYTE *)&dwColor)[1]; + ((BYTE *)&clrColor)[2]+=((BYTE *)&dwColor)[2];*/ + + /* blendedcolor = + ( ( forecolor * ( 1 - alpha ) ) >> 8 ) + + ( ( backcolor * ( 256 - alpha ) ) >> 8 ) */ + ((BYTE *)&clrColor)[0] = + ( ( ((BYTE *)&clrColor)[0] * ( ((BYTE *)&dwAlpha)[0] + 1 ) ) >> 8 ) + + ( ( ((BYTE *)&dwColor)[0] * ( 256 - ((BYTE *)&dwAlpha)[0] ) ) >> 8 ); + ((BYTE *)&clrColor)[1] = + ( ( ((BYTE *)&clrColor)[1] * ( ((BYTE *)&dwAlpha)[1] + 1 ) ) >> 8 ) + + ( ( ((BYTE *)&dwColor)[1] * ( 256 - ((BYTE *)&dwAlpha)[1] ) ) >> 8 ); + ((BYTE *)&clrColor)[2] = + ( ( ((BYTE *)&clrColor)[2] * ( ((BYTE *)&dwAlpha)[2] + 1 ) ) >> 8 ) + + ( ( ((BYTE *)&dwColor)[2] * ( 256 - ((BYTE *)&dwAlpha)[2] ) ) >> 8 ); + } + SetPixelV(hDC,X,Y,clrColor); +} + diff --git a/grpapi/grpapi.def b/grpapi/grpapi.def new file mode 100644 index 0000000..db8056e --- /dev/null +++ b/grpapi/grpapi.def @@ -0,0 +1,8 @@ +EXPORTS + LoadPalette @1 + LoadGrp @2 + DestroyGrp @3 + DrawGrp @4 + GetGrpInfo @5 + LoadGrpApi @6 + FreeGrpApi @7 diff --git a/grpapi/grpapi.h b/grpapi/grpapi.h new file mode 100644 index 0000000..8fc78cb --- /dev/null +++ b/grpapi/grpapi.h @@ -0,0 +1,67 @@ +/* + + ShadowFlare GRP Library. (c) ShadowFlare Software 2002 + + Any comments or suggestions are accepted at blakflare@hotmail.com (ShadowFlare) +*/ + +#ifndef GRPAPI_INCLUDED +#define GRPAPI_INCLUDED + +#include + +#ifndef GRPAPI_STATIC + +#ifdef GRPAPI_EXPORTS +#define GRPAPI __declspec(dllexport) +#else +#define GRPAPI __declspec(dllimport) +#endif + +#else +#define GRPAPI +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + WORD nFrames; + WORD wMaxWidth; + WORD wMaxHeight; +} GRPHEADER; + +#define HORIZONTAL_FLIP 0x00000001 // Flips the graphic horizontally +#define VERTICAL_FLIP 0x00000002 // Flips the graphic vertically +#define SHADOW_COLOR 0x00000004 // Causes the graphic to be drawn in one color + // Second byte of flags is the red component of + // the shadow's color, third byte is green, + // fourth byte is blue; like this: + // SHADOW_COLOR|0xBBGGRR00 +#define ALPHA_BLEND 0x00000008 // Blends the graphic with what it is being drawn over. + // The dwAlpha parameter will only be used when this + // flag is specified. dwAlpha is an RGB value + // (0xBBGGRR). + // Note: Because of the extra calculations required, + // alpha blended graphics take longer to draw + +// Palette is an array of 256 DWORD's +// For LoadPalette and LoadGrp, lpFileName may be a file in an open mpq archive +// or a file not in an archive +BOOL GRPAPI WINAPI LoadPalette(LPCSTR lpFileName, DWORD *dwPaletteBuffer); +HANDLE GRPAPI WINAPI LoadGrp(LPCSTR lpFileName); +BOOL GRPAPI WINAPI DestroyGrp(HANDLE hGrp); +BOOL GRPAPI WINAPI DrawGrp(HANDLE hGrp, HDC hdcDest, int nXDest, int nYDest, WORD nFrame, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha); +BOOL GRPAPI WINAPI GetGrpInfo(HANDLE hGrp, GRPHEADER *GrpInfo); + +// These no longer need to be called +BOOL GRPAPI WINAPI LoadGrpApi(); +void GRPAPI WINAPI FreeGrpApi(); + +#ifdef __cplusplus +}; // extern "C" +#endif + +#endif + diff --git a/grpapi/grpapi.rc b/grpapi/grpapi.rc new file mode 100644 index 0000000..7a3ae1c --- /dev/null +++ b/grpapi/grpapi.rc @@ -0,0 +1,110 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "ShadowFlare Software\0" + #ifdef _DEBUG + VALUE "FileDescription", "ShadowFlare GRP Library (debug build)\0" + #else + VALUE "FileDescription", "ShadowFlare GRP Library\0" + #endif + VALUE "FileVersion", "1.00\0" + VALUE "InternalName", "grpapi\0" + VALUE "LegalCopyright", "Copyright © ShadowFlare Software 2002\0" + VALUE "OriginalFilename", "grpapi.dll\0" + VALUE "ProductName", "GRP Library\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + VALUE "Web Address", "http://shadowflare.ancillaediting.net/\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/grpapi/grpapi.sln b/grpapi/grpapi.sln new file mode 100644 index 0000000..4aa5309 --- /dev/null +++ b/grpapi/grpapi.sln @@ -0,0 +1,58 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "drawgrp", "..\drawgrp\drawgrp.vcproj", "{10729DB2-5CEA-41BA-9C6F-B47BE5A3C242}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpapi", "grpapi.vcproj", "{08812E9C-7F03-4DCB-8828-F3BDB0728EC7}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grplib", "grplib.vcproj", "{66127C6F-39DA-4B7A-9856-789ED0139DCB}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SourceCodeControl) = preSolution + SccNumberOfProjects = 4 + SccProjectName0 = \u0022$/grpapi.root/grpapi\u0022,\u0020FEAAAAAA + SccLocalPath0 = .. + SccProvider0 = MSSCCI:Microsoft\u0020Visual\u0020SourceSafe + CanCheckoutShared = false + SccProjectFilePathRelativizedFromConnection0 = grpapi\\ + SolutionUniqueID = {C7ACFA83-726F-4F2A-93F1-58F59B9D32B9} + SccProjectUniqueName1 = ..\\drawgrp\\drawgrp.vcproj + SccLocalPath1 = .. + CanCheckoutShared = false + SccProjectFilePathRelativizedFromConnection1 = drawgrp\\ + SccProjectUniqueName2 = grpapi.vcproj + SccLocalPath2 = .. + CanCheckoutShared = false + SccProjectFilePathRelativizedFromConnection2 = grpapi\\ + SccProjectUniqueName3 = grplib.vcproj + SccLocalPath3 = .. + CanCheckoutShared = false + SccProjectFilePathRelativizedFromConnection3 = grpapi\\ + EndGlobalSection + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {10729DB2-5CEA-41BA-9C6F-B47BE5A3C242}.Debug.ActiveCfg = Debug|Win32 + {10729DB2-5CEA-41BA-9C6F-B47BE5A3C242}.Debug.Build.0 = Debug|Win32 + {10729DB2-5CEA-41BA-9C6F-B47BE5A3C242}.Release.ActiveCfg = Release|Win32 + {10729DB2-5CEA-41BA-9C6F-B47BE5A3C242}.Release.Build.0 = Release|Win32 + {08812E9C-7F03-4DCB-8828-F3BDB0728EC7}.Debug.ActiveCfg = Debug|Win32 + {08812E9C-7F03-4DCB-8828-F3BDB0728EC7}.Debug.Build.0 = Debug|Win32 + {08812E9C-7F03-4DCB-8828-F3BDB0728EC7}.Release.ActiveCfg = Release|Win32 + {08812E9C-7F03-4DCB-8828-F3BDB0728EC7}.Release.Build.0 = Release|Win32 + {66127C6F-39DA-4B7A-9856-789ED0139DCB}.Debug.ActiveCfg = Debug|Win32 + {66127C6F-39DA-4B7A-9856-789ED0139DCB}.Debug.Build.0 = Debug|Win32 + {66127C6F-39DA-4B7A-9856-789ED0139DCB}.Release.ActiveCfg = Release|Win32 + {66127C6F-39DA-4B7A-9856-789ED0139DCB}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/grpapi/grpapi.vcproj b/grpapi/grpapi.vcproj new file mode 100644 index 0000000..11fbbd9 --- /dev/null +++ b/grpapi/grpapi.vcproj @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/grpapi/grpapi.vcproj.vspscc b/grpapi/grpapi.vcproj.vspscc new file mode 100644 index 0000000..055d30a --- /dev/null +++ b/grpapi/grpapi.vcproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "relative:grpapi" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" +} diff --git a/grpapi/grpapi.vsscc b/grpapi/grpapi.vsscc new file mode 100644 index 0000000..85ef98b Binary files /dev/null and b/grpapi/grpapi.vsscc differ diff --git a/grpapi/grpapi.vssscc b/grpapi/grpapi.vssscc new file mode 100644 index 0000000..055d30a --- /dev/null +++ b/grpapi/grpapi.vssscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "relative:grpapi" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" +} diff --git a/grpapi/grpapi_no-lib.cpp b/grpapi/grpapi_no-lib.cpp new file mode 100644 index 0000000..a183155 --- /dev/null +++ b/grpapi/grpapi_no-lib.cpp @@ -0,0 +1,56 @@ +#include "grpapi_no-lib.h" + +struct GRPAPIMODULE { + GRPAPIMODULE(); + ~GRPAPIMODULE(); +} GrpApi; + +HINSTANCE hGrpApi = 0; + +funcLoadPalette LoadPalette = 0; +funcLoadGrp LoadGrp = 0; +funcDestroyGrp DestroyGrp = 0; +funcDrawGrp DrawGrp = 0; +funcGetGrpInfo GetGrpInfo = 0; +funcLoadGrpApi LoadGrpApi = 0; +funcFreeGrpApi FreeGrpApi = 0; + +GRPAPIMODULE::GRPAPIMODULE() +{ + if (hGrpApi!=0) return; + hGrpApi = LoadLibrary("grpapi.dll"); + + if (hGrpApi!=0) { + LoadPalette = (funcLoadPalette)GetProcAddress(hGrpApi,"LoadPalette"); + LoadGrp = (funcLoadGrp)GetProcAddress(hGrpApi,"LoadGrp"); + DestroyGrp = (funcDestroyGrp)GetProcAddress(hGrpApi,"DestroyGrp"); + DrawGrp = (funcDrawGrp)GetProcAddress(hGrpApi,"DrawGrp"); + GetGrpInfo = (funcGetGrpInfo)GetProcAddress(hGrpApi,"GetGrpInfo"); + LoadGrpApi = (funcLoadGrpApi)GetProcAddress(hGrpApi,"LoadGrpApi"); + FreeGrpApi = (funcFreeGrpApi)GetProcAddress(hGrpApi,"FreeGrpApi"); + } +} + +GRPAPIMODULE::~GRPAPIMODULE() +{ + LoadPalette = 0; + LoadGrp = 0; + DestroyGrp = 0; + DrawGrp = 0; + GetGrpInfo = 0; + LoadGrpApi = 0; + FreeGrpApi = 0; + + if (hGrpApi==0) return; + FreeLibrary(hGrpApi); + hGrpApi = 0; +} + +void LoadGrpApiLib() +{ +} + +void FreeGrpApiLib() +{ +} + diff --git a/grpapi/grpapi_no-lib.h b/grpapi/grpapi_no-lib.h new file mode 100644 index 0000000..a252519 --- /dev/null +++ b/grpapi/grpapi_no-lib.h @@ -0,0 +1,72 @@ +/* + + ShadowFlare GRP Library. (c) ShadowFlare Software 2002 + + Any comments or suggestions are accepted at blakflare@hotmail.com (ShadowFlare) +*/ + +#ifndef GRPAPI_INCLUDED +#define GRPAPI_INCLUDED + +#include + +#ifdef GRPAPI_EXPORTS +#define GRPAPI __declspec(dllexport) +#else +#define GRPAPI __declspec(dllimport) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// These no longer need to be called +extern void LoadGrpApiLib(); +extern void FreeGrpApiLib(); + +typedef struct { + WORD nFrames; + WORD wMaxWidth; + WORD wMaxHeight; +} GRPHEADER; + +#define HORIZONTAL_FLIP 0x00000001 // Flips the graphic horizontally +#define VERTICAL_FLIP 0x00000002 // Flips the graphic vertically +#define SHADOW_COLOR 0x00000004 // Causes the graphic to be drawn in one color + // Second byte of flags is the red component of + // the shadow's color, third byte is green, + // fourth byte is blue; like this: + // SHADOW_COLOR|0xBBGGRR00 +#define ALPHA_BLEND 0x00000008 // Blends the graphic with what it is being drawn over. + // The dwAlpha parameter will only be used when this + // flag is specified. dwAlpha is an RGB value + // (0xBBGGRR). + // Note: Because of the extra calculations required, + // alpha blended graphics take longer to draw + +// Palette is an array of 256 DWORD's +// For LoadPalette and LoadGrp, lpFileName may be a file in an open mpq archive +// or a file not in an archive +typedef BOOL (WINAPI* funcLoadPalette)(LPCSTR lpFileName, DWORD *dwPaletteBuffer); +typedef HANDLE (WINAPI* funcLoadGrp)(LPCSTR lpFileName); +typedef BOOL (WINAPI* funcDestroyGrp)(HANDLE hGrp); +typedef BOOL (WINAPI* funcDrawGrp)(HANDLE hGrp, HDC hdcDest, int nXDest, int nYDest, WORD nFrame, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha); +typedef BOOL (WINAPI* funcGetGrpInfo)(HANDLE hGrp, GRPHEADER *GrpInfo); +extern funcLoadPalette LoadPalette; +extern funcLoadGrp LoadGrp; +extern funcDestroyGrp DestroyGrp; +extern funcDrawGrp DrawGrp; +extern funcGetGrpInfo GetGrpInfo; + +// These no longer need to be called +typedef BOOL (WINAPI* funcLoadGrpApi)(); +typedef void (WINAPI* funcFreeGrpApi)(); +extern funcLoadGrpApi LoadGrpApi; +extern funcFreeGrpApi FreeGrpApi; + +#ifdef __cplusplus +}; // extern "C" +#endif + +#endif + diff --git a/grpapi/grplib.vcproj b/grpapi/grplib.vcproj new file mode 100644 index 0000000..f48df3e --- /dev/null +++ b/grpapi/grplib.vcproj @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/grpapi/grplib.vcproj.vspscc b/grpapi/grplib.vcproj.vspscc new file mode 100644 index 0000000..055d30a --- /dev/null +++ b/grpapi/grplib.vcproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "relative:grpapi" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" +}