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