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




3de6be8cb7d619c1d9df30ebb712dca7c9480076
1 #include "grpapi.h"\r
2 #include "../LoadStorm/storm.h"\r
3 #include <malloc.h>\r
4 \r
5 #ifdef GRPAPI_STATIC\r
6 #define DllMain GrpMain\r
7 \r
8 #include "grp_static.h"\r
9 \r
10 struct GRPLIBMODULE {\r
11         GRPLIBMODULE();\r
12         ~GRPLIBMODULE();\r
13 } GrpLib;\r
14 \r
15 BOOL APIENTRY DllMain(HINSTANCE hInstDLL, DWORD  ul_reason_for_call, LPVOID lpReserved);\r
16 \r
17 GRPLIBMODULE::GRPLIBMODULE()\r
18 {\r
19         GrpMain(0,DLL_PROCESS_ATTACH,0);\r
20 }\r
21 \r
22 GRPLIBMODULE::~GRPLIBMODULE()\r
23 {\r
24         GrpMain(0,DLL_PROCESS_DETACH,0);\r
25 }\r
26 \r
27 #endif\r
28 \r
29 typedef struct {\r
30         BYTE Left;\r
31         BYTE Top;\r
32         BYTE Width;\r
33         BYTE Height;\r
34         DWORD Offset;\r
35 } FRAMEHEADER;\r
36 \r
37 typedef struct {\r
38         WORD *lpRowOffsets;\r
39         WORD *lpRowSizes;\r
40         LPBYTE *lpRowData;\r
41 } FRAMEDATA;\r
42 \r
43 GETPIXELPROC MyGetPixel = GetPixel;\r
44 SETPIXELPROC MySetPixel = (SETPIXELPROC)SetPixelV;\r
45 \r
46 void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha);\r
47 void EncodeFrameData(signed short *lpImageData, WORD nFrame, GRPHEADER *lpGrpHeader, FRAMEHEADER *lpFrameHeader, FRAMEDATA *lpFrameData);\r
48 \r
49 extern HINSTANCE hStorm;\r
50 \r
51 BOOL APIENTRY DllMain( HINSTANCE hInstDLL, \r
52                        DWORD  ul_reason_for_call, \r
53                        LPVOID lpReserved\r
54                                          )\r
55 {\r
56     switch (ul_reason_for_call)\r
57         {\r
58                 case DLL_PROCESS_ATTACH:\r
59                         break;\r
60                 case DLL_THREAD_ATTACH:\r
61                         break;\r
62                 case DLL_THREAD_DETACH:\r
63                         break;\r
64                 case DLL_PROCESS_DETACH:\r
65                         break;\r
66     }\r
67 \r
68     return TRUE;\r
69 }\r
70 \r
71 BOOL GRPAPI WINAPI LoadGrpApi()\r
72 {\r
73         if (!hStorm) return FALSE;\r
74         else return TRUE;\r
75 }\r
76 \r
77 void GRPAPI WINAPI FreeGrpApi()\r
78 {\r
79 }\r
80 \r
81 BOOL GRPAPI WINAPI SetMpqDll(LPCSTR lpDllFileName)\r
82 {\r
83         if (LoadStorm((char *)lpDllFileName)) return TRUE;\r
84         else return FALSE;\r
85 }\r
86 \r
87 BOOL GRPAPI WINAPI LoadPalette(LPCSTR lpFileName, DWORD *dwPaletteBuffer)\r
88 {\r
89         if (!lpFileName || !dwPaletteBuffer) return FALSE;\r
90         HANDLE hFile;\r
91         if (SFileOpenFileEx && SFileGetFileSize\r
92          && SFileSetFilePointer && SFileReadFile\r
93          && SFileCloseFile) {\r
94                 if (!SFileOpenFileEx(0,lpFileName,1,&hFile)) return FALSE;\r
95                 DWORD fsz = SFileGetFileSize(hFile,0);\r
96                 SFileSetFilePointer(hFile,0,0,FILE_BEGIN);\r
97                 if (fsz>=1024) {\r
98                         memset(dwPaletteBuffer,0,1024);\r
99                         SFileReadFile(hFile,dwPaletteBuffer,1024,0,0);\r
100                 }\r
101                 else if (fsz==768) {\r
102                         char *buffer = (char *)_alloca(768);\r
103                         memset(buffer,0,768);\r
104                         SFileReadFile(hFile,buffer,768,0,0);\r
105                         for (DWORD i=0;i<256;i++) {\r
106                                 memcpy(&dwPaletteBuffer[i],buffer+i*3,3);\r
107                                 *(((char *)&dwPaletteBuffer[i])+3) = 0;\r
108                         }\r
109                 }\r
110                 else {\r
111                         memset(dwPaletteBuffer,0,1024);\r
112                         SFileReadFile(hFile,dwPaletteBuffer,fsz,0,0);\r
113                 }\r
114                 SFileCloseFile(hFile);\r
115         }\r
116         else {\r
117                 hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);\r
118                 if (hFile==INVALID_HANDLE_VALUE) return FALSE;\r
119                 DWORD fsz = GetFileSize(hFile,0),tsz;\r
120                 SetFilePointer(hFile,0,0,FILE_BEGIN);\r
121                 if (fsz>=1024) {\r
122                         memset(dwPaletteBuffer,0,1024);\r
123                         ReadFile(hFile,dwPaletteBuffer,1024,&tsz,0);\r
124                 }\r
125                 else if (fsz==768) {\r
126                         char *buffer = (char *)_alloca(768);\r
127                         memset(buffer,0,768);\r
128                         ReadFile(hFile,buffer,768,&tsz,0);\r
129                         for (DWORD i=0;i<256;i++) {\r
130                                 memcpy(&dwPaletteBuffer[i],buffer+i*3,3);\r
131                                 *(((char *)&dwPaletteBuffer[i])+3) = 0;\r
132                         }\r
133                 }\r
134                 else {\r
135                         memset(dwPaletteBuffer,0,1024);\r
136                         ReadFile(hFile,dwPaletteBuffer,fsz,&tsz,0);\r
137                 }\r
138                 CloseHandle(hFile);\r
139         }\r
140         return TRUE;\r
141 }\r
142 \r
143 HANDLE GRPAPI WINAPI LoadGrp(LPCSTR lpFileName)\r
144 {\r
145         if (!lpFileName) return (HANDLE)-1;\r
146         HANDLE hFile;\r
147         char *GrpFile;\r
148         if (SFileOpenFileEx && SFileGetFileSize\r
149          && SFileSetFilePointer && SFileReadFile\r
150          && SFileCloseFile) {\r
151                 if (!SFileOpenFileEx(0,lpFileName,1,&hFile)) return (HANDLE)-1;\r
152                 DWORD fsz = SFileGetFileSize(hFile,0);\r
153                 if (fsz<6) {\r
154                         SFileCloseFile(hFile);\r
155                         return (HANDLE)-1;\r
156                 }\r
157                 GrpFile = (char *)malloc(fsz);\r
158                 if (GrpFile) {\r
159                         SFileSetFilePointer(hFile,0,0,FILE_BEGIN);\r
160                         SFileReadFile(hFile,GrpFile,fsz,0,0);\r
161                 }\r
162                 else GrpFile=(char *)-1;\r
163                 SFileCloseFile(hFile);\r
164         }\r
165         else {\r
166                 hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);\r
167                 if (hFile==INVALID_HANDLE_VALUE) return (HANDLE)-1;\r
168                 DWORD fsz = GetFileSize(hFile,0),tsz;\r
169                 if (fsz<6) {\r
170                         CloseHandle(hFile);\r
171                         return (HANDLE)-1;\r
172                 }\r
173                 GrpFile = (char *)malloc(fsz);\r
174                 if (GrpFile) {\r
175                         SetFilePointer(hFile,0,0,FILE_BEGIN);\r
176                         ReadFile(hFile,GrpFile,fsz,&tsz,0);\r
177                 }\r
178                 else GrpFile=(char *)-1;\r
179                 CloseHandle(hFile);\r
180         }\r
181         return (HANDLE)GrpFile;\r
182 }\r
183 \r
184 BOOL GRPAPI WINAPI DestroyGrp(HANDLE hGrp)\r
185 {\r
186         if (!hGrp || hGrp==INVALID_HANDLE_VALUE) return FALSE;\r
187         free(hGrp);\r
188         return TRUE;\r
189 }\r
190 \r
191 BOOL GRPAPI WINAPI DrawGrp(HANDLE hGrp, HDC hdcDest, int nXDest, int nYDest, WORD nFrame, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha)\r
192 {\r
193         if (!hGrp || hGrp==INVALID_HANDLE_VALUE || hdcDest==0 || (!dwPalette && !(dwFlags&USE_INDEX))) return FALSE;\r
194         GRPHEADER *GrpFile = (GRPHEADER *)hGrp;\r
195         nFrame %= GrpFile->nFrames;\r
196         FRAMEHEADER *GrpFrame = &((FRAMEHEADER *)(((char *)GrpFile)+6))[nFrame];\r
197         FRAMEHEADER *GrpFrames = &((FRAMEHEADER *)(((char *)GrpFile)+6))[0];\r
198         int FrameSize = 0xFFFFFF;\r
199         DWORD Right,Bottom;\r
200         if (dwFlags&HORIZONTAL_FLIP) Right = nXDest+GrpFile->wMaxWidth-1-GrpFrame->Left;\r
201         if (dwFlags&VERTICAL_FLIP) Bottom = nYDest+GrpFile->wMaxHeight-1-GrpFrame->Top;\r
202         nXDest += GrpFrame->Left;\r
203         nYDest += GrpFrame->Top;\r
204         WORD *GrpOffsets = ((WORD *)(((char *)GrpFile)+GrpFrame->Offset));\r
205         BYTE *GrpRaw = (BYTE *)GrpOffsets;\r
206         BYTE *RowData;\r
207         WORD x,ofs;\r
208         DWORD y;\r
209         WORD i;\r
210         int j;\r
211         if (nFrame + 1 < GrpFile->nFrames) {\r
212                 for (i = 0; i + 1 < GrpFile->nFrames; i++) {\r
213                         j = GrpFrames[i].Offset - GrpFrame->Offset;\r
214                         if (j > 0 && j < FrameSize)\r
215                                 FrameSize = j;\r
216                 }\r
217         }\r
218         if (FrameSize == 0xFFFFFF) {\r
219                 for (i = 0; i + 1 < GrpFile->nFrames; i++) {\r
220                         j = GrpFrames[i].Offset - GrpFrames[0].Offset;\r
221                         if (j > 0 && j < FrameSize)\r
222                                 FrameSize = j;\r
223                 }\r
224                 if (FrameSize == GrpFrames[0].Width * GrpFrames[0].Height)\r
225                         FrameSize = GrpFrame->Width * GrpFrame->Height;\r
226         }\r
227         if (!(dwFlags&HORIZONTAL_FLIP) && !(dwFlags&VERTICAL_FLIP)) {\r
228                 if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
229                         for (y=0;y<GrpFrame->Height;y++) {\r
230                                 RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
231                                 x=0; ofs=0;\r
232                                 while (x<GrpFrame->Width) {\r
233                                         if (!(RowData[ofs] & 0x80)) {\r
234                                                 if (!(RowData[ofs] & 0x40)) {\r
235                                                         for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
236                                                                 SetPix(hdcDest,nXDest+x,nYDest+y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
237                                                                 x++;\r
238                                                         }\r
239                                                         ofs+=RowData[ofs]+1;\r
240                                                 }\r
241                                                 else {\r
242                                                         for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
243                                                                 SetPix(hdcDest,nXDest+x,nYDest+y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
244                                                                 x++;\r
245                                                         }\r
246                                                         ofs+=2;\r
247                                                 }\r
248                                         }\r
249                                         else {\r
250                                                 x+=RowData[ofs]-128;\r
251                                                 ofs++;\r
252                                         }\r
253                                 }\r
254                         }\r
255                 }\r
256                 else {\r
257                         for (y=0;y<GrpFrame->Height;y++) {\r
258                                 for (x=0;x<GrpFrame->Width;x++) {\r
259                                         SetPix(hdcDest,nXDest+x,nYDest+y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
260                                 }\r
261                         }\r
262                 }\r
263         }\r
264         else if (dwFlags&HORIZONTAL_FLIP && !(dwFlags&VERTICAL_FLIP)) {\r
265                 if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
266                         for (y=0;y<GrpFrame->Height;y++) {\r
267                                 RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
268                                 x=0; ofs=0;\r
269                                 while (x<GrpFrame->Width) {\r
270                                         if (!(RowData[ofs] & 0x80)) {\r
271                                                 if (!(RowData[ofs] & 0x40)) {\r
272                                                         for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
273                                                                 SetPix(hdcDest,Right-x,nYDest+y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
274                                                                 x++;\r
275                                                         }\r
276                                                         ofs+=RowData[ofs]+1;\r
277                                                 }\r
278                                                 else {\r
279                                                         for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
280                                                                 SetPix(hdcDest,Right-x,nYDest+y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
281                                                                 x++;\r
282                                                         }\r
283                                                         ofs+=2;\r
284                                                 }\r
285                                         }\r
286                                         else {\r
287                                                 x+=RowData[ofs]-128;\r
288                                                 ofs++;\r
289                                         }\r
290                                 }\r
291                         }\r
292                 }\r
293                 else {\r
294                         for (y=0;y<GrpFrame->Height;y++) {\r
295                                 for (x=0;x<GrpFrame->Width;x++) {\r
296                                         SetPix(hdcDest,Right-x,nYDest+y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
297                                 }\r
298                         }\r
299                 }\r
300         }\r
301         else if (!(dwFlags&HORIZONTAL_FLIP) && dwFlags&VERTICAL_FLIP) {\r
302                 if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
303                         for (y=0;y<GrpFrame->Height;y++) {\r
304                                 RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
305                                 x=0; ofs=0;\r
306                                 while (x<GrpFrame->Width) {\r
307                                         if (!(RowData[ofs] & 0x80)) {\r
308                                                 if (!(RowData[ofs] & 0x40)) {\r
309                                                         for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
310                                                                 SetPix(hdcDest,nXDest+x,Bottom-y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
311                                                                 x++;\r
312                                                         }\r
313                                                         ofs+=RowData[ofs]+1;\r
314                                                 }\r
315                                                 else {\r
316                                                         for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
317                                                                 SetPix(hdcDest,nXDest+x,Bottom-y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
318                                                                 x++;\r
319                                                         }\r
320                                                         ofs+=2;\r
321                                                 }\r
322                                         }\r
323                                         else {\r
324                                                 x+=RowData[ofs]-128;\r
325                                                 ofs++;\r
326                                         }\r
327                                 }\r
328                         }\r
329                 }\r
330                 else {\r
331                         for (y=0;y<GrpFrame->Height;y++) {\r
332                                 for (x=0;x<GrpFrame->Width;x++) {\r
333                                         SetPix(hdcDest,nXDest+x,Bottom-y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
334                                 }\r
335                         }\r
336                 }\r
337         }\r
338         else {\r
339                 if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
340                         for (y=0;y<GrpFrame->Height;y++) {\r
341                                 RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
342                                 x=0; ofs=0;\r
343                                 while (x<GrpFrame->Width) {\r
344                                         if (!(RowData[ofs] & 0x80)) {\r
345                                                 if (!(RowData[ofs] & 0x40)) {\r
346                                                         for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
347                                                                 SetPix(hdcDest,Right-x,Bottom-y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
348                                                                 x++;\r
349                                                         }\r
350                                                         ofs+=RowData[ofs]+1;\r
351                                                 }\r
352                                                 else {\r
353                                                         for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
354                                                                 SetPix(hdcDest,Right-x,Bottom-y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
355                                                                 x++;\r
356                                                         }\r
357                                                         ofs+=2;\r
358                                                 }\r
359                                         }\r
360                                         else {\r
361                                                 x+=RowData[ofs]-128;\r
362                                                 ofs++;\r
363                                         }\r
364                                 }\r
365                         }\r
366                 }\r
367                 else {\r
368                         for (y=0;y<GrpFrame->Height;y++) {\r
369                                 for (x=0;x<GrpFrame->Width;x++) {\r
370                                         SetPix(hdcDest,Right-x,Bottom-y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
371                                 }\r
372                         }\r
373                 }\r
374         }\r
375         return TRUE;\r
376 }\r
377 \r
378 BOOL GRPAPI WINAPI GetGrpInfo(HANDLE hGrp, GRPHEADER *GrpInfo)\r
379 {\r
380         if (!hGrp || hGrp==INVALID_HANDLE_VALUE || !GrpInfo) return FALSE;\r
381         memcpy(GrpInfo,hGrp,6);\r
382         return TRUE;\r
383 }\r
384 \r
385 void GRPAPI WINAPI SetFunctionGetPixel(GETPIXELPROC lpGetPixelProc)\r
386 {\r
387         if (!lpGetPixelProc)\r
388                 MyGetPixel = GetPixel;\r
389         else\r
390                 MyGetPixel = lpGetPixelProc;\r
391 }\r
392 \r
393 void GRPAPI WINAPI SetFunctionSetPixel(SETPIXELPROC lpSetPixelProc)\r
394 {\r
395         if (!lpSetPixelProc)\r
396                 MySetPixel = (SETPIXELPROC)SetPixelV;\r
397         else\r
398                 MySetPixel = lpSetPixelProc;\r
399 }\r
400 \r
401 void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha)\r
402 {\r
403         if (!(dwFlags&USE_INDEX)) {\r
404                 if (dwFlags&SHADOW_COLOR) {\r
405                         clrColor = (dwFlags >> 8) & 0x00FFFFFF;\r
406                 }\r
407                 else {\r
408                         clrColor = dwPalette[clrColor];\r
409                 }\r
410                 if (dwFlags&ALPHA_BLEND) {\r
411                         DWORD dwColor = MyGetPixel(hDC,X,Y);\r
412 \r
413                         // Old alpha\r
414                         /*((BYTE *)&dwColor)[0]*=1-((float)((BYTE *)&dwAlpha)[0]/256);\r
415                         ((BYTE *)&dwColor)[1]*=1-((float)((BYTE *)&dwAlpha)[1]/256);\r
416                         ((BYTE *)&dwColor)[2]*=1-((float)((BYTE *)&dwAlpha)[2]/256);\r
417                         ((BYTE *)&clrColor)[0]*=(float)((BYTE *)&dwAlpha)[0]/256;\r
418                         ((BYTE *)&clrColor)[1]*=(float)((BYTE *)&dwAlpha)[1]/256;\r
419                         ((BYTE *)&clrColor)[2]*=(float)((BYTE *)&dwAlpha)[2]/256;\r
420                         ((BYTE *)&clrColor)[0]+=((BYTE *)&dwColor)[0];\r
421                         ((BYTE *)&clrColor)[1]+=((BYTE *)&dwColor)[1];\r
422                         ((BYTE *)&clrColor)[2]+=((BYTE *)&dwColor)[2];*/\r
423 \r
424                         /* blendedcolor =\r
425                                  ( ( forecolor * ( 1 - alpha ) ) >> 8 )\r
426                            + ( ( backcolor * ( 256 - alpha ) ) >> 8 ) */\r
427                         ((BYTE *)&clrColor)[0] =\r
428                                 ( ( ((BYTE *)&clrColor)[0] * ( ((BYTE *)&dwAlpha)[0] + 1 ) ) >> 8 )\r
429                                 + ( ( ((BYTE *)&dwColor)[0] * ( 256 - ((BYTE *)&dwAlpha)[0] ) ) >> 8 );\r
430                         ((BYTE *)&clrColor)[1] =\r
431                                 ( ( ((BYTE *)&clrColor)[1] * ( ((BYTE *)&dwAlpha)[1] + 1 ) ) >> 8 )\r
432                                 + ( ( ((BYTE *)&dwColor)[1] * ( 256 - ((BYTE *)&dwAlpha)[1] ) ) >> 8 );\r
433                         ((BYTE *)&clrColor)[2] =\r
434                                 ( ( ((BYTE *)&clrColor)[2] * ( ((BYTE *)&dwAlpha)[2] + 1 ) ) >> 8 )\r
435                                 + ( ( ((BYTE *)&dwColor)[2] * ( 256 - ((BYTE *)&dwAlpha)[2] ) ) >> 8 );\r
436                 }\r
437         }\r
438         MySetPixel(hDC,X,Y,clrColor);\r
439 }\r
440 \r
441 HANDLE GRPAPI WINAPI CreateGrp(signed short *lpImageData, WORD nFrames, WORD wMaxWidth, WORD wMaxHeight, DWORD *nGrpSize)\r
442 {\r
443         GRPHEADER GrpHeader;\r
444         FRAMEHEADER *lpFrameHeaders;\r
445         FRAMEDATA *lpFrameData;\r
446         LPBYTE lpGrpData;\r
447         int i, x, y, x1, x2, y1, y2;\r
448 \r
449         if (!lpImageData || !nGrpSize) return (HANDLE)-1;\r
450 \r
451         GrpHeader.nFrames = nFrames;\r
452         GrpHeader.wMaxWidth = wMaxWidth;\r
453         GrpHeader.wMaxHeight = wMaxHeight;\r
454         lpFrameHeaders = (FRAMEHEADER *)malloc((nFrames + 1) * sizeof(FRAMEHEADER));\r
455         lpFrameData = (FRAMEDATA *)malloc(nFrames * sizeof(FRAMEDATA));\r
456 \r
457         for (i = 0; i <= nFrames; i++) {\r
458                 if (i == 0) {\r
459                         lpFrameHeaders[i].Offset = sizeof(GRPHEADER) + nFrames * sizeof(FRAMEHEADER);\r
460                 }\r
461                 else {\r
462                         y = lpFrameHeaders[i-1].Height;\r
463                         if (y > 0) {\r
464                                 y--;\r
465                                 lpFrameHeaders[i].Offset = lpFrameHeaders[i-1].Offset + lpFrameData[i-1].lpRowOffsets[y] + lpFrameData[i-1].lpRowSizes[y];\r
466                         }\r
467                         else {\r
468                                 lpFrameHeaders[i].Offset = lpFrameHeaders[i-1].Offset;\r
469                         }\r
470                 }\r
471                 if (i == nFrames) continue;\r
472 \r
473                 // Scan frame to find dimensions of used part\r
474                 x1 = y1 = 0x10000;\r
475                 x2 = y2 = -1;\r
476                 for (y = 0; y < wMaxHeight; y++) {\r
477                         for (x = 0; x < wMaxWidth; x++) {\r
478                                 if (lpImageData[i * wMaxWidth * wMaxHeight + y * wMaxWidth + x] >= 0) {\r
479                                         if (x < x1) x1 = x;\r
480                                         if (x > x2) x2 = x;\r
481                                         if (y < y1) y1 = y;\r
482                                         if (y > y2) y2 = y;\r
483                                 }\r
484                         }\r
485                 }\r
486                 lpFrameHeaders[i].Left = x1;\r
487                 lpFrameHeaders[i].Top = y1;\r
488                 lpFrameHeaders[i].Width = x2 - x1 + 1;\r
489                 lpFrameHeaders[i].Height = y2 - y1 + 1;\r
490 \r
491                 EncodeFrameData(lpImageData, i, &GrpHeader, &lpFrameHeaders[i], &lpFrameData[i]);\r
492         }\r
493 \r
494         lpGrpData = (LPBYTE)malloc(lpFrameHeaders[nFrames].Offset);\r
495 \r
496         // Write completed GRP to buffer\r
497         memcpy(lpGrpData, &GrpHeader, sizeof(GRPHEADER));\r
498         memcpy(lpGrpData + sizeof(GRPHEADER), lpFrameHeaders, nFrames * sizeof(FRAMEHEADER));\r
499 \r
500         for (i = 0; i < nFrames; i++) {\r
501                 memcpy(lpGrpData + lpFrameHeaders[i].Offset, lpFrameData[i].lpRowOffsets, lpFrameHeaders[i].Height * sizeof(WORD));\r
502 \r
503                 for (y = 0; y < lpFrameHeaders[i].Height; y++) {\r
504                         memcpy(lpGrpData + lpFrameHeaders[i].Offset + lpFrameData[i].lpRowOffsets[y], lpFrameData[i].lpRowData[y], lpFrameData[i].lpRowSizes[y]);\r
505                         free(lpFrameData[i].lpRowData[y]);\r
506                 }\r
507 \r
508                 free(lpFrameData[i].lpRowOffsets);\r
509                 free(lpFrameData[i].lpRowSizes);\r
510                 free(lpFrameData[i].lpRowData);\r
511         }\r
512 \r
513         *nGrpSize = lpFrameHeaders[nFrames].Offset;\r
514         free(lpFrameHeaders);\r
515         free(lpFrameData);\r
516 \r
517         return (HANDLE)lpGrpData;\r
518 }\r
519 \r
520 void EncodeFrameData(signed short *lpImageData, WORD nFrame, GRPHEADER *lpGrpHeader, FRAMEHEADER *lpFrameHeader, FRAMEDATA *lpFrameData)\r
521 {\r
522         int x, y, i, nBufPos;\r
523         LPBYTE lpRowBuf;\r
524 \r
525         lpFrameData->lpRowOffsets = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));\r
526         lpFrameData->lpRowSizes = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));\r
527         lpFrameData->lpRowData = (LPBYTE *)malloc(lpFrameHeader->Height * sizeof(LPBYTE));\r
528         lpRowBuf = (LPBYTE)malloc(lpFrameHeader->Width * 2);\r
529 \r
530         for (y = 0; y < lpFrameHeader->Height; y++) {\r
531                 i = nFrame * lpGrpHeader->wMaxWidth * lpGrpHeader->wMaxHeight + (lpFrameHeader->Top + y) * lpGrpHeader->wMaxWidth;\r
532                 nBufPos = 0;\r
533                 if (lpFrameHeader->Width > 1) {\r
534                         for (x = lpFrameHeader->Left; x < lpFrameHeader->Left + lpFrameHeader->Width - 1; x++) {\r
535                                 if (lpImageData[i+x] < 0) {\r
536                                         lpRowBuf[nBufPos] = 0x80;\r
537                                         for (; lpImageData[i+x] < 0 && x < lpFrameHeader->Left + lpFrameHeader->Width; x++) {\r
538                                                 lpRowBuf[nBufPos]++;\r
539                                         }\r
540                                         x--;\r
541                                         nBufPos++;\r
542                                 }\r
543                                 else if (lpImageData[i+x] == lpImageData[i+x+1]) {\r
544                                         lpRowBuf[nBufPos] = 0x41;\r
545                                         lpRowBuf[nBufPos+1] = (BYTE)lpImageData[i+x];\r
546                                         for (; lpImageData[i+x] == lpImageData[i+x+1] && x < lpFrameHeader->Left + lpFrameHeader->Width - 1; x++) {\r
547                                                 lpRowBuf[nBufPos]++;\r
548                                         }\r
549                                         nBufPos += 2;\r
550                                 }\r
551                                 else {\r
552                                         lpRowBuf[nBufPos] = 1;\r
553                                         lpRowBuf[nBufPos+1] = (BYTE)lpImageData[i+x];\r
554                                         x++;\r
555                                         for (; lpImageData[i+x] != lpImageData[i+x+1] && x < lpFrameHeader->Left + lpFrameHeader->Width - 1; x++) {\r
556                                                 lpRowBuf[nBufPos]++;\r
557                                                 lpRowBuf[nBufPos+lpRowBuf[nBufPos]] = (BYTE)lpImageData[i+x];\r
558                                         }\r
559                                         x--;\r
560                                         nBufPos += 1 + lpRowBuf[nBufPos];\r
561                                 }\r
562                         }\r
563                 }\r
564                 else if (lpFrameHeader->Width == 1){\r
565                         if (lpImageData[i] < 0) {\r
566                                 lpRowBuf[nBufPos] = 0x81;\r
567                                 nBufPos++;\r
568                         }\r
569                         else {\r
570                                 lpRowBuf[nBufPos] = 1;\r
571                                 lpRowBuf[nBufPos+1] = (BYTE)lpImageData[i+1];\r
572                                 nBufPos += 2;\r
573                         }\r
574                 }\r
575 \r
576                 if (y == 0) {\r
577                         lpFrameData->lpRowOffsets[y] = lpFrameHeader->Height * sizeof(WORD);\r
578                 }\r
579                 else {\r
580                         lpFrameData->lpRowOffsets[y] = lpFrameData->lpRowOffsets[y-1] + lpFrameData->lpRowSizes[y-1];\r
581                 }\r
582 \r
583                 lpFrameData->lpRowSizes[y] = nBufPos;\r
584                 lpFrameData->lpRowData[y] = (LPBYTE)malloc(nBufPos);\r
585                 memcpy(lpFrameData->lpRowData[y], lpRowBuf, nBufPos);\r
586         }\r
587 \r
588         free(lpRowBuf);\r
589 }\r