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