]> icculus.org git repositories - btb/d2x.git/blob - main/mveplay.c
movie improvements
[btb/d2x.git] / main / mveplay.c
1 #ifdef HAVE_CONFIG_H
2 #include <conf.h>
3 #endif
4
5 #include <string.h>
6 #include <errno.h>
7 #include <time.h>
8 #include <sys/time.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <SDL/SDL.h>
14 #include <SDL/SDL_thread.h>
15
16 #include "error.h"
17 #include "u_mem.h"
18 #include "mvelib.h"
19 #include "mve_audio.h"
20 #include "gr.h"
21 #include "palette.h"
22
23 #ifndef MIN
24 #define MIN(a,b) ((a)<(b)?(a):(b))
25 #endif
26
27 static int g_spdFactorNum=0;
28 static int g_spdFactorDenom=10;
29
30 void initializeMovie(MVESTREAM *mve, grs_bitmap *mve_bitmap);
31 void shutdownMovie(MVESTREAM *mve);
32
33 static short get_short(unsigned char *data)
34 {
35     short value;
36     value = data[0] | (data[1] << 8);
37     return value;
38 }
39
40 static int get_int(unsigned char *data)
41 {
42     int value;
43     value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
44     return value;
45 }
46
47 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
48 {
49     fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
50     return 1;
51 }
52
53 /*************************
54  * general handlers
55  *************************/
56 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
57 {
58         return 0;
59 }
60
61 /*************************
62  * timer handlers
63  *************************/
64
65 /*
66  * timer variables
67  */
68 static int micro_frame_delay=0;
69
70 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
71 {
72     long long temp;
73     micro_frame_delay = get_int(data) * (int)get_short(data+4);
74     if (g_spdFactorNum != 0)
75     {
76         temp = micro_frame_delay;
77         temp *= g_spdFactorNum;
78         temp /= g_spdFactorDenom;
79         micro_frame_delay = (int)temp;
80     }
81
82     return 1;
83 }
84
85
86 /*************************
87  * audio handlers
88  *************************/
89 static void mve_audio_callback(void *userdata, Uint8 *stream, int len);
90 static short *mve_audio_buffers[64];
91 static int    mve_audio_buflens[64];
92 static int    mve_audio_curbuf_curpos=0;
93 static int mve_audio_bufhead=0;
94 static int mve_audio_buftail=0;
95 static int mve_audio_playing=0;
96 static int mve_audio_canplay=0;
97 static int mve_audio_compressed=0;
98 static SDL_AudioSpec *mve_audio_spec=NULL;
99 static SDL_mutex *mve_audio_mutex = NULL;
100
101 static void mve_audio_callback(void *userdata, Uint8 *stream, int len)
102 {
103     int total=0;
104     int length;
105     if (mve_audio_bufhead == mve_audio_buftail)
106         return /* 0 */;
107
108 fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
109
110     SDL_mutexP(mve_audio_mutex);
111
112     while (mve_audio_bufhead != mve_audio_buftail                                       /* while we have more buffers  */
113             &&  len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos))   /* and while we need more data */
114     {
115         length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
116         __builtin_memcpy(stream,                                                        /* cur output position */
117                 mve_audio_buffers[mve_audio_bufhead]+mve_audio_curbuf_curpos,           /* cur input position  */
118                 length);                                                                /* cur input length    */
119
120         total += length;
121         stream += length;                                                               /* advance output */
122         len -= length;                                                                  /* decrement avail ospace */
123         d_free(mve_audio_buffers[mve_audio_bufhead]);                                   /* free the buffer */
124         mve_audio_buffers[mve_audio_bufhead]=NULL;                                      /* free the buffer */
125         mve_audio_buflens[mve_audio_bufhead]=0;                                         /* free the buffer */
126
127         if (++mve_audio_bufhead == 64)                                                  /* next buffer */
128             mve_audio_bufhead = 0;
129         mve_audio_curbuf_curpos = 0;
130     }
131
132 fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
133 /*    return total; */
134
135     if (len != 0                                                                        /* ospace remaining  */
136             &&  mve_audio_bufhead != mve_audio_buftail)                                 /* buffers remaining */
137     {
138         __builtin_memcpy(stream,                                                        /* dest */
139                 mve_audio_buffers[mve_audio_bufhead] + mve_audio_curbuf_curpos,         /* src */
140                 len);                                                                   /* length */
141
142         mve_audio_curbuf_curpos += len;                                                 /* advance input */
143         stream += len;                                                                  /* advance output (unnecessary) */
144         len -= len;                                                                     /* advance output (unnecessary) */
145
146         if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead])            /* if this ends the current chunk */
147         {
148             d_free(mve_audio_buffers[mve_audio_bufhead]);                               /* free buffer */
149             mve_audio_buffers[mve_audio_bufhead]=NULL;
150             mve_audio_buflens[mve_audio_bufhead]=0;
151
152             if (++mve_audio_bufhead == 64)                                              /* next buffer */
153                 mve_audio_bufhead = 0;
154             mve_audio_curbuf_curpos = 0;
155         }
156     }
157
158 fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
159     SDL_mutexV(mve_audio_mutex);
160 }
161
162 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
163 {
164     int flags;
165     int sample_rate;
166     int desired_buffer;
167
168 fprintf(stderr, "creating audio buffers\n");
169
170     mve_audio_mutex = SDL_CreateMutex();
171
172     flags = get_short(data + 2);
173     sample_rate = get_short(data + 4);
174     desired_buffer = get_int(data + 6);
175
176 fprintf(stderr, "stereo=%d 16bit=%d compressed=%d sample_rate=%d desired_buffer=%d\n",
177         flags & 1, (flags >> 1) & 1, (flags >> 2) & 1, sample_rate, desired_buffer);
178
179     mve_audio_compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED;
180     mve_audio_spec = (SDL_AudioSpec *)d_malloc(sizeof(SDL_AudioSpec));
181     mve_audio_spec->freq = sample_rate;
182 #ifdef WORDS_BIGENDIAN
183     mve_audio_spec->format = (flags & MVE_AUDIO_FLAGS_16BIT)?AUDIO_S16MSB:AUDIO_U8;
184 #else
185     mve_audio_spec->format = (flags & MVE_AUDIO_FLAGS_16BIT)?AUDIO_S16LSB:AUDIO_U8;
186 #endif
187     mve_audio_spec->channels = (flags & MVE_AUDIO_FLAGS_STEREO)?2:1;
188     mve_audio_spec->samples = 32768;
189     mve_audio_spec->callback = mve_audio_callback;
190     mve_audio_spec->userdata = NULL;
191     if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
192     {
193 fprintf(stderr, "   success\n");
194         mve_audio_canplay = 1;
195     }
196     else
197     {
198 fprintf(stderr, "   failure : %s\n", SDL_GetError());
199         mve_audio_canplay = 0;
200     }
201
202     memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
203     memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
204
205     return 1;
206 }
207
208 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
209 {
210     if (mve_audio_canplay  &&  !mve_audio_playing  &&  mve_audio_bufhead != mve_audio_buftail)
211     {
212         SDL_PauseAudio(0);
213         mve_audio_playing = 1;
214     }
215
216     return 1;
217 }
218
219 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
220 {
221     static const int selected_chan=1;
222     int chan;
223     int nsamp;
224     if (mve_audio_canplay)
225     {
226         if (mve_audio_playing)
227             SDL_LockAudio();
228
229         chan = get_short(data + 2);
230         nsamp = get_short(data + 4);
231         if (chan & selected_chan)
232         {
233             SDL_mutexP(mve_audio_mutex);
234             mve_audio_buflens[mve_audio_buftail] = nsamp;
235             mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp+4);
236             if (major == 8)
237                 if (mve_audio_compressed)
238                     mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
239                 else
240                     memcpy(mve_audio_buffers[mve_audio_buftail], data + 6, nsamp);
241             else
242                 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
243
244             if (++mve_audio_buftail == 64)
245                 mve_audio_buftail = 0;
246
247             if (mve_audio_buftail == mve_audio_bufhead)
248                 fprintf(stderr, "d'oh!  buffer ring overrun (%d)\n", mve_audio_bufhead);
249             SDL_mutexV(mve_audio_mutex);
250         }
251
252         if (mve_audio_playing)
253             SDL_UnlockAudio();
254     }
255
256     return 1;
257 }
258
259 /*************************
260  * video handlers
261  *************************/
262 static grs_bitmap *g_screen;
263 static int g_screenWidth, g_screenHeight;
264 static int g_width, g_height;
265 static unsigned char g_palette[768];
266 static unsigned char *g_vBackBuf1, *g_vBackBuf2;
267 static unsigned char *g_pCurMap=NULL;
268 static int g_nMapLength=0;
269
270 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
271 {
272     short w, h;
273     w = get_short(data);
274     h = get_short(data+2);
275     g_width = w << 3;
276     g_height = h << 3;
277     printf("mve width, height: %d, %d\n", g_width, g_height);
278     Assert((g_width == g_screen->bm_w) && (g_height == g_screen->bm_h));
279     g_vBackBuf1 = d_malloc(g_width * g_height);
280     g_vBackBuf2 = d_malloc(g_width * g_height);
281     memset(g_vBackBuf1, 0, g_width * g_height);
282     memset(g_vBackBuf2, 0, g_width * g_height);
283     return 1;
284 }
285
286 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
287 {
288     gr_palette_load(g_palette);
289
290     memcpy(g_screen->bm_data, g_vBackBuf1, g_width * g_height);
291
292     return 1;
293 }
294
295 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
296 {
297     short width, height;
298     width = get_short(data);
299     height = get_short(data+2);
300     g_screenWidth = width;
301     g_screenHeight = height;
302     memset(g_palette, 0, 768);
303     return 1;
304 }
305
306 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
307 {
308     short start, count;
309     start = get_short(data);
310     count = get_short(data+2);
311     memcpy(g_palette + 3*start, data+4, 3*count);
312     return 1;
313 }
314
315 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
316 {
317     g_pCurMap = data;
318     g_nMapLength = len;
319     return 1;
320 }
321
322 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
323
324 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
325 {
326     short nFrameHot, nFrameCold;
327     short nXoffset, nYoffset;
328     short nXsize, nYsize;
329     short nFlags;
330     unsigned char *temp;
331
332     nFrameHot  = get_short(data);
333     nFrameCold = get_short(data+2);
334     nXoffset   = get_short(data+4);
335     nYoffset   = get_short(data+6);
336     nXsize     = get_short(data+8);
337     nYsize     = get_short(data+10);
338     nFlags     = get_short(data+12);
339
340     if (nFlags & 1)
341     {
342         temp = g_vBackBuf1;
343         g_vBackBuf1 = g_vBackBuf2;
344         g_vBackBuf2 = temp;
345     }
346
347     /* convert the frame */
348     decodeFrame(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
349
350     return 1;
351 }
352
353 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
354 {
355     g_pCurMap=NULL;
356     return 1;
357 }
358
359 void initializeMovie(MVESTREAM *mve, grs_bitmap *mve_bitmap)
360 {
361     g_screen = mve_bitmap;
362
363     mve_set_handler(mve, 0x00, end_movie_handler);
364     mve_set_handler(mve, 0x01, end_chunk_handler);
365     mve_set_handler(mve, 0x02, create_timer_handler);
366     mve_set_handler(mve, 0x03, create_audiobuf_handler);
367     mve_set_handler(mve, 0x04, play_audio_handler);
368     mve_set_handler(mve, 0x05, create_videobuf_handler);
369     mve_set_handler(mve, 0x06, default_seg_handler);
370     mve_set_handler(mve, 0x07, display_video_handler);
371     mve_set_handler(mve, 0x08, audio_data_handler);
372     mve_set_handler(mve, 0x09, audio_data_handler);
373     mve_set_handler(mve, 0x0a, init_video_handler);
374     mve_set_handler(mve, 0x0b, default_seg_handler);
375     mve_set_handler(mve, 0x0c, video_palette_handler);
376     mve_set_handler(mve, 0x0d, default_seg_handler);
377     mve_set_handler(mve, 0x0e, default_seg_handler);
378     mve_set_handler(mve, 0x0f, video_codemap_handler);
379     mve_set_handler(mve, 0x10, default_seg_handler);
380     mve_set_handler(mve, 0x11, video_data_handler);
381     mve_set_handler(mve, 0x12, default_seg_handler);
382     //mve_set_handler(mve, 0x13, default_seg_handler);
383     mve_set_handler(mve, 0x14, default_seg_handler);
384     //mve_set_handler(mve, 0x15, default_seg_handler);
385 }
386
387 void shutdownMovie(MVESTREAM *mve)
388 {
389     int i;
390
391     SDL_CloseAudio();
392     for (i = 0; i < 64; i++)
393         if (mve_audio_buffers[i] != NULL) {
394             d_free(mve_audio_buffers[i]);
395             mve_audio_buffers[i] = NULL;
396         }
397
398     d_free(mve_audio_spec);
399     d_free(g_vBackBuf1);
400     d_free(g_vBackBuf2);
401 }
402
403 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
404
405 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
406 {
407     int i, j;
408     int xb, yb;
409
410     xb = g_width >> 3;
411     yb = g_height >> 3;
412     for (j=0; j<yb; j++)
413     {
414         for (i=0; i<xb/2; i++)
415         {
416             dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
417             if (pFrame < g_vBackBuf1)
418                 fprintf(stderr, "danger!  pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
419             else if (pFrame >= g_vBackBuf1 + g_width*g_height)
420                 fprintf(stderr, "danger!  pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
421             dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
422             if (pFrame < g_vBackBuf1)
423                 fprintf(stderr, "danger!  pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
424             else if (pFrame >= g_vBackBuf1 + g_width*g_height)
425                 fprintf(stderr, "danger!  pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
426
427             ++pMap;
428             --mapRemain;
429         }
430
431         pFrame += 7*g_width;
432     }
433 }
434
435 static void relClose(int i, int *x, int *y)
436 {
437     int ma, mi;
438
439     ma = i >> 4;
440     mi = i & 0xf;
441
442     *x = mi - 8;
443     *y = ma - 8;
444 }
445
446 static void relFar(int i, int sign, int *x, int *y)
447 {
448     if (i < 56)
449     {
450         *x = sign * (8 + (i % 7));
451         *y = sign *      (i / 7);
452     }
453     else
454     {
455         *x = sign * (-14 + (i - 56) % 29);
456         *y = sign *   (8 + (i - 56) / 29);
457     }
458 }
459
460 static void copyFrame(unsigned char *pDest, unsigned char *pSrc)
461 {
462     int i;
463
464     for (i=0; i<8; i++)
465     {
466         memcpy(pDest, pSrc, 8);
467         pDest += g_width;
468         pSrc += g_width;
469     }
470 }
471
472 static void patternRow4Pixels(unsigned char *pFrame,
473                               unsigned char pat0, unsigned char pat1,
474                               unsigned char *p)
475 {
476     unsigned short mask=0x0003;
477     unsigned short shift=0;
478     unsigned short pattern = (pat1 << 8) | pat0;
479
480     while (mask != 0)
481     {
482         *pFrame++ = p[(mask & pattern) >> shift];
483         mask <<= 2;
484         shift += 2;
485     }
486 }
487
488 static void patternRow4Pixels2(unsigned char *pFrame,
489                                unsigned char pat0,
490                                unsigned char *p)
491 {
492     unsigned char mask=0x03;
493     unsigned char shift=0;
494     unsigned char pel;
495     int skip=1;
496
497     while (mask != 0)
498     {
499         pel = p[(mask & pat0) >> shift];
500         pFrame[0] = pel;
501         pFrame[2] = pel;
502         pFrame[g_width + 0] = pel;
503         pFrame[g_width + 2] = pel;
504         pFrame += skip;
505         skip = 4 - skip;
506         mask <<= 2;
507         shift += 2;
508     }
509 }
510
511 static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p)
512 {
513     unsigned char mask=0x03;
514     unsigned char shift=0;
515     unsigned char pel;
516
517     while (mask != 0)
518     {
519         pel = p[(mask & pat) >> shift];
520         pFrame[0] = pel;
521         pFrame[1] = pel;
522         pFrame += 2;
523         mask <<= 2;
524         shift += 2;
525     }
526 }
527
528 static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p)
529 {
530     unsigned long mask = 0x00000003UL;
531     int shift=0;
532     int i;
533     unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
534
535     for (i=0; i<16; i++)
536     {
537         pFrame[i&3] = p[(pat & mask) >> shift];
538
539         if ((i&3) == 3)
540             pFrame += g_width;
541
542         mask <<= 2;
543         shift += 2;
544     }
545 }
546
547
548 static void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p)
549 {
550     unsigned char mask=0x01;
551
552     while (mask != 0)
553     {
554         *pFrame++ = p[(mask & pat) ? 1 : 0];
555         mask <<= 1;
556     }
557 }
558
559 static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p)
560 {
561     unsigned char pel;
562     unsigned char mask=0x1;
563     int skip=1;
564
565     while (mask != 0x10)
566     {
567         pel = p[(mask & pat) ? 1 : 0];
568         pFrame[0] = pel;
569         pFrame[2] = pel;
570         pFrame[g_width + 0] = pel;
571         pFrame[g_width + 2] = pel;
572         pFrame += skip;
573         skip = 4 - skip;
574         mask <<= 1;
575     }
576 }
577
578 static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p)
579 {
580     unsigned short mask = 0x0001;
581     int i;
582     unsigned short pat = (pat1 << 8) | pat0;
583
584     for (i=0; i<16; i++)
585     {
586         pFrame[i&3] = p[(pat & mask) ? 1 : 0];
587
588         if ((i&3) == 3)
589             pFrame += g_width;
590
591         mask <<= 1;
592     }
593 }
594
595 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
596 {
597     unsigned char p[4];
598     unsigned char pat[16];
599     int i, j, k;
600     int x, y;
601
602     switch(codeType)
603     {
604         case 0x0:
605                   copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
606         case 0x1:
607                   *pFrame += 8;
608                   break;
609
610         case 0x2:
611                   relFar(*(*pData)++, 1, &x, &y);
612                   copyFrame(*pFrame, *pFrame + x + y*g_width);
613                   *pFrame += 8;
614                   --*pDataRemain;
615                   break;
616
617         case 0x3:
618                   relFar(*(*pData)++, -1, &x, &y);
619                   copyFrame(*pFrame, *pFrame + x + y*g_width);
620                   *pFrame += 8;
621                   --*pDataRemain;
622                   break;
623
624         case 0x4:
625                   relClose(*(*pData)++, &x, &y);
626                   copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
627                   *pFrame += 8;
628                   --*pDataRemain;
629                   break;
630
631         case 0x5:
632                   x = (char)*(*pData)++;
633                   y = (char)*(*pData)++;
634                   copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
635                   *pFrame += 8;
636                   *pDataRemain -= 2;
637                   break;
638
639         case 0x6:
640                   for (i=0; i<2; i++)
641                   {
642                       *pFrame += 16;
643                       if (++*curXb == (g_width >> 3))
644                       {
645                           *pFrame += 7*g_width;
646                           *curXb = 0;
647                           if (++*curYb == (g_height >> 3))
648                               return;
649                       }
650                   }
651                   break;
652
653         case 0x7:
654                   p[0] = *(*pData)++;
655                   p[1] = *(*pData)++;
656                   if (p[0] <= p[1])
657                   {
658                       for (i=0; i<8; i++)
659                       {
660                           patternRow2Pixels(*pFrame, *(*pData)++, p);
661                           *pFrame += g_width;
662                       }
663                   }
664                   else
665                   {
666                       for (i=0; i<2; i++)
667                       {
668                           patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
669                           *pFrame += 2*g_width;
670                           patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
671                           *pFrame += 2*g_width;
672                       }
673                   }
674                   *pFrame -= (8*g_width - 8);
675                   break;
676
677         case 0x8:
678                   if ( (*pData)[0] <= (*pData)[1])
679                   {
680                       for (i=0; i<4; i++)
681                       {
682                           p[0] = *(*pData)++;
683                           p[1] = *(*pData)++;
684                           pat[0] = *(*pData)++;
685                           pat[1] = *(*pData)++;
686                           patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
687
688                           if (i & 1)
689                               *pFrame -= (4*g_width - 4);
690                           else
691                               *pFrame += 4*g_width;
692                       }
693                   }
694                   else if ( (*pData)[6] <= (*pData)[7])
695                   {
696                       for (i=0; i<4; i++)
697                       {
698                           if ((i & 1) == 0)
699                           {
700                               p[0] = *(*pData)++;
701                               p[1] = *(*pData)++;
702                           }
703                           pat[0] = *(*pData)++;
704                           pat[1] = *(*pData)++;
705                           patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
706
707                           if (i & 1)
708                               *pFrame -= (4*g_width - 4);
709                           else
710                               *pFrame += 4*g_width;
711                       }
712                   }
713                   else
714                   {
715                       for (i=0; i<8; i++)
716                       {
717                           if ((i & 3) == 0)
718                           {
719                               p[0] = *(*pData)++;
720                               p[1] = *(*pData)++;
721                           }
722                           patternRow2Pixels(*pFrame, *(*pData)++, p);
723                           *pFrame += g_width;
724                       }
725                       *pFrame -= (8*g_width - 8);
726                   }
727                   break;
728
729         case 0x9:
730                   if ( (*pData)[0] <= (*pData)[1])
731                   {
732                       if ( (*pData)[2] <= (*pData)[3])
733                       {
734                           p[0] = *(*pData)++;
735                           p[1] = *(*pData)++;
736                           p[2] = *(*pData)++;
737                           p[3] = *(*pData)++;
738
739                           for (i=0; i<8; i++)
740                           {
741                               pat[0] = *(*pData)++;
742                               pat[1] = *(*pData)++;
743                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
744                               *pFrame += g_width;
745                           }
746
747                           *pFrame -= (8*g_width - 8);
748                       }
749                       else
750                       {
751                           p[0] = *(*pData)++;
752                           p[1] = *(*pData)++;
753                           p[2] = *(*pData)++;
754                           p[3] = *(*pData)++;
755
756                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
757                           *pFrame += 2*g_width;
758                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
759                           *pFrame += 2*g_width;
760                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
761                           *pFrame += 2*g_width;
762                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
763                           *pFrame -= (6*g_width - 8);
764                       }
765                   }
766                   else
767                   {
768                       if ( (*pData)[2] <= (*pData)[3])
769                       {
770                           p[0] = *(*pData)++;
771                           p[1] = *(*pData)++;
772                           p[2] = *(*pData)++;
773                           p[3] = *(*pData)++;
774
775                           for (i=0; i<8; i++)
776                           {
777                               pat[0] = *(*pData)++;
778                               patternRow4Pixels2x1(*pFrame, pat[0], p);
779                               *pFrame += g_width;
780                           }
781
782                           *pFrame -= (8*g_width - 8);
783                       }
784                       else
785                       {
786                           p[0] = *(*pData)++;
787                           p[1] = *(*pData)++;
788                           p[2] = *(*pData)++;
789                           p[3] = *(*pData)++;
790
791                           for (i=0; i<4; i++)
792                           {
793                               pat[0] = *(*pData)++;
794                               pat[1] = *(*pData)++;
795                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
796                               *pFrame += g_width;
797                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
798                               *pFrame += g_width;
799                           }
800
801                           *pFrame -= (8*g_width - 8);
802                       }
803                   }
804                   break;
805
806         case 0xa:
807                   if ( (*pData)[0] <= (*pData)[1])
808                   {
809                       for (i=0; i<4; i++)
810                       {
811                           p[0] = *(*pData)++;
812                           p[1] = *(*pData)++;
813                           p[2] = *(*pData)++;
814                           p[3] = *(*pData)++;
815                           pat[0] = *(*pData)++;
816                           pat[1] = *(*pData)++;
817                           pat[2] = *(*pData)++;
818                           pat[3] = *(*pData)++;
819
820                           patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
821
822                           if (i & 1)
823                               *pFrame -= (4*g_width - 4);
824                           else
825                               *pFrame += 4*g_width;
826                       }
827                   }
828                   else
829                   {
830                       if ( (*pData)[12] <= (*pData)[13])
831                       {
832                           for (i=0; i<4; i++)
833                           {
834                               if ((i&1) == 0)
835                               {
836                                   p[0] = *(*pData)++;
837                                   p[1] = *(*pData)++;
838                                   p[2] = *(*pData)++;
839                                   p[3] = *(*pData)++;
840                               }
841
842                               pat[0] = *(*pData)++;
843                               pat[1] = *(*pData)++;
844                               pat[2] = *(*pData)++;
845                               pat[3] = *(*pData)++;
846
847                               patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
848
849                               if (i & 1)
850                                   *pFrame -= (4*g_width - 4);
851                               else
852                                   *pFrame += 4*g_width;
853                           }
854                       }
855                       else
856                       {
857                           for (i=0; i<8; i++)
858                           {
859                               if ((i&3) == 0)
860                               {
861                                   p[0] = *(*pData)++;
862                                   p[1] = *(*pData)++;
863                                   p[2] = *(*pData)++;
864                                   p[3] = *(*pData)++;
865                               }
866
867                               pat[0] = *(*pData)++;
868                               pat[1] = *(*pData)++;
869                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
870                               *pFrame += g_width;
871                           }
872
873                           *pFrame -= (8*g_width - 8);
874                       }
875                   }
876                   break;
877
878         case 0xb:
879                   for (i=0; i<8; i++)
880                   {
881                       memcpy(*pFrame, *pData, 8);
882                       *pFrame += g_width;
883                       *pData += 8;
884                       *pDataRemain -= 8;
885                   }
886                   *pFrame -= (8*g_width - 8);
887                   break;
888
889         case 0xc:
890                   for (i=0; i<4; i++)
891                   {
892                       for (j=0; j<2; j++)
893                       {
894                           for (k=0; k<4; k++)
895                           {
896                               (*pFrame)[j+2*k] = (*pData)[k];
897                               (*pFrame)[g_width+j+2*k] = (*pData)[k];
898                           }
899                           *pFrame += g_width;
900                       }
901                       *pData += 4;
902                       *pDataRemain -= 4;
903                   }
904                   *pFrame -= (8*g_width - 8);
905                   break;
906
907         case 0xd:
908                   for (i=0; i<2; i++)
909                   {
910                       for (j=0; j<4; j++)
911                       {
912                           for (k=0; k<4; k++)
913                           {
914                               (*pFrame)[k*g_width+j] = (*pData)[0];
915                               (*pFrame)[k*g_width+j+4] = (*pData)[1];
916                           }
917                       }
918                       *pFrame += 4*g_width;
919                       *pData += 2;
920                       *pDataRemain -= 2;
921                   }
922                   *pFrame -= (8*g_width - 8);
923                   break;
924
925         case 0xe:
926                   for (i=0; i<8; i++)
927                   {
928                       memset(*pFrame, **pData, 8);
929                       *pFrame += g_width;
930                   }
931                   ++*pData;
932                   --*pDataRemain;
933                   *pFrame -= (8*g_width - 8);
934                   break;
935
936         case 0xf:
937                   for (i=0; i<8; i++)
938                   {
939                       for (j=0; j<8; j++)
940                       {
941                           (*pFrame)[j] = (*pData)[(i+j)&1];
942                       }
943                       *pFrame += g_width;
944                   }
945                   *pData += 2;
946                   *pDataRemain -= 2;
947                   *pFrame -= (8*g_width - 8);
948                   break;
949
950         default:
951             break;
952     }
953 }