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