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