Current News
Archived News
Search News
Discussion Forum


Old Forum
Install Programs More Downloads...
Troubleshooting
Source Code
Format Specs.
Misc. Information
Non-SF Stuff
Links




index b002e12..ad088c3 100644 (file)
-#include "grpapi.h"\r
-#include "../LoadStorm/storm.h"\r
-#include <malloc.h>\r
-\r
-#ifdef GRPAPI_STATIC\r
-#define DllMain GrpMain\r
-\r
-#include "grp_static.h"\r
-\r
-struct GRPLIBMODULE {\r
-       GRPLIBMODULE();\r
-       ~GRPLIBMODULE();\r
-} GrpLib;\r
-\r
-BOOL APIENTRY DllMain(HINSTANCE hInstDLL, DWORD  ul_reason_for_call, LPVOID lpReserved);\r
-\r
-GRPLIBMODULE::GRPLIBMODULE()\r
-{\r
-       GrpMain(0,DLL_PROCESS_ATTACH,0);\r
-}\r
-\r
-GRPLIBMODULE::~GRPLIBMODULE()\r
-{\r
-       GrpMain(0,DLL_PROCESS_DETACH,0);\r
-}\r
-\r
-#endif\r
-\r
-typedef struct {\r
-       BYTE Left;\r
-       BYTE Top;\r
-       BYTE Width;\r
-       BYTE Height;\r
-       DWORD Offset;\r
-} FRAMEHEADER;\r
-\r
-typedef struct {\r
-       WORD *lpRowOffsets;\r
-       WORD *lpRowSizes;\r
-       LPBYTE *lpRowData;\r
-       DWORD Size;\r
-} FRAMEDATA;\r
-\r
-GETPIXELPROC MyGetPixel = GetPixel;\r
-SETPIXELPROC MySetPixel = (SETPIXELPROC)SetPixelV;\r
-\r
-void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha);\r
-void EncodeFrameData(signed short *lpImageData, WORD nFrame, GRPHEADER *lpGrpHeader, FRAMEHEADER *lpFrameHeader, FRAMEDATA *lpFrameData, BOOL bNoCompress);\r
-BOOL VerifyRow(signed short *lpRawRow, int nWidth, LPBYTE lpEncRow, int nSize, BOOL bNoCompress);\r
-\r
-extern HINSTANCE hStorm;\r
-\r
-BOOL APIENTRY DllMain( HINSTANCE hInstDLL, \r
-                       DWORD  ul_reason_for_call, \r
-                       LPVOID lpReserved\r
-                                        )\r
-{\r
-    switch (ul_reason_for_call)\r
-       {\r
-               case DLL_PROCESS_ATTACH:\r
-                       break;\r
-               case DLL_THREAD_ATTACH:\r
-                       break;\r
-               case DLL_THREAD_DETACH:\r
-                       break;\r
-               case DLL_PROCESS_DETACH:\r
-                       break;\r
-    }\r
-\r
-    return TRUE;\r
-}\r
-\r
-BOOL GRPAPI WINAPI LoadGrpApi()\r
-{\r
-       if (!hStorm) return FALSE;\r
-       else return TRUE;\r
-}\r
-\r
-void GRPAPI WINAPI FreeGrpApi()\r
-{\r
-}\r
-\r
-/*\r
-HANDLE hProcessHeap = NULL;\r
-\r
-void * SFAlloc(size_t nSize)\r
-{\r
-       if (!hProcessHeap) hProcessHeap = GetProcessHeap();\r
-       if (hProcessHeap) return HeapAlloc(hProcessHeap, 0, nSize);\r
-       else return NULL;\r
-}\r
-\r
-void SFFree(void *lpMem)\r
-{\r
-       if (!hProcessHeap) hProcessHeap = GetProcessHeap();\r
-       if (hProcessHeap) HeapFree(hProcessHeap, 0, lpMem);\r
-}\r
-*/\r
-\r
-BOOL GRPAPI WINAPI SetMpqDll(LPCSTR lpDllFileName)\r
-{\r
-       if (LoadStorm((char *)lpDllFileName)) return TRUE;\r
-       else return FALSE;\r
-}\r
-\r
-BOOL GRPAPI WINAPI LoadPalette(LPCSTR lpFileName, DWORD *dwPaletteBuffer)\r
-{\r
-       if (!lpFileName || !dwPaletteBuffer) return FALSE;\r
-       HANDLE hFile;\r
-       if (SFileOpenFileEx && SFileGetFileSize\r
-        && SFileSetFilePointer && SFileReadFile\r
-        && SFileCloseFile) {\r
-               if (!SFileOpenFileEx(0,lpFileName,1,&hFile)) return FALSE;\r
-               DWORD fsz = SFileGetFileSize(hFile,0);\r
-               SFileSetFilePointer(hFile,0,0,FILE_BEGIN);\r
-               if (fsz>=1024) {\r
-                       memset(dwPaletteBuffer,0,1024);\r
-                       SFileReadFile(hFile,dwPaletteBuffer,1024,0,0);\r
-               }\r
-               else if (fsz==768) {\r
-                       char *buffer = (char *)_alloca(768);\r
-                       memset(buffer,0,768);\r
-                       SFileReadFile(hFile,buffer,768,0,0);\r
-                       for (DWORD i=0;i<256;i++) {\r
-                               memcpy(&dwPaletteBuffer[i],buffer+i*3,3);\r
-                               *(((char *)&dwPaletteBuffer[i])+3) = 0;\r
-                       }\r
-               }\r
-               else {\r
-                       memset(dwPaletteBuffer,0,1024);\r
-                       SFileReadFile(hFile,dwPaletteBuffer,fsz,0,0);\r
-               }\r
-               SFileCloseFile(hFile);\r
-       }\r
-       else {\r
-               hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);\r
-               if (hFile==INVALID_HANDLE_VALUE) return FALSE;\r
-               DWORD fsz = GetFileSize(hFile,0),tsz;\r
-               SetFilePointer(hFile,0,0,FILE_BEGIN);\r
-               if (fsz>=1024) {\r
-                       memset(dwPaletteBuffer,0,1024);\r
-                       ReadFile(hFile,dwPaletteBuffer,1024,&tsz,0);\r
-               }\r
-               else if (fsz==768) {\r
-                       char *buffer = (char *)_alloca(768);\r
-                       memset(buffer,0,768);\r
-                       ReadFile(hFile,buffer,768,&tsz,0);\r
-                       for (DWORD i=0;i<256;i++) {\r
-                               memcpy(&dwPaletteBuffer[i],buffer+i*3,3);\r
-                               *(((char *)&dwPaletteBuffer[i])+3) = 0;\r
-                       }\r
-               }\r
-               else {\r
-                       memset(dwPaletteBuffer,0,1024);\r
-                       ReadFile(hFile,dwPaletteBuffer,fsz,&tsz,0);\r
-               }\r
-               CloseHandle(hFile);\r
-       }\r
-       return TRUE;\r
-}\r
-\r
-HANDLE GRPAPI WINAPI LoadGrp(LPCSTR lpFileName)\r
-{\r
-       if (!lpFileName) return (HANDLE)-1;\r
-       HANDLE hFile;\r
-       char *GrpFile;\r
-       if (SFileOpenFileEx && SFileGetFileSize\r
-        && SFileSetFilePointer && SFileReadFile\r
-        && SFileCloseFile) {\r
-               if (!SFileOpenFileEx(0,lpFileName,1,&hFile)) return (HANDLE)-1;\r
-               DWORD fsz = SFileGetFileSize(hFile,0);\r
-               if (fsz<6) {\r
-                       SFileCloseFile(hFile);\r
-                       return (HANDLE)-1;\r
-               }\r
-               GrpFile = (char *)malloc(fsz);\r
-               if (GrpFile) {\r
-                       SFileSetFilePointer(hFile,0,0,FILE_BEGIN);\r
-                       SFileReadFile(hFile,GrpFile,fsz,0,0);\r
-               }\r
-               else GrpFile=(char *)-1;\r
-               SFileCloseFile(hFile);\r
-       }\r
-       else {\r
-               hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);\r
-               if (hFile==INVALID_HANDLE_VALUE) return (HANDLE)-1;\r
-               DWORD fsz = GetFileSize(hFile,0),tsz;\r
-               if (fsz<6) {\r
-                       CloseHandle(hFile);\r
-                       return (HANDLE)-1;\r
-               }\r
-               GrpFile = (char *)malloc(fsz);\r
-               if (GrpFile) {\r
-                       SetFilePointer(hFile,0,0,FILE_BEGIN);\r
-                       ReadFile(hFile,GrpFile,fsz,&tsz,0);\r
-               }\r
-               else GrpFile=(char *)-1;\r
-               CloseHandle(hFile);\r
-       }\r
-       return (HANDLE)GrpFile;\r
-}\r
-\r
-BOOL GRPAPI WINAPI DestroyGrp(HANDLE hGrp)\r
-{\r
-       if (!hGrp || hGrp==INVALID_HANDLE_VALUE) return FALSE;\r
-       free(hGrp);\r
-       return TRUE;\r
-}\r
-\r
-BOOL GRPAPI WINAPI DrawGrp(HANDLE hGrp, HDC hdcDest, int nXDest, int nYDest, WORD nFrame, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha)\r
-{\r
-       if (!hGrp || hGrp==INVALID_HANDLE_VALUE || hdcDest==0 || (!dwPalette && !(dwFlags&USE_INDEX))) return FALSE;\r
-       GRPHEADER *GrpFile = (GRPHEADER *)hGrp;\r
-       nFrame %= GrpFile->nFrames;\r
-       FRAMEHEADER *GrpFrame = &((FRAMEHEADER *)(((char *)GrpFile)+6))[nFrame];\r
-       FRAMEHEADER *GrpFrames = &((FRAMEHEADER *)(((char *)GrpFile)+6))[0];\r
-       int FrameSize = 0xFFFFFF;\r
-       DWORD Right,Bottom;\r
-       if (dwFlags&HORIZONTAL_FLIP) Right = nXDest+GrpFile->wMaxWidth-1-GrpFrame->Left;\r
-       if (dwFlags&VERTICAL_FLIP) Bottom = nYDest+GrpFile->wMaxHeight-1-GrpFrame->Top;\r
-       nXDest += GrpFrame->Left;\r
-       nYDest += GrpFrame->Top;\r
-       WORD *GrpOffsets = ((WORD *)(((char *)GrpFile)+GrpFrame->Offset));\r
-       BYTE *GrpRaw = (BYTE *)GrpOffsets;\r
-       BYTE *RowData;\r
-       WORD x,ofs;\r
-       DWORD y, nMaxOffset = 0;\r
-       WORD i;\r
-       int j, nFirstNonBlankFrame = 0;\r
-       for (i = 0; i < GrpFile->nFrames; i++) {\r
-               j = GrpFrames[i].Offset - GrpFrame->Offset;\r
-               if (j > 0 && j < FrameSize)\r
-                       FrameSize = j;\r
-               if (GrpFrames[i].Offset > nMaxOffset)\r
-                       nMaxOffset = GrpFrames[i].Offset;\r
-       }\r
-       if (FrameSize == 0xFFFFFF || FrameSize == GrpFrame->Width * GrpFrame->Height) {\r
-               FrameSize = 0xFFFFFF;\r
-               for (i = 0; i < GrpFile->nFrames; i++) {\r
-                       if (GrpFrames[i].Width != 0 && GrpFrames[i].Height != 0 && GrpFrames[i].Offset != GrpFrame->Offset && GrpFrames[i].Offset != nMaxOffset) {\r
-                               nFirstNonBlankFrame = i;\r
-                               break;\r
-                       }\r
-               }\r
-               if (i == GrpFile->nFrames)\r
-                       nFirstNonBlankFrame = nFrame;\r
-\r
-               for (i = 0; i < GrpFile->nFrames; i++) {\r
-                       j = GrpFrames[i].Offset - GrpFrames[nFirstNonBlankFrame].Offset;\r
-                       if (j > 0 && j < FrameSize)\r
-                               FrameSize = j;\r
-               }\r
-               if (FrameSize == GrpFrames[nFirstNonBlankFrame].Width * GrpFrames[nFirstNonBlankFrame].Height)\r
-                       FrameSize = GrpFrame->Width * GrpFrame->Height;\r
-       }\r
-       if (!(dwFlags&HORIZONTAL_FLIP) && !(dwFlags&VERTICAL_FLIP)) {\r
-               if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
-                       for (y=0;y<GrpFrame->Height;y++) {\r
-                               RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
-                               x=0; ofs=0;\r
-                               while (x<GrpFrame->Width) {\r
-                                       if (!(RowData[ofs] & 0x80)) {\r
-                                               if (!(RowData[ofs] & 0x40)) {\r
-                                                       for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
-                                                               SetPix(hdcDest,nXDest+x,nYDest+y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
-                                                               x++;\r
-                                                       }\r
-                                                       ofs+=RowData[ofs]+1;\r
-                                               }\r
-                                               else {\r
-                                                       for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
-                                                               SetPix(hdcDest,nXDest+x,nYDest+y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
-                                                               x++;\r
-                                                       }\r
-                                                       ofs+=2;\r
-                                               }\r
-                                       }\r
-                                       else {\r
-                                               x+=RowData[ofs]-128;\r
-                                               ofs++;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               else {\r
-                       for (y=0;y<GrpFrame->Height;y++) {\r
-                               for (x=0;x<GrpFrame->Width;x++) {\r
-                                       SetPix(hdcDest,nXDest+x,nYDest+y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       else if (dwFlags&HORIZONTAL_FLIP && !(dwFlags&VERTICAL_FLIP)) {\r
-               if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
-                       for (y=0;y<GrpFrame->Height;y++) {\r
-                               RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
-                               x=0; ofs=0;\r
-                               while (x<GrpFrame->Width) {\r
-                                       if (!(RowData[ofs] & 0x80)) {\r
-                                               if (!(RowData[ofs] & 0x40)) {\r
-                                                       for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
-                                                               SetPix(hdcDest,Right-x,nYDest+y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
-                                                               x++;\r
-                                                       }\r
-                                                       ofs+=RowData[ofs]+1;\r
-                                               }\r
-                                               else {\r
-                                                       for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
-                                                               SetPix(hdcDest,Right-x,nYDest+y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
-                                                               x++;\r
-                                                       }\r
-                                                       ofs+=2;\r
-                                               }\r
-                                       }\r
-                                       else {\r
-                                               x+=RowData[ofs]-128;\r
-                                               ofs++;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               else {\r
-                       for (y=0;y<GrpFrame->Height;y++) {\r
-                               for (x=0;x<GrpFrame->Width;x++) {\r
-                                       SetPix(hdcDest,Right-x,nYDest+y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       else if (!(dwFlags&HORIZONTAL_FLIP) && dwFlags&VERTICAL_FLIP) {\r
-               if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
-                       for (y=0;y<GrpFrame->Height;y++) {\r
-                               RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
-                               x=0; ofs=0;\r
-                               while (x<GrpFrame->Width) {\r
-                                       if (!(RowData[ofs] & 0x80)) {\r
-                                               if (!(RowData[ofs] & 0x40)) {\r
-                                                       for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
-                                                               SetPix(hdcDest,nXDest+x,Bottom-y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
-                                                               x++;\r
-                                                       }\r
-                                                       ofs+=RowData[ofs]+1;\r
-                                               }\r
-                                               else {\r
-                                                       for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
-                                                               SetPix(hdcDest,nXDest+x,Bottom-y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
-                                                               x++;\r
-                                                       }\r
-                                                       ofs+=2;\r
-                                               }\r
-                                       }\r
-                                       else {\r
-                                               x+=RowData[ofs]-128;\r
-                                               ofs++;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               else {\r
-                       for (y=0;y<GrpFrame->Height;y++) {\r
-                               for (x=0;x<GrpFrame->Width;x++) {\r
-                                       SetPix(hdcDest,nXDest+x,Bottom-y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       else {\r
-               if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
-                       for (y=0;y<GrpFrame->Height;y++) {\r
-                               RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
-                               x=0; ofs=0;\r
-                               while (x<GrpFrame->Width) {\r
-                                       if (!(RowData[ofs] & 0x80)) {\r
-                                               if (!(RowData[ofs] & 0x40)) {\r
-                                                       for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
-                                                               SetPix(hdcDest,Right-x,Bottom-y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
-                                                               x++;\r
-                                                       }\r
-                                                       ofs+=RowData[ofs]+1;\r
-                                               }\r
-                                               else {\r
-                                                       for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
-                                                               SetPix(hdcDest,Right-x,Bottom-y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
-                                                               x++;\r
-                                                       }\r
-                                                       ofs+=2;\r
-                                               }\r
-                                       }\r
-                                       else {\r
-                                               x+=RowData[ofs]-128;\r
-                                               ofs++;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               else {\r
-                       for (y=0;y<GrpFrame->Height;y++) {\r
-                               for (x=0;x<GrpFrame->Width;x++) {\r
-                                       SetPix(hdcDest,Right-x,Bottom-y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       return TRUE;\r
-}\r
-\r
-BOOL GRPAPI WINAPI GetGrpInfo(HANDLE hGrp, GRPHEADER *GrpInfo)\r
-{\r
-       if (!hGrp || hGrp==INVALID_HANDLE_VALUE || !GrpInfo) return FALSE;\r
-       memcpy(GrpInfo,hGrp,6);\r
-       return TRUE;\r
-}\r
-\r
-BOOL GRPAPI WINAPI GetGrpFrameInfo(HANDLE hGrp, WORD nFrame, DWORD *nLeft, DWORD *nTop, DWORD *nWidth, DWORD *nHeight)\r
-{\r
-       if (!hGrp || hGrp==INVALID_HANDLE_VALUE) return FALSE;\r
-       FRAMEHEADER *GrpFrame = &((FRAMEHEADER *)(((char *)hGrp)+6))[nFrame];\r
-\r
-       if (nLeft) *nLeft = GrpFrame->Left;\r
-       if (nTop) *nTop = GrpFrame->Top;\r
-       if (nWidth) *nWidth = GrpFrame->Width;\r
-       if (nHeight) *nHeight = GrpFrame->Height;\r
-\r
-       return TRUE;\r
-}\r
-\r
-void GRPAPI WINAPI SetFunctionGetPixel(GETPIXELPROC lpGetPixelProc)\r
-{\r
-       if (!lpGetPixelProc)\r
-               MyGetPixel = GetPixel;\r
-       else\r
-               MyGetPixel = lpGetPixelProc;\r
-}\r
-\r
-void GRPAPI WINAPI SetFunctionSetPixel(SETPIXELPROC lpSetPixelProc)\r
-{\r
-       if (!lpSetPixelProc)\r
-               MySetPixel = (SETPIXELPROC)SetPixelV;\r
-       else\r
-               MySetPixel = lpSetPixelProc;\r
-}\r
-\r
-void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha)\r
-{\r
-       if (!(dwFlags&USE_INDEX)) {\r
-               if (dwFlags&SHADOW_COLOR) {\r
-                       clrColor = (dwFlags >> 8) & 0x00FFFFFF;\r
-               }\r
-               else {\r
-                       clrColor = dwPalette[clrColor];\r
-               }\r
-               if (dwFlags&ALPHA_BLEND) {\r
-                       DWORD dwColor = MyGetPixel(hDC,X,Y);\r
-\r
-                       // Old alpha\r
-                       /*((BYTE *)&dwColor)[0]*=1-((float)((BYTE *)&dwAlpha)[0]/256);\r
-                       ((BYTE *)&dwColor)[1]*=1-((float)((BYTE *)&dwAlpha)[1]/256);\r
-                       ((BYTE *)&dwColor)[2]*=1-((float)((BYTE *)&dwAlpha)[2]/256);\r
-                       ((BYTE *)&clrColor)[0]*=(float)((BYTE *)&dwAlpha)[0]/256;\r
-                       ((BYTE *)&clrColor)[1]*=(float)((BYTE *)&dwAlpha)[1]/256;\r
-                       ((BYTE *)&clrColor)[2]*=(float)((BYTE *)&dwAlpha)[2]/256;\r
-                       ((BYTE *)&clrColor)[0]+=((BYTE *)&dwColor)[0];\r
-                       ((BYTE *)&clrColor)[1]+=((BYTE *)&dwColor)[1];\r
-                       ((BYTE *)&clrColor)[2]+=((BYTE *)&dwColor)[2];*/\r
-\r
-                       /* blendedcolor =\r
-                                ( ( forecolor * ( 1 - alpha ) ) >> 8 )\r
-                          + ( ( backcolor * ( 256 - alpha ) ) >> 8 ) */\r
-                       ((BYTE *)&clrColor)[0] =\r
-                               ( ( ((BYTE *)&clrColor)[0] * ( ((BYTE *)&dwAlpha)[0] + 1 ) ) >> 8 )\r
-                               + ( ( ((BYTE *)&dwColor)[0] * ( 256 - ((BYTE *)&dwAlpha)[0] ) ) >> 8 );\r
-                       ((BYTE *)&clrColor)[1] =\r
-                               ( ( ((BYTE *)&clrColor)[1] * ( ((BYTE *)&dwAlpha)[1] + 1 ) ) >> 8 )\r
-                               + ( ( ((BYTE *)&dwColor)[1] * ( 256 - ((BYTE *)&dwAlpha)[1] ) ) >> 8 );\r
-                       ((BYTE *)&clrColor)[2] =\r
-                               ( ( ((BYTE *)&clrColor)[2] * ( ((BYTE *)&dwAlpha)[2] + 1 ) ) >> 8 )\r
-                               + ( ( ((BYTE *)&dwColor)[2] * ( 256 - ((BYTE *)&dwAlpha)[2] ) ) >> 8 );\r
-               }\r
-       }\r
-       MySetPixel(hDC,X,Y,clrColor);\r
-}\r
-\r
-HANDLE GRPAPI WINAPI CreateGrp(signed short *lpImageData, WORD nFrames, WORD wMaxWidth, WORD wMaxHeight, BOOL bNoCompress, DWORD *nGrpSize)\r
-{\r
-       GRPHEADER GrpHeader;\r
-       FRAMEHEADER *lpFrameHeaders;\r
-       FRAMEDATA *lpFrameData;\r
-       LPBYTE lpGrpData;\r
-       int i, j, x, y, x1, x2, y1, y2;\r
-       DWORD nLastOffset;\r
-\r
-       if (!lpImageData || !nGrpSize) return (HANDLE)-1;\r
-\r
-       GrpHeader.nFrames = nFrames;\r
-       GrpHeader.wMaxWidth = wMaxWidth;\r
-       GrpHeader.wMaxHeight = wMaxHeight;\r
-       lpFrameHeaders = (FRAMEHEADER *)malloc(nFrames * sizeof(FRAMEHEADER));\r
-       lpFrameData = (FRAMEDATA *)malloc(nFrames * sizeof(FRAMEDATA));\r
-       nLastOffset = sizeof(GRPHEADER) + nFrames * sizeof(FRAMEHEADER);\r
-\r
-       for (i = 0; i < nFrames; i++) {\r
-               lpFrameHeaders[i].Offset = nLastOffset;\r
-\r
-               // Scan frame to find dimensions of used part\r
-               x1 = y1 = 0x10000;\r
-               x2 = y2 = -1;\r
-               for (y = 0; y < wMaxHeight; y++) {\r
-                       for (x = 0; x < wMaxWidth; x++) {\r
-                               if (lpImageData[i * wMaxWidth * wMaxHeight + y * wMaxWidth + x] >= 0) {\r
-                                       if (x < x1) x1 = x;\r
-                                       if (x > x2) x2 = x;\r
-                                       if (y < y1) y1 = y;\r
-                                       if (y > y2) y2 = y;\r
-                               }\r
-                       }\r
-               }\r
-               x2 = x2 - x1 + 1;\r
-               y2 = y2 - y1 + 1;\r
-               if ((WORD)x1 > 255) x1 = 255;\r
-               if ((WORD)y1 > 255) y1 = 255;\r
-               if ((WORD)x2 > 255) x2 = 255;\r
-               if ((WORD)y2 > 255) y2 = 255;\r
-               lpFrameHeaders[i].Left = x1;\r
-               lpFrameHeaders[i].Top = y1;\r
-               lpFrameHeaders[i].Width = x2;\r
-               lpFrameHeaders[i].Height = y2;\r
-\r
-               // Search for duplicate frames\r
-               for (j = 0; j < i; j++) {\r
-                       if (lpFrameData[j].lpRowOffsets && lpFrameHeaders[i].Width == lpFrameHeaders[j].Width && lpFrameHeaders[i].Height == lpFrameHeaders[j].Height) {\r
-                               y1 = i * wMaxWidth * wMaxHeight + lpFrameHeaders[i].Top * wMaxWidth + lpFrameHeaders[i].Left;\r
-                               y2 = j * wMaxWidth * wMaxHeight + lpFrameHeaders[j].Top * wMaxWidth + lpFrameHeaders[j].Left;\r
-\r
-                               for (y = 0; y < lpFrameHeaders[i].Height; y++) {\r
-                                       if (memcmp(&lpImageData[y1], &lpImageData[y2], lpFrameHeaders[i].Width * sizeof(short)) != 0)\r
-                                               break;\r
-\r
-                                       y1 += wMaxWidth;\r
-                                       y2 += wMaxWidth;\r
-                               }\r
-\r
-                               if (y == lpFrameHeaders[i].Height) {\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               if (j < i) {\r
-                       // Duplicate frame found, set offset and flag as duplicate\r
-                       lpFrameHeaders[i].Offset = lpFrameHeaders[j].Offset;\r
-                       lpFrameData[i].lpRowOffsets = 0;\r
-                       lpFrameData[i].lpRowSizes = 0;\r
-                       lpFrameData[i].lpRowData = 0;\r
-                       lpFrameData[i].Size = 0;\r
-                       continue;\r
-               }\r
-\r
-               EncodeFrameData(lpImageData, i, &GrpHeader, &lpFrameHeaders[i], &lpFrameData[i], bNoCompress);\r
-               nLastOffset = lpFrameHeaders[i].Offset + lpFrameData[i].Size;\r
-       }\r
-\r
-       lpGrpData = (LPBYTE)malloc(nLastOffset);\r
-\r
-       // Write completed GRP to buffer\r
-       memcpy(lpGrpData, &GrpHeader, sizeof(GRPHEADER));\r
-       memcpy(lpGrpData + sizeof(GRPHEADER), lpFrameHeaders, nFrames * sizeof(FRAMEHEADER));\r
-\r
-       for (i = 0; i < nFrames; i++) {\r
-               if (lpFrameData[i].lpRowOffsets) {\r
-                       if (!bNoCompress)\r
-                               memcpy(lpGrpData + lpFrameHeaders[i].Offset, lpFrameData[i].lpRowOffsets, lpFrameHeaders[i].Height * sizeof(WORD));\r
-\r
-                       for (y = 0; y < lpFrameHeaders[i].Height; y++) {\r
-                               if (lpFrameData[i].lpRowData[y]) {\r
-                                       memcpy(lpGrpData + lpFrameHeaders[i].Offset + lpFrameData[i].lpRowOffsets[y], lpFrameData[i].lpRowData[y], lpFrameData[i].lpRowSizes[y]);\r
-                                       free(lpFrameData[i].lpRowData[y]);\r
-                               }\r
-                       }\r
-\r
-                       free(lpFrameData[i].lpRowOffsets);\r
-                       free(lpFrameData[i].lpRowSizes);\r
-                       free(lpFrameData[i].lpRowData);\r
-               }\r
-       }\r
-\r
-       free(lpFrameHeaders);\r
-       free(lpFrameData);\r
-\r
-       *nGrpSize = nLastOffset;\r
-       return (HANDLE)lpGrpData;\r
-}\r
-\r
-void EncodeFrameData(signed short *lpImageData, WORD nFrame, GRPHEADER *lpGrpHeader, FRAMEHEADER *lpFrameHeader, FRAMEDATA *lpFrameData, BOOL bNoCompress)\r
-{\r
-       int x, y, i, j, nBufPos, nRepeat;\r
-       LPBYTE lpRowBuf;\r
-       WORD nLastOffset = 0;\r
-\r
-       lpFrameData->lpRowOffsets = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));\r
-       lpFrameData->lpRowSizes = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));\r
-       lpFrameData->lpRowData = (LPBYTE *)malloc(lpFrameHeader->Height * sizeof(LPBYTE));\r
-       lpRowBuf = (LPBYTE)malloc(lpFrameHeader->Width * 2);\r
-\r
-       if (!bNoCompress)\r
-               nLastOffset = lpFrameHeader->Height * sizeof(WORD);\r
-\r
-       for (y = 0; y < lpFrameHeader->Height; y++) {\r
-               i = nFrame * lpGrpHeader->wMaxWidth * lpGrpHeader->wMaxHeight + (lpFrameHeader->Top + y) * lpGrpHeader->wMaxWidth;\r
-\r
-               if (!bNoCompress) {\r
-                       // Search for duplicate rows\r
-                       for (x = 0; x < y; x++) {\r
-                               j = nFrame * lpGrpHeader->wMaxWidth * lpGrpHeader->wMaxHeight + (lpFrameHeader->Top + x) * lpGrpHeader->wMaxWidth;\r
-                               if (memcmp(&lpImageData[i+lpFrameHeader->Left],\r
-                                                  &lpImageData[j+lpFrameHeader->Left],\r
-                                                  lpGrpHeader->wMaxWidth * sizeof(short)) == 0)\r
-                                       break;\r
-                       }\r
-\r
-                       if (x < y) {\r
-                               lpFrameData->lpRowOffsets[y] = lpFrameData->lpRowOffsets[x];\r
-                               lpFrameData->lpRowSizes[y] = 0;\r
-                               lpFrameData->lpRowData[y] = 0;\r
-\r
-#ifdef _DEBUG\r
-                               if (!VerifyRow(&lpImageData[i+lpFrameHeader->Left], lpFrameHeader->Width, lpFrameData->lpRowData[x], lpFrameData->lpRowSizes[x], bNoCompress)) {\r
-                                       nBufPos = nBufPos;\r
-                               }\r
-#endif\r
-\r
-                               continue;\r
-                       }\r
-               }\r
-\r
-               nBufPos = 0;\r
-               if (lpFrameHeader->Width > 0) {\r
-                       for (x = lpFrameHeader->Left; x < lpFrameHeader->Left + lpFrameHeader->Width; x++) {\r
-                               if (!bNoCompress) {\r
-                                       if (x < lpFrameHeader->Left + lpFrameHeader->Width - 1) {\r
-                                               if (lpImageData[i+x] < 0) {\r
-                                                       lpRowBuf[nBufPos] = 0x80;\r
-                                                       for (; lpImageData[i+x] < 0 && x < lpFrameHeader->Left + lpFrameHeader->Width && lpRowBuf[nBufPos] < 0xFF; x++) {\r
-                                                               lpRowBuf[nBufPos]++;\r
-                                                       }\r
-                                                       x--;\r
-                                                       if (nLastOffset + nBufPos + 1 <= 0xFFFF)\r
-                                                               nBufPos++;\r
-                                                       continue;\r
-                                               }\r
-\r
-                                               // Count repeating pixels, nRepeat = number of pixels - 1, ignore if there are less than 4 duplicates\r
-                                               for (nRepeat = 0; lpImageData[i+x+nRepeat] == lpImageData[i+x+nRepeat+1] && x+nRepeat < lpFrameHeader->Left + lpFrameHeader->Width - 1 && nRepeat < 0x3E; nRepeat++) {}\r
-\r
-                                               if (nRepeat > 2) {\r
-                                                       lpRowBuf[nBufPos] = 0x41 + nRepeat;\r
-                                                       lpRowBuf[nBufPos+1] = (BYTE)(lpImageData[i+x]);\r
-                                                       x += nRepeat;\r
-                                                       if (nLastOffset + nBufPos + 2 <= 0xFFFF)\r
-                                                               nBufPos += 2;\r
-                                               }\r
-                                               else {\r
-                                                       lpRowBuf[nBufPos] = 0;\r
-                                                       for (; lpImageData[i+x] >= 0 && x < lpFrameHeader->Left + lpFrameHeader->Width && lpRowBuf[nBufPos] < 0x3F; x++) {\r
-                                                               // Count repeating pixels, ignore if there are less than 4 duplicates\r
-                                                               for (nRepeat = 0; lpImageData[i+x+nRepeat] == lpImageData[i+x+nRepeat+1] && x+nRepeat < lpFrameHeader->Left + lpFrameHeader->Width - 1 && nRepeat < 3; nRepeat++) {}\r
-                                                               if (nRepeat > 2) break;\r
-\r
-                                                               lpRowBuf[nBufPos]++;\r
-                                                               lpRowBuf[nBufPos+lpRowBuf[nBufPos]] = (BYTE)(lpImageData[i+x]);\r
-                                                       }\r
-                                                       if (lpImageData[i+x] >= 0 && x == lpFrameHeader->Left + lpFrameHeader->Width - 1 && lpRowBuf[nBufPos] < 0x3F) {\r
-                                                               lpRowBuf[nBufPos]++;\r
-                                                               lpRowBuf[nBufPos+lpRowBuf[nBufPos]] = (BYTE)(lpImageData[i+x]);\r
-                                                       }\r
-                                                       x--;\r
-                                                       if (nLastOffset + nBufPos + 1 + lpRowBuf[nBufPos] <= 0xFFFF)\r
-                                                               nBufPos += 1 + lpRowBuf[nBufPos];\r
-                                               }\r
-                                       }\r
-                                       else {\r
-                                               if (lpImageData[i+x] < 0) {\r
-                                                       lpRowBuf[nBufPos] = 0x81;\r
-                                                       if (nLastOffset + nBufPos + 1 <= 0xFFFF)\r
-                                                               nBufPos++;\r
-                                               }\r
-                                               else {\r
-                                                       lpRowBuf[nBufPos] = 1;\r
-                                                       lpRowBuf[nBufPos+1] = (BYTE)(lpImageData[i+x]);\r
-                                                       if (nLastOffset + nBufPos + 2 <= 0xFFFF)\r
-                                                               nBufPos += 2;\r
-                                               }\r
-                                       }\r
-                               }\r
-                               else {\r
-                                       lpRowBuf[nBufPos] = (BYTE)(lpImageData[i+x]);\r
-                                       if (nLastOffset + nBufPos + 1 <= 0xFFFF)\r
-                                               nBufPos++;\r
-                               }\r
-                       }\r
-               }\r
-\r
-#ifdef _DEBUG\r
-               if (!VerifyRow(&lpImageData[i+lpFrameHeader->Left], lpFrameHeader->Width, lpRowBuf, nBufPos, bNoCompress)) {\r
-                       nBufPos = nBufPos;\r
-               }\r
-#endif\r
-\r
-               lpFrameData->lpRowOffsets[y] = nLastOffset;\r
-               nLastOffset = lpFrameData->lpRowOffsets[y] + nBufPos;\r
-\r
-               lpFrameData->lpRowSizes[y] = nBufPos;\r
-               lpFrameData->lpRowData[y] = (LPBYTE)malloc(nBufPos);\r
-               memcpy(lpFrameData->lpRowData[y], lpRowBuf, nBufPos);\r
-       }\r
-\r
-       lpFrameData->Size = nLastOffset;\r
-\r
-       free(lpRowBuf);\r
-}\r
-\r
-#ifdef _DEBUG\r
-BOOL VerifyRow(signed short *lpRawRow, int nWidth, LPBYTE lpEncRow, int nSize, BOOL bNoCompress)\r
-{\r
-       int i,x=0,ofs=0;\r
-       while (x < nWidth && ofs < nSize) {\r
-               if (!bNoCompress) {\r
-                       if (!(lpEncRow[ofs] & 0x80)) {\r
-                               if (!(lpEncRow[ofs] & 0x40)) {\r
-                                       for (i=1;i<=lpEncRow[ofs] && x<nWidth;i++) {\r
-                                               if (lpEncRow[ofs+i] != (BYTE)lpRawRow[x]) return FALSE;\r
-                                               x++;\r
-                                       }\r
-                                       ofs+=lpEncRow[ofs]+1;\r
-                               }\r
-                               else {\r
-                                       for (i=0;i<lpEncRow[ofs]-64 && x<nWidth;i++) {\r
-                                               if (lpEncRow[ofs+1] != (BYTE)lpRawRow[x]) return FALSE;\r
-                                               x++;\r
-                                       }\r
-                                       ofs+=2;\r
-                               }\r
-                       }\r
-                       else {\r
-                               for (i=0;i<lpEncRow[ofs]-128 && x<nWidth;i++) {\r
-                                       if (lpRawRow[x] >= 0) return FALSE;\r
-                               }\r
-                               x+=lpEncRow[ofs]-128;\r
-                               ofs++;\r
-                       }\r
-               }\r
-               else {\r
-                       if (lpEncRow[ofs] != (BYTE)lpRawRow[x]) return FALSE;\r
-                       x++;\r
-                       ofs++;\r
-               }\r
-       }\r
-\r
-       if (x != nWidth || ofs != nSize) return FALSE;\r
-\r
-       return TRUE;\r
-}\r
-#endif\r
+#include "grpapi.h"
+#include "../LoadStorm/storm.h"
+#include <malloc.h>
+
+#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;
+
+typedef struct {
+       WORD *lpRowOffsets;
+       WORD *lpRowSizes;
+       LPBYTE *lpRowData;
+       DWORD Size;
+} FRAMEDATA;
+
+GETPIXELPROC MyGetPixel = GetPixel;
+SETPIXELPROC MySetPixel = (SETPIXELPROC)SetPixelV;
+
+void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha);
+void EncodeFrameData(signed short *lpImageData, WORD nFrame, GRPHEADER *lpGrpHeader, FRAMEHEADER *lpFrameHeader, FRAMEDATA *lpFrameData, BOOL bNoCompress);
+BOOL VerifyRow(signed short *lpRawRow, int nWidth, LPBYTE lpEncRow, int nSize, BOOL bNoCompress);
+
+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) return FALSE;
+       else return TRUE;
+}
+
+void GRPAPI WINAPI FreeGrpApi()
+{
+}
+
+/*
+HANDLE hProcessHeap = NULL;
+
+void * SFAlloc(size_t nSize)
+{
+       if (!hProcessHeap) hProcessHeap = GetProcessHeap();
+       if (hProcessHeap) return HeapAlloc(hProcessHeap, 0, nSize);
+       else return NULL;
+}
+
+void SFFree(void *lpMem)
+{
+       if (!hProcessHeap) hProcessHeap = GetProcessHeap();
+       if (hProcessHeap) HeapFree(hProcessHeap, 0, lpMem);
+}
+*/
+
+BOOL GRPAPI WINAPI SetMpqDll(LPCSTR lpDllFileName)
+{
+       if (LoadStorm((char *)lpDllFileName)) return TRUE;
+       else return FALSE;
+}
+
+BOOL GRPAPI WINAPI LoadPalette(LPCSTR lpFileName, DWORD *dwPaletteBuffer)
+{
+       if (!lpFileName || !dwPaletteBuffer) return FALSE;
+       HANDLE hFile;
+       if (SFileOpenFileEx && SFileGetFileSize
+        && SFileSetFilePointer && SFileReadFile
+        && SFileCloseFile) {
+               if (!SFileOpenFileEx(0,lpFileName,1,&hFile)) 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) return (HANDLE)-1;
+       HANDLE hFile;
+       char *GrpFile;
+       if (SFileOpenFileEx && SFileGetFileSize
+        && SFileSetFilePointer && SFileReadFile
+        && SFileCloseFile) {
+               if (!SFileOpenFileEx(0,lpFileName,1,&hFile)) return (HANDLE)-1;
+               DWORD fsz = SFileGetFileSize(hFile,0);
+               if (fsz<6) {
+                       SFileCloseFile(hFile);
+                       return (HANDLE)-1;
+               }
+               GrpFile = (char *)malloc(fsz);
+               if (GrpFile) {
+                       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 *)malloc(fsz);
+               if (GrpFile) {
+                       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 || hGrp==INVALID_HANDLE_VALUE) return FALSE;
+       free(hGrp);
+       return TRUE;
+}
+
+BOOL GRPAPI WINAPI DrawGrp(HANDLE hGrp, HDC hdcDest, int nXDest, int nYDest, WORD nFrame, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha)
+{
+       if (!hGrp || hGrp==INVALID_HANDLE_VALUE || hdcDest==0 || (!dwPalette && !(dwFlags&USE_INDEX))) return FALSE;
+       GRPHEADER *GrpFile = (GRPHEADER *)hGrp;
+       nFrame %= GrpFile->nFrames;
+       FRAMEHEADER *GrpFrame = &((FRAMEHEADER *)(((char *)GrpFile)+6))[nFrame];
+       FRAMEHEADER *GrpFrames = &((FRAMEHEADER *)(((char *)GrpFile)+6))[0];
+       int FrameSize = 0xFFFFFF;
+       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));
+       BYTE *GrpRaw = (BYTE *)GrpOffsets;
+       BYTE *RowData;
+       WORD x,ofs;
+       DWORD y, nMaxOffset = 0;
+       WORD i;
+       int j, nFirstNonBlankFrame = 0;
+       for (i = 0; i < GrpFile->nFrames; i++) {
+               j = GrpFrames[i].Offset - GrpFrame->Offset;
+               if (j > 0 && j < FrameSize)
+                       FrameSize = j;
+               if (GrpFrames[i].Offset > nMaxOffset)
+                       nMaxOffset = GrpFrames[i].Offset;
+       }
+       if (FrameSize == 0xFFFFFF || FrameSize == GrpFrame->Width * GrpFrame->Height) {
+               FrameSize = 0xFFFFFF;
+               for (i = 0; i < GrpFile->nFrames; i++) {
+                       if (GrpFrames[i].Width != 0 && GrpFrames[i].Height != 0 && GrpFrames[i].Offset != GrpFrame->Offset && GrpFrames[i].Offset != nMaxOffset) {
+                               nFirstNonBlankFrame = i;
+                               break;
+                       }
+               }
+               if (i == GrpFile->nFrames)
+                       nFirstNonBlankFrame = nFrame;
+
+               for (i = 0; i < GrpFile->nFrames; i++) {
+                       j = GrpFrames[i].Offset - GrpFrames[nFirstNonBlankFrame].Offset;
+                       if (j > 0 && j < FrameSize)
+                               FrameSize = j;
+               }
+               if (FrameSize == GrpFrames[nFirstNonBlankFrame].Width * GrpFrames[nFirstNonBlankFrame].Height)
+                       FrameSize = GrpFrame->Width * GrpFrame->Height;
+       }
+       if (!(dwFlags&HORIZONTAL_FLIP) && !(dwFlags&VERTICAL_FLIP)) {
+               if (FrameSize != GrpFrame->Width * GrpFrame->Height) {
+                       for (y=0;y<GrpFrame->Height;y++) {
+                               RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));
+                               x=0; ofs=0;
+                               while (x<GrpFrame->Width) {
+                                       if (!(RowData[ofs] & 0x80)) {
+                                               if (!(RowData[ofs] & 0x40)) {
+                                                       for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {
+                                                               SetPix(hdcDest,nXDest+x,nYDest+y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);
+                                                               x++;
+                                                       }
+                                                       ofs+=RowData[ofs]+1;
+                                               }
+                                               else {
+                                                       for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {
+                                                               SetPix(hdcDest,nXDest+x,nYDest+y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);
+                                                               x++;
+                                                       }
+                                                       ofs+=2;
+                                               }
+                                       }
+                                       else {
+                                               x+=RowData[ofs]-128;
+                                               ofs++;
+                                       }
+                               }
+                       }
+               }
+               else {
+                       for (y=0;y<GrpFrame->Height;y++) {
+                               for (x=0;x<GrpFrame->Width;x++) {
+                                       SetPix(hdcDest,nXDest+x,nYDest+y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);
+                               }
+                       }
+               }
+       }
+       else if (dwFlags&HORIZONTAL_FLIP && !(dwFlags&VERTICAL_FLIP)) {
+               if (FrameSize != GrpFrame->Width * GrpFrame->Height) {
+                       for (y=0;y<GrpFrame->Height;y++) {
+                               RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));
+                               x=0; ofs=0;
+                               while (x<GrpFrame->Width) {
+                                       if (!(RowData[ofs] & 0x80)) {
+                                               if (!(RowData[ofs] & 0x40)) {
+                                                       for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {
+                                                               SetPix(hdcDest,Right-x,nYDest+y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);
+                                                               x++;
+                                                       }
+                                                       ofs+=RowData[ofs]+1;
+                                               }
+                                               else {
+                                                       for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {
+                                                               SetPix(hdcDest,Right-x,nYDest+y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);
+                                                               x++;
+                                                       }
+                                                       ofs+=2;
+                                               }
+                                       }
+                                       else {
+                                               x+=RowData[ofs]-128;
+                                               ofs++;
+                                       }
+                               }
+                       }
+               }
+               else {
+                       for (y=0;y<GrpFrame->Height;y++) {
+                               for (x=0;x<GrpFrame->Width;x++) {
+                                       SetPix(hdcDest,Right-x,nYDest+y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);
+                               }
+                       }
+               }
+       }
+       else if (!(dwFlags&HORIZONTAL_FLIP) && dwFlags&VERTICAL_FLIP) {
+               if (FrameSize != GrpFrame->Width * GrpFrame->Height) {
+                       for (y=0;y<GrpFrame->Height;y++) {
+                               RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));
+                               x=0; ofs=0;
+                               while (x<GrpFrame->Width) {
+                                       if (!(RowData[ofs] & 0x80)) {
+                                               if (!(RowData[ofs] & 0x40)) {
+                                                       for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {
+                                                               SetPix(hdcDest,nXDest+x,Bottom-y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);
+                                                               x++;
+                                                       }
+                                                       ofs+=RowData[ofs]+1;
+                                               }
+                                               else {
+                                                       for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {
+                                                               SetPix(hdcDest,nXDest+x,Bottom-y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);
+                                                               x++;
+                                                       }
+                                                       ofs+=2;
+                                               }
+                                       }
+                                       else {
+                                               x+=RowData[ofs]-128;
+                                               ofs++;
+                                       }
+                               }
+                       }
+               }
+               else {
+                       for (y=0;y<GrpFrame->Height;y++) {
+                               for (x=0;x<GrpFrame->Width;x++) {
+                                       SetPix(hdcDest,nXDest+x,Bottom-y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);
+                               }
+                       }
+               }
+       }
+       else {
+               if (FrameSize != GrpFrame->Width * GrpFrame->Height) {
+                       for (y=0;y<GrpFrame->Height;y++) {
+                               RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));
+                               x=0; ofs=0;
+                               while (x<GrpFrame->Width) {
+                                       if (!(RowData[ofs] & 0x80)) {
+                                               if (!(RowData[ofs] & 0x40)) {
+                                                       for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {
+                                                               SetPix(hdcDest,Right-x,Bottom-y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);
+                                                               x++;
+                                                       }
+                                                       ofs+=RowData[ofs]+1;
+                                               }
+                                               else {
+                                                       for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {
+                                                               SetPix(hdcDest,Right-x,Bottom-y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);
+                                                               x++;
+                                                       }
+                                                       ofs+=2;
+                                               }
+                                       }
+                                       else {
+                                               x+=RowData[ofs]-128;
+                                               ofs++;
+                                       }
+                               }
+                       }
+               }
+               else {
+                       for (y=0;y<GrpFrame->Height;y++) {
+                               for (x=0;x<GrpFrame->Width;x++) {
+                                       SetPix(hdcDest,Right-x,Bottom-y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);
+                               }
+                       }
+               }
+       }
+       return TRUE;
+}
+
+BOOL GRPAPI WINAPI GetGrpInfo(HANDLE hGrp, GRPHEADER *GrpInfo)
+{
+       if (!hGrp || hGrp==INVALID_HANDLE_VALUE || !GrpInfo) return FALSE;
+       memcpy(GrpInfo,hGrp,6);
+       return TRUE;
+}
+
+BOOL GRPAPI WINAPI GetGrpFrameInfo(HANDLE hGrp, WORD nFrame, DWORD *nLeft, DWORD *nTop, DWORD *nWidth, DWORD *nHeight)
+{
+       if (!hGrp || hGrp==INVALID_HANDLE_VALUE) return FALSE;
+       FRAMEHEADER *GrpFrame = &((FRAMEHEADER *)(((char *)hGrp)+6))[nFrame];
+
+       if (nLeft) *nLeft = GrpFrame->Left;
+       if (nTop) *nTop = GrpFrame->Top;
+       if (nWidth) *nWidth = GrpFrame->Width;
+       if (nHeight) *nHeight = GrpFrame->Height;
+
+       return TRUE;
+}
+
+void GRPAPI WINAPI SetFunctionGetPixel(GETPIXELPROC lpGetPixelProc)
+{
+       if (!lpGetPixelProc)
+               MyGetPixel = GetPixel;
+       else
+               MyGetPixel = lpGetPixelProc;
+}
+
+void GRPAPI WINAPI SetFunctionSetPixel(SETPIXELPROC lpSetPixelProc)
+{
+       if (!lpSetPixelProc)
+               MySetPixel = (SETPIXELPROC)SetPixelV;
+       else
+               MySetPixel = lpSetPixelProc;
+}
+
+void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha)
+{
+       if (!(dwFlags&USE_INDEX)) {
+               if (dwFlags&SHADOW_COLOR) {
+                       clrColor = (dwFlags >> 8) & 0x00FFFFFF;
+               }
+               else {
+                       clrColor = dwPalette[clrColor];
+               }
+               if (dwFlags&ALPHA_BLEND) {
+                       DWORD dwColor = MyGetPixel(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 );
+               }
+       }
+       MySetPixel(hDC,X,Y,clrColor);
+}
+
+HANDLE GRPAPI WINAPI CreateGrp(signed short *lpImageData, WORD nFrames, WORD wMaxWidth, WORD wMaxHeight, BOOL bNoCompress, DWORD *nGrpSize)
+{
+       GRPHEADER GrpHeader;
+       FRAMEHEADER *lpFrameHeaders;
+       FRAMEDATA *lpFrameData;
+       LPBYTE lpGrpData;
+       int i, j, x, y, x1, x2, y1, y2;
+       DWORD nLastOffset;
+
+       if (!lpImageData || !nGrpSize) return (HANDLE)-1;
+
+       GrpHeader.nFrames = nFrames;
+       GrpHeader.wMaxWidth = wMaxWidth;
+       GrpHeader.wMaxHeight = wMaxHeight;
+       lpFrameHeaders = (FRAMEHEADER *)malloc(nFrames * sizeof(FRAMEHEADER));
+       lpFrameData = (FRAMEDATA *)malloc(nFrames * sizeof(FRAMEDATA));
+       nLastOffset = sizeof(GRPHEADER) + nFrames * sizeof(FRAMEHEADER);
+
+       for (i = 0; i < nFrames; i++) {
+               lpFrameHeaders[i].Offset = nLastOffset;
+
+               // Scan frame to find dimensions of used part
+               x1 = y1 = 0x10000;
+               x2 = y2 = -1;
+               for (y = 0; y < wMaxHeight; y++) {
+                       for (x = 0; x < wMaxWidth; x++) {
+                               if (lpImageData[i * wMaxWidth * wMaxHeight + y * wMaxWidth + x] >= 0) {
+                                       if (x < x1) x1 = x;
+                                       if (x > x2) x2 = x;
+                                       if (y < y1) y1 = y;
+                                       if (y > y2) y2 = y;
+                               }
+                       }
+               }
+               x2 = x2 - x1 + 1;
+               y2 = y2 - y1 + 1;
+               if ((WORD)x1 > 255) x1 = 255;
+               if ((WORD)y1 > 255) y1 = 255;
+               if ((WORD)x2 > 255) x2 = 255;
+               if ((WORD)y2 > 255) y2 = 255;
+               lpFrameHeaders[i].Left = x1;
+               lpFrameHeaders[i].Top = y1;
+               lpFrameHeaders[i].Width = x2;
+               lpFrameHeaders[i].Height = y2;
+
+               // Search for duplicate frames
+               for (j = 0; j < i; j++) {
+                       if (lpFrameData[j].lpRowOffsets && lpFrameHeaders[i].Width == lpFrameHeaders[j].Width && lpFrameHeaders[i].Height == lpFrameHeaders[j].Height) {
+                               y1 = i * wMaxWidth * wMaxHeight + lpFrameHeaders[i].Top * wMaxWidth + lpFrameHeaders[i].Left;
+                               y2 = j * wMaxWidth * wMaxHeight + lpFrameHeaders[j].Top * wMaxWidth + lpFrameHeaders[j].Left;
+
+                               for (y = 0; y < lpFrameHeaders[i].Height; y++) {
+                                       if (memcmp(&lpImageData[y1], &lpImageData[y2], lpFrameHeaders[i].Width * sizeof(short)) != 0)
+                                               break;
+
+                                       y1 += wMaxWidth;
+                                       y2 += wMaxWidth;
+                               }
+
+                               if (y == lpFrameHeaders[i].Height) {
+                                       break;
+                               }
+                       }
+               }
+
+               if (j < i) {
+                       // Duplicate frame found, set offset and flag as duplicate
+                       lpFrameHeaders[i].Offset = lpFrameHeaders[j].Offset;
+                       lpFrameData[i].lpRowOffsets = 0;
+                       lpFrameData[i].lpRowSizes = 0;
+                       lpFrameData[i].lpRowData = 0;
+                       lpFrameData[i].Size = 0;
+                       continue;
+               }
+
+               EncodeFrameData(lpImageData, i, &GrpHeader, &lpFrameHeaders[i], &lpFrameData[i], bNoCompress);
+               nLastOffset = lpFrameHeaders[i].Offset + lpFrameData[i].Size;
+       }
+
+       lpGrpData = (LPBYTE)malloc(nLastOffset);
+
+       // Write completed GRP to buffer
+       memcpy(lpGrpData, &GrpHeader, sizeof(GRPHEADER));
+       memcpy(lpGrpData + sizeof(GRPHEADER), lpFrameHeaders, nFrames * sizeof(FRAMEHEADER));
+
+       for (i = 0; i < nFrames; i++) {
+               if (lpFrameData[i].lpRowOffsets) {
+                       if (!bNoCompress)
+                               memcpy(lpGrpData + lpFrameHeaders[i].Offset, lpFrameData[i].lpRowOffsets, lpFrameHeaders[i].Height * sizeof(WORD));
+
+                       for (y = 0; y < lpFrameHeaders[i].Height; y++) {
+                               if (lpFrameData[i].lpRowData[y]) {
+                                       memcpy(lpGrpData + lpFrameHeaders[i].Offset + lpFrameData[i].lpRowOffsets[y], lpFrameData[i].lpRowData[y], lpFrameData[i].lpRowSizes[y]);
+                                       free(lpFrameData[i].lpRowData[y]);
+                               }
+                       }
+
+                       free(lpFrameData[i].lpRowOffsets);
+                       free(lpFrameData[i].lpRowSizes);
+                       free(lpFrameData[i].lpRowData);
+               }
+       }
+
+       free(lpFrameHeaders);
+       free(lpFrameData);
+
+       *nGrpSize = nLastOffset;
+       return (HANDLE)lpGrpData;
+}
+
+void EncodeFrameData(signed short *lpImageData, WORD nFrame, GRPHEADER *lpGrpHeader, FRAMEHEADER *lpFrameHeader, FRAMEDATA *lpFrameData, BOOL bNoCompress)
+{
+       int x, y, i, j, nBufPos, nRepeat;
+       LPBYTE lpRowBuf;
+       WORD nLastOffset = 0;
+
+       lpFrameData->lpRowOffsets = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));
+       lpFrameData->lpRowSizes = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));
+       lpFrameData->lpRowData = (LPBYTE *)malloc(lpFrameHeader->Height * sizeof(LPBYTE));
+       lpRowBuf = (LPBYTE)malloc(lpFrameHeader->Width * 2);
+
+       if (!bNoCompress)
+               nLastOffset = lpFrameHeader->Height * sizeof(WORD);
+
+       for (y = 0; y < lpFrameHeader->Height; y++) {
+               i = nFrame * lpGrpHeader->wMaxWidth * lpGrpHeader->wMaxHeight + (lpFrameHeader->Top + y) * lpGrpHeader->wMaxWidth;
+
+               if (!bNoCompress) {
+                       // Search for duplicate rows
+                       for (x = 0; x < y; x++) {
+                               j = nFrame * lpGrpHeader->wMaxWidth * lpGrpHeader->wMaxHeight + (lpFrameHeader->Top + x) * lpGrpHeader->wMaxWidth;
+                               if (memcmp(&lpImageData[i+lpFrameHeader->Left],
+                                                  &lpImageData[j+lpFrameHeader->Left],
+                                                  lpGrpHeader->wMaxWidth * sizeof(short)) == 0)
+                                       break;
+                       }
+
+                       if (x < y) {
+                               lpFrameData->lpRowOffsets[y] = lpFrameData->lpRowOffsets[x];
+                               lpFrameData->lpRowSizes[y] = 0;
+                               lpFrameData->lpRowData[y] = 0;
+
+#ifdef _DEBUG
+                               if (!VerifyRow(&lpImageData[i+lpFrameHeader->Left], lpFrameHeader->Width, lpFrameData->lpRowData[x], lpFrameData->lpRowSizes[x], bNoCompress)) {
+                                       nBufPos = nBufPos;
+                               }
+#endif
+
+                               continue;
+                       }
+               }
+
+               nBufPos = 0;
+               if (lpFrameHeader->Width > 0) {
+                       for (x = lpFrameHeader->Left; x < lpFrameHeader->Left + lpFrameHeader->Width; x++) {
+                               if (!bNoCompress) {
+                                       if (x < lpFrameHeader->Left + lpFrameHeader->Width - 1) {
+                                               if (lpImageData[i+x] < 0) {
+                                                       lpRowBuf[nBufPos] = 0x80;
+                                                       for (; lpImageData[i+x] < 0 && x < lpFrameHeader->Left + lpFrameHeader->Width && lpRowBuf[nBufPos] < 0xFF; x++) {
+                                                               lpRowBuf[nBufPos]++;
+                                                       }
+                                                       x--;
+                                                       if (nLastOffset + nBufPos + 1 <= 0xFFFF)
+                                                               nBufPos++;
+                                                       continue;
+                                               }
+
+                                               // Count repeating pixels, nRepeat = number of pixels - 1, ignore if there are less than 4 duplicates
+                                               for (nRepeat = 0; lpImageData[i+x+nRepeat] == lpImageData[i+x+nRepeat+1] && x+nRepeat < lpFrameHeader->Left + lpFrameHeader->Width - 1 && nRepeat < 0x3E; nRepeat++) {}
+
+                                               if (nRepeat > 2) {
+                                                       lpRowBuf[nBufPos] = 0x41 + nRepeat;
+                                                       lpRowBuf[nBufPos+1] = (BYTE)(lpImageData[i+x]);
+                                                       x += nRepeat;
+                                                       if (nLastOffset + nBufPos + 2 <= 0xFFFF)
+                                                               nBufPos += 2;
+                                               }
+                                               else {
+                                                       lpRowBuf[nBufPos] = 0;
+                                                       for (; lpImageData[i+x] >= 0 && x < lpFrameHeader->Left + lpFrameHeader->Width && lpRowBuf[nBufPos] < 0x3F; x++) {
+                                                               // Count repeating pixels, ignore if there are less than 4 duplicates
+                                                               for (nRepeat = 0; lpImageData[i+x+nRepeat] == lpImageData[i+x+nRepeat+1] && x+nRepeat < lpFrameHeader->Left + lpFrameHeader->Width - 1 && nRepeat < 3; nRepeat++) {}
+                                                               if (nRepeat > 2) break;
+
+                                                               lpRowBuf[nBufPos]++;
+                                                               lpRowBuf[nBufPos+lpRowBuf[nBufPos]] = (BYTE)(lpImageData[i+x]);
+                                                       }
+                                                       if (lpImageData[i+x] >= 0 && x == lpFrameHeader->Left + lpFrameHeader->Width - 1 && lpRowBuf[nBufPos] < 0x3F) {
+                                                               lpRowBuf[nBufPos]++;
+                                                               lpRowBuf[nBufPos+lpRowBuf[nBufPos]] = (BYTE)(lpImageData[i+x]);
+                                                       }
+                                                       x--;
+                                                       if (nLastOffset + nBufPos + 1 + lpRowBuf[nBufPos] <= 0xFFFF)
+                                                               nBufPos += 1 + lpRowBuf[nBufPos];
+                                               }
+                                       }
+                                       else {
+                                               if (lpImageData[i+x] < 0) {
+                                                       lpRowBuf[nBufPos] = 0x81;
+                                                       if (nLastOffset + nBufPos + 1 <= 0xFFFF)
+                                                               nBufPos++;
+                                               }
+                                               else {
+                                                       lpRowBuf[nBufPos] = 1;
+                                                       lpRowBuf[nBufPos+1] = (BYTE)(lpImageData[i+x]);
+                                                       if (nLastOffset + nBufPos + 2 <= 0xFFFF)
+                                                               nBufPos += 2;
+                                               }
+                                       }
+                               }
+                               else {
+                                       lpRowBuf[nBufPos] = (BYTE)(lpImageData[i+x]);
+                                       if (nLastOffset + nBufPos + 1 <= 0xFFFF)
+                                               nBufPos++;
+                               }
+                       }
+               }
+
+#ifdef _DEBUG
+               if (!VerifyRow(&lpImageData[i+lpFrameHeader->Left], lpFrameHeader->Width, lpRowBuf, nBufPos, bNoCompress)) {
+                       nBufPos = nBufPos;
+               }
+#endif
+
+               lpFrameData->lpRowOffsets[y] = nLastOffset;
+               nLastOffset = lpFrameData->lpRowOffsets[y] + nBufPos;
+
+               lpFrameData->lpRowSizes[y] = nBufPos;
+               lpFrameData->lpRowData[y] = (LPBYTE)malloc(nBufPos);
+               memcpy(lpFrameData->lpRowData[y], lpRowBuf, nBufPos);
+       }
+
+       lpFrameData->Size = nLastOffset;
+
+       free(lpRowBuf);
+}
+
+#ifdef _DEBUG
+BOOL VerifyRow(signed short *lpRawRow, int nWidth, LPBYTE lpEncRow, int nSize, BOOL bNoCompress)
+{
+       int i,x=0,ofs=0;
+       while (x < nWidth && ofs < nSize) {
+               if (!bNoCompress) {
+                       if (!(lpEncRow[ofs] & 0x80)) {
+                               if (!(lpEncRow[ofs] & 0x40)) {
+                                       for (i=1;i<=lpEncRow[ofs] && x<nWidth;i++) {
+                                               if (lpEncRow[ofs+i] != (BYTE)lpRawRow[x]) return FALSE;
+                                               x++;
+                                       }
+                                       ofs+=lpEncRow[ofs]+1;
+                               }
+                               else {
+                                       for (i=0;i<lpEncRow[ofs]-64 && x<nWidth;i++) {
+                                               if (lpEncRow[ofs+1] != (BYTE)lpRawRow[x]) return FALSE;
+                                               x++;
+                                       }
+                                       ofs+=2;
+                               }
+                       }
+                       else {
+                               for (i=0;i<lpEncRow[ofs]-128 && x<nWidth;i++) {
+                                       if (lpRawRow[x] >= 0) return FALSE;
+                               }
+                               x+=lpEncRow[ofs]-128;
+                               ofs++;
+                       }
+               }
+               else {
+                       if (lpEncRow[ofs] != (BYTE)lpRawRow[x]) return FALSE;
+                       x++;
+                       ofs++;
+               }
+       }
+
+       if (x != nWidth || ofs != nSize) return FALSE;
+
+       return TRUE;
+}
+#endif