]> icculus.org git repositories - btb/d2x.git/blob - main/mveplay.c
foo
[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         if (!mve_audio_spec)
231                 mve_audio_spec = (SDL_AudioSpec *)d_malloc(sizeof(SDL_AudioSpec));
232     mve_audio_spec->freq = sample_rate;
233 #ifdef WORDS_BIGENDIAN
234     mve_audio_spec->format = (flags & MVE_AUDIO_FLAGS_16BIT)?AUDIO_S16MSB:AUDIO_U8;
235 #else
236     mve_audio_spec->format = (flags & MVE_AUDIO_FLAGS_16BIT)?AUDIO_S16LSB:AUDIO_U8;
237 #endif
238     mve_audio_spec->channels = (flags & MVE_AUDIO_FLAGS_STEREO)?2:1;
239     mve_audio_spec->samples = 32768;
240     mve_audio_spec->callback = mve_audio_callback;
241     mve_audio_spec->userdata = NULL;
242     if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
243     {
244 #ifdef DEBUG
245                 fprintf(stderr, "   success\n");
246 #endif
247         mve_audio_canplay = 1;
248     }
249     else
250     {
251 #ifdef DEBUG
252                 fprintf(stderr, "   failure : %s\n", SDL_GetError());
253 #endif
254                 Warning("mveplay: failed to create audio buffers\n");
255         mve_audio_canplay = 0;
256     }
257
258     memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
259     memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
260
261     return 1;
262 }
263
264 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
265 {
266     if (mve_audio_canplay  &&  !mve_audio_playing  &&  mve_audio_bufhead != mve_audio_buftail)
267     {
268         SDL_PauseAudio(0);
269         mve_audio_playing = 1;
270     }
271
272     return 1;
273 }
274
275 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
276 {
277     static const int selected_chan=1;
278     int chan;
279     int nsamp;
280     if (mve_audio_canplay)
281     {
282         if (mve_audio_playing)
283             SDL_LockAudio();
284
285         chan = get_short(data + 2);
286         nsamp = get_short(data + 4);
287         if (chan & selected_chan)
288         {
289             SDL_mutexP(mve_audio_mutex);
290             mve_audio_buflens[mve_audio_buftail] = nsamp;
291                         if (mve_audio_buffers[mve_audio_buftail])
292                                 d_free(mve_audio_buffers[mve_audio_buftail]);
293             mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp+4);
294             if (major == 8)
295                 if (mve_audio_compressed)
296                     mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
297                 else
298                     memcpy(mve_audio_buffers[mve_audio_buftail], data + 6, nsamp);
299             else
300                 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
301
302             if (++mve_audio_buftail == 64)
303                 mve_audio_buftail = 0;
304
305             if (mve_audio_buftail == mve_audio_bufhead)
306                 Warning("mveplay: d'oh!  buffer ring overrun (%d)\n", mve_audio_bufhead);
307             SDL_mutexV(mve_audio_mutex);
308         }
309
310         if (mve_audio_playing)
311             SDL_UnlockAudio();
312     }
313
314     return 1;
315 }
316
317 /*************************
318  * video handlers
319  *************************/
320 static grs_bitmap *g_screen;
321 static int g_screenWidth, g_screenHeight;
322 static int g_width, g_height;
323 static unsigned char g_palette[768];
324 static unsigned char *g_vBackBuf1, *g_vBackBuf2 = NULL;
325 static unsigned char *g_pCurMap=NULL;
326 static int g_nMapLength=0;
327
328 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
329 {
330     short w, h;
331     w = get_short(data);
332     h = get_short(data+2);
333     g_width = w << 3;
334     g_height = h << 3;
335 #ifdef DEBUG
336         fprintf(stderr, "g_width, g_height: %d, %d\n", g_width, g_height);
337 #endif
338     Assert((g_width == g_screen->bm_w) && (g_height == g_screen->bm_h));
339         if (!g_vBackBuf1)
340                 g_vBackBuf1 = d_malloc(g_width * g_height);
341         if (!g_vBackBuf2)
342                 g_vBackBuf2 = d_malloc(g_width * g_height);
343     memset(g_vBackBuf1, 0, g_width * g_height);
344     memset(g_vBackBuf2, 0, g_width * g_height);
345     return 1;
346 }
347
348 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
349 {
350     memcpy(g_screen->bm_data, g_vBackBuf1, g_width * g_height);
351
352     return 1;
353 }
354
355 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
356 {
357     short width, height;
358     width = get_short(data);
359     height = get_short(data+2);
360     g_screenWidth = width;
361     g_screenHeight = height;
362     memset(g_palette, 0, 765);
363         // 255 needs to default to white, for subtitles, etc
364         memset(g_palette + 765, 63, 3);
365     return 1;
366 }
367
368 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
369 {
370     short start, count;
371     start = get_short(data);
372     count = get_short(data+2);
373     memcpy(g_palette + 3*start, data+4, 3*count);
374     gr_palette_load(g_palette);
375
376     return 1;
377 }
378
379 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
380 {
381     g_pCurMap = data;
382     g_nMapLength = len;
383     return 1;
384 }
385
386 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
387
388 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
389 {
390     short nFrameHot, nFrameCold;
391     short nXoffset, nYoffset;
392     short nXsize, nYsize;
393     short nFlags;
394     unsigned char *temp;
395
396     nFrameHot  = get_short(data);
397     nFrameCold = get_short(data+2);
398     nXoffset   = get_short(data+4);
399     nYoffset   = get_short(data+6);
400     nXsize     = get_short(data+8);
401     nYsize     = get_short(data+10);
402     nFlags     = get_short(data+12);
403
404     if (nFlags & 1)
405     {
406         temp = g_vBackBuf1;
407         g_vBackBuf1 = g_vBackBuf2;
408         g_vBackBuf2 = temp;
409     }
410
411     /* convert the frame */
412     decodeFrame(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
413
414     return 1;
415 }
416
417 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
418 {
419     g_pCurMap=NULL;
420     return 1;
421 }
422
423 /************************************************************
424  * public mveplay functions
425  ************************************************************/
426
427 void mveplay_initializeMovie(MVESTREAM *mve, grs_bitmap *mve_bitmap)
428 {
429     g_screen = mve_bitmap;
430
431     mve_set_handler(mve, 0x00, end_movie_handler);
432     mve_set_handler(mve, 0x01, end_chunk_handler);
433     mve_set_handler(mve, 0x02, create_timer_handler);
434     mve_set_handler(mve, 0x03, create_audiobuf_handler);
435     mve_set_handler(mve, 0x04, play_audio_handler);
436     mve_set_handler(mve, 0x05, create_videobuf_handler);
437     mve_set_handler(mve, 0x06, default_seg_handler);
438     mve_set_handler(mve, 0x07, display_video_handler);
439     mve_set_handler(mve, 0x08, audio_data_handler);
440     mve_set_handler(mve, 0x09, audio_data_handler);
441     mve_set_handler(mve, 0x0a, init_video_handler);
442     mve_set_handler(mve, 0x0b, default_seg_handler);
443     mve_set_handler(mve, 0x0c, video_palette_handler);
444     mve_set_handler(mve, 0x0d, default_seg_handler);
445     mve_set_handler(mve, 0x0e, default_seg_handler);
446     mve_set_handler(mve, 0x0f, video_codemap_handler);
447     mve_set_handler(mve, 0x10, default_seg_handler);
448     mve_set_handler(mve, 0x11, video_data_handler);
449     mve_set_handler(mve, 0x12, default_seg_handler);
450     //mve_set_handler(mve, 0x13, default_seg_handler);
451     mve_set_handler(mve, 0x14, default_seg_handler);
452     //mve_set_handler(mve, 0x15, default_seg_handler);
453 }
454
455 int mveplay_stepMovie(MVESTREAM *mve)
456 {
457     static int init_timer=0;
458     int cont=1;
459
460         if (!timer_started)
461                 timer_start();
462
463         cont = mve_play_next_chunk(mve);
464         if (fix_frame_delay  && !init_timer) {
465                 timer_start();
466                 init_timer = 1;
467         }
468
469         do_timer_wait();
470
471         return cont;
472 }
473
474 void mveplay_restartTimer(MVESTREAM *mve)
475 {
476         timer_start();
477 }
478
479 void mveplay_shutdownMovie(MVESTREAM *mve)
480 {
481     int i;
482
483         timer_stop();
484     SDL_CloseAudio();
485     for (i = 0; i < 64; i++)
486         if (mve_audio_buffers[i] != NULL)
487             d_free(mve_audio_buffers[i]);
488     memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
489     memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
490         mve_audio_curbuf_curpos=0;
491         mve_audio_bufhead=0;
492         mve_audio_buftail=0;
493         mve_audio_playing=0;
494         mve_audio_canplay=0;
495         mve_audio_compressed=0;
496         mve_audio_mutex = NULL;
497         if (mve_audio_spec)
498                 d_free(mve_audio_spec);
499         mve_audio_spec=NULL;
500
501     d_free(g_vBackBuf1);
502         g_vBackBuf1 = NULL;
503     d_free(g_vBackBuf2);
504         g_vBackBuf2 = NULL;
505         g_pCurMap=NULL;
506         g_nMapLength=0;
507 }
508
509
510 /************************************************************
511  * internal decoding functions
512  ************************************************************/
513
514 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
515
516 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
517 {
518     int i, j;
519     int xb, yb;
520
521     xb = g_width >> 3;
522     yb = g_height >> 3;
523     for (j=0; j<yb; j++)
524     {
525         for (i=0; i<xb/2; i++)
526         {
527             dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
528             if (pFrame < g_vBackBuf1)
529                 Warning("mveplay: danger!  pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
530             else if (pFrame >= g_vBackBuf1 + g_width*g_height)
531                 Warning("mveplay: danger!  pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
532             dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
533             if (pFrame < g_vBackBuf1)
534                 Warning("mveplay: danger!  pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
535             else if (pFrame >= g_vBackBuf1 + g_width*g_height)
536                 Warning("mveplay: danger!  pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
537
538             ++pMap;
539             --mapRemain;
540         }
541
542         pFrame += 7*g_width;
543     }
544 }
545
546 static void relClose(int i, int *x, int *y)
547 {
548     int ma, mi;
549
550     ma = i >> 4;
551     mi = i & 0xf;
552
553     *x = mi - 8;
554     *y = ma - 8;
555 }
556
557 static void relFar(int i, int sign, int *x, int *y)
558 {
559     if (i < 56)
560     {
561         *x = sign * (8 + (i % 7));
562         *y = sign *      (i / 7);
563     }
564     else
565     {
566         *x = sign * (-14 + (i - 56) % 29);
567         *y = sign *   (8 + (i - 56) / 29);
568     }
569 }
570
571 static void copyFrame(unsigned char *pDest, unsigned char *pSrc)
572 {
573     int i;
574
575     for (i=0; i<8; i++)
576     {
577         memcpy(pDest, pSrc, 8);
578         pDest += g_width;
579         pSrc += g_width;
580     }
581 }
582
583 static void patternRow4Pixels(unsigned char *pFrame,
584                               unsigned char pat0, unsigned char pat1,
585                               unsigned char *p)
586 {
587     unsigned short mask=0x0003;
588     unsigned short shift=0;
589     unsigned short pattern = (pat1 << 8) | pat0;
590
591     while (mask != 0)
592     {
593         *pFrame++ = p[(mask & pattern) >> shift];
594         mask <<= 2;
595         shift += 2;
596     }
597 }
598
599 static void patternRow4Pixels2(unsigned char *pFrame,
600                                unsigned char pat0,
601                                unsigned char *p)
602 {
603     unsigned char mask=0x03;
604     unsigned char shift=0;
605     unsigned char pel;
606     int skip=1;
607
608     while (mask != 0)
609     {
610         pel = p[(mask & pat0) >> shift];
611         pFrame[0] = pel;
612         pFrame[2] = pel;
613         pFrame[g_width + 0] = pel;
614         pFrame[g_width + 2] = pel;
615         pFrame += skip;
616         skip = 4 - skip;
617         mask <<= 2;
618         shift += 2;
619     }
620 }
621
622 static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p)
623 {
624     unsigned char mask=0x03;
625     unsigned char shift=0;
626     unsigned char pel;
627
628     while (mask != 0)
629     {
630         pel = p[(mask & pat) >> shift];
631         pFrame[0] = pel;
632         pFrame[1] = pel;
633         pFrame += 2;
634         mask <<= 2;
635         shift += 2;
636     }
637 }
638
639 static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p)
640 {
641     unsigned long mask = 0x00000003UL;
642     int shift=0;
643     int i;
644     unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
645
646     for (i=0; i<16; i++)
647     {
648         pFrame[i&3] = p[(pat & mask) >> shift];
649
650         if ((i&3) == 3)
651             pFrame += g_width;
652
653         mask <<= 2;
654         shift += 2;
655     }
656 }
657
658
659 static void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p)
660 {
661     unsigned char mask=0x01;
662
663     while (mask != 0)
664     {
665         *pFrame++ = p[(mask & pat) ? 1 : 0];
666         mask <<= 1;
667     }
668 }
669
670 static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p)
671 {
672     unsigned char pel;
673     unsigned char mask=0x1;
674     int skip=1;
675
676     while (mask != 0x10)
677     {
678         pel = p[(mask & pat) ? 1 : 0];
679         pFrame[0] = pel;
680         pFrame[2] = pel;
681         pFrame[g_width + 0] = pel;
682         pFrame[g_width + 2] = pel;
683         pFrame += skip;
684         skip = 4 - skip;
685         mask <<= 1;
686     }
687 }
688
689 static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p)
690 {
691     unsigned short mask = 0x0001;
692     int i;
693     unsigned short pat = (pat1 << 8) | pat0;
694
695     for (i=0; i<16; i++)
696     {
697         pFrame[i&3] = p[(pat & mask) ? 1 : 0];
698
699         if ((i&3) == 3)
700             pFrame += g_width;
701
702         mask <<= 1;
703     }
704 }
705
706 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
707 {
708     unsigned char p[4];
709     unsigned char pat[16];
710     int i, j, k;
711     int x, y;
712
713     switch(codeType)
714     {
715         case 0x0:
716                   copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
717         case 0x1:
718                   *pFrame += 8;
719                   break;
720
721         case 0x2:
722                   relFar(*(*pData)++, 1, &x, &y);
723                   copyFrame(*pFrame, *pFrame + x + y*g_width);
724                   *pFrame += 8;
725                   --*pDataRemain;
726                   break;
727
728         case 0x3:
729                   relFar(*(*pData)++, -1, &x, &y);
730                   copyFrame(*pFrame, *pFrame + x + y*g_width);
731                   *pFrame += 8;
732                   --*pDataRemain;
733                   break;
734
735         case 0x4:
736                   relClose(*(*pData)++, &x, &y);
737                   copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
738                   *pFrame += 8;
739                   --*pDataRemain;
740                   break;
741
742         case 0x5:
743                   x = (char)*(*pData)++;
744                   y = (char)*(*pData)++;
745                   copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
746                   *pFrame += 8;
747                   *pDataRemain -= 2;
748                   break;
749
750         case 0x6:
751                   for (i=0; i<2; i++)
752                   {
753                       *pFrame += 16;
754                       if (++*curXb == (g_width >> 3))
755                       {
756                           *pFrame += 7*g_width;
757                           *curXb = 0;
758                           if (++*curYb == (g_height >> 3))
759                               return;
760                       }
761                   }
762                   break;
763
764         case 0x7:
765                   p[0] = *(*pData)++;
766                   p[1] = *(*pData)++;
767                   if (p[0] <= p[1])
768                   {
769                       for (i=0; i<8; i++)
770                       {
771                           patternRow2Pixels(*pFrame, *(*pData)++, p);
772                           *pFrame += g_width;
773                       }
774                   }
775                   else
776                   {
777                       for (i=0; i<2; i++)
778                       {
779                           patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
780                           *pFrame += 2*g_width;
781                           patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
782                           *pFrame += 2*g_width;
783                       }
784                   }
785                   *pFrame -= (8*g_width - 8);
786                   break;
787
788         case 0x8:
789                   if ( (*pData)[0] <= (*pData)[1])
790                   {
791                       for (i=0; i<4; i++)
792                       {
793                           p[0] = *(*pData)++;
794                           p[1] = *(*pData)++;
795                           pat[0] = *(*pData)++;
796                           pat[1] = *(*pData)++;
797                           patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
798
799                           if (i & 1)
800                               *pFrame -= (4*g_width - 4);
801                           else
802                               *pFrame += 4*g_width;
803                       }
804                   }
805                   else if ( (*pData)[6] <= (*pData)[7])
806                   {
807                       for (i=0; i<4; i++)
808                       {
809                           if ((i & 1) == 0)
810                           {
811                               p[0] = *(*pData)++;
812                               p[1] = *(*pData)++;
813                           }
814                           pat[0] = *(*pData)++;
815                           pat[1] = *(*pData)++;
816                           patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
817
818                           if (i & 1)
819                               *pFrame -= (4*g_width - 4);
820                           else
821                               *pFrame += 4*g_width;
822                       }
823                   }
824                   else
825                   {
826                       for (i=0; i<8; i++)
827                       {
828                           if ((i & 3) == 0)
829                           {
830                               p[0] = *(*pData)++;
831                               p[1] = *(*pData)++;
832                           }
833                           patternRow2Pixels(*pFrame, *(*pData)++, p);
834                           *pFrame += g_width;
835                       }
836                       *pFrame -= (8*g_width - 8);
837                   }
838                   break;
839
840         case 0x9:
841                   if ( (*pData)[0] <= (*pData)[1])
842                   {
843                       if ( (*pData)[2] <= (*pData)[3])
844                       {
845                           p[0] = *(*pData)++;
846                           p[1] = *(*pData)++;
847                           p[2] = *(*pData)++;
848                           p[3] = *(*pData)++;
849
850                           for (i=0; i<8; i++)
851                           {
852                               pat[0] = *(*pData)++;
853                               pat[1] = *(*pData)++;
854                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
855                               *pFrame += g_width;
856                           }
857
858                           *pFrame -= (8*g_width - 8);
859                       }
860                       else
861                       {
862                           p[0] = *(*pData)++;
863                           p[1] = *(*pData)++;
864                           p[2] = *(*pData)++;
865                           p[3] = *(*pData)++;
866
867                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
868                           *pFrame += 2*g_width;
869                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
870                           *pFrame += 2*g_width;
871                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
872                           *pFrame += 2*g_width;
873                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
874                           *pFrame -= (6*g_width - 8);
875                       }
876                   }
877                   else
878                   {
879                       if ( (*pData)[2] <= (*pData)[3])
880                       {
881                           p[0] = *(*pData)++;
882                           p[1] = *(*pData)++;
883                           p[2] = *(*pData)++;
884                           p[3] = *(*pData)++;
885
886                           for (i=0; i<8; i++)
887                           {
888                               pat[0] = *(*pData)++;
889                               patternRow4Pixels2x1(*pFrame, pat[0], p);
890                               *pFrame += g_width;
891                           }
892
893                           *pFrame -= (8*g_width - 8);
894                       }
895                       else
896                       {
897                           p[0] = *(*pData)++;
898                           p[1] = *(*pData)++;
899                           p[2] = *(*pData)++;
900                           p[3] = *(*pData)++;
901
902                           for (i=0; i<4; i++)
903                           {
904                               pat[0] = *(*pData)++;
905                               pat[1] = *(*pData)++;
906                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
907                               *pFrame += g_width;
908                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
909                               *pFrame += g_width;
910                           }
911
912                           *pFrame -= (8*g_width - 8);
913                       }
914                   }
915                   break;
916
917         case 0xa:
918                   if ( (*pData)[0] <= (*pData)[1])
919                   {
920                       for (i=0; i<4; i++)
921                       {
922                           p[0] = *(*pData)++;
923                           p[1] = *(*pData)++;
924                           p[2] = *(*pData)++;
925                           p[3] = *(*pData)++;
926                           pat[0] = *(*pData)++;
927                           pat[1] = *(*pData)++;
928                           pat[2] = *(*pData)++;
929                           pat[3] = *(*pData)++;
930
931                           patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
932
933                           if (i & 1)
934                               *pFrame -= (4*g_width - 4);
935                           else
936                               *pFrame += 4*g_width;
937                       }
938                   }
939                   else
940                   {
941                       if ( (*pData)[12] <= (*pData)[13])
942                       {
943                           for (i=0; i<4; i++)
944                           {
945                               if ((i&1) == 0)
946                               {
947                                   p[0] = *(*pData)++;
948                                   p[1] = *(*pData)++;
949                                   p[2] = *(*pData)++;
950                                   p[3] = *(*pData)++;
951                               }
952
953                               pat[0] = *(*pData)++;
954                               pat[1] = *(*pData)++;
955                               pat[2] = *(*pData)++;
956                               pat[3] = *(*pData)++;
957
958                               patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
959
960                               if (i & 1)
961                                   *pFrame -= (4*g_width - 4);
962                               else
963                                   *pFrame += 4*g_width;
964                           }
965                       }
966                       else
967                       {
968                           for (i=0; i<8; i++)
969                           {
970                               if ((i&3) == 0)
971                               {
972                                   p[0] = *(*pData)++;
973                                   p[1] = *(*pData)++;
974                                   p[2] = *(*pData)++;
975                                   p[3] = *(*pData)++;
976                               }
977
978                               pat[0] = *(*pData)++;
979                               pat[1] = *(*pData)++;
980                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
981                               *pFrame += g_width;
982                           }
983
984                           *pFrame -= (8*g_width - 8);
985                       }
986                   }
987                   break;
988
989         case 0xb:
990                   for (i=0; i<8; i++)
991                   {
992                       memcpy(*pFrame, *pData, 8);
993                       *pFrame += g_width;
994                       *pData += 8;
995                       *pDataRemain -= 8;
996                   }
997                   *pFrame -= (8*g_width - 8);
998                   break;
999
1000         case 0xc:
1001                   for (i=0; i<4; i++)
1002                   {
1003                       for (j=0; j<2; j++)
1004                       {
1005                           for (k=0; k<4; k++)
1006                           {
1007                               (*pFrame)[j+2*k] = (*pData)[k];
1008                               (*pFrame)[g_width+j+2*k] = (*pData)[k];
1009                           }
1010                           *pFrame += g_width;
1011                       }
1012                       *pData += 4;
1013                       *pDataRemain -= 4;
1014                   }
1015                   *pFrame -= (8*g_width - 8);
1016                   break;
1017
1018         case 0xd:
1019                   for (i=0; i<2; i++)
1020                   {
1021                       for (j=0; j<4; j++)
1022                       {
1023                           for (k=0; k<4; k++)
1024                           {
1025                               (*pFrame)[k*g_width+j] = (*pData)[0];
1026                               (*pFrame)[k*g_width+j+4] = (*pData)[1];
1027                           }
1028                       }
1029                       *pFrame += 4*g_width;
1030                       *pData += 2;
1031                       *pDataRemain -= 2;
1032                   }
1033                   *pFrame -= (8*g_width - 8);
1034                   break;
1035
1036         case 0xe:
1037                   for (i=0; i<8; i++)
1038                   {
1039                       memset(*pFrame, **pData, 8);
1040                       *pFrame += g_width;
1041                   }
1042                   ++*pData;
1043                   --*pDataRemain;
1044                   *pFrame -= (8*g_width - 8);
1045                   break;
1046
1047         case 0xf:
1048                   for (i=0; i<8; i++)
1049                   {
1050                       for (j=0; j<8; j++)
1051                       {
1052                           (*pFrame)[j] = (*pData)[(i+j)&1];
1053                       }
1054                       *pFrame += g_width;
1055                   }
1056                   *pData += 2;
1057                   *pDataRemain -= 2;
1058                   *pFrame -= (8*g_width - 8);
1059                   break;
1060
1061         default:
1062             break;
1063     }
1064 }