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