]> icculus.org git repositories - btb/d2x.git/blob - main/mveplay.c
restore prototype for swap_polygon_model_data
[btb/d2x.git] / main / mveplay.c
1 /* $Id: mveplay.c,v 1.9 2003-01-15 02:44:31 btb Exp $ */
2
3 #ifdef HAVE_CONFIG_H
4 #include <conf.h>
5 #endif
6
7 #include <string.h>
8 #include <errno.h>
9 #include <time.h>
10 #include <sys/time.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15
16 #include <SDL.h>
17
18 #include "mveplay.h"
19 #include "error.h"
20 #include "u_mem.h"
21 #include "mvelib.h"
22 #include "mve_audio.h"
23 #include "gr.h"
24 #include "palette.h"
25 #include "fix.h"
26 #include "timer.h"
27
28 #ifndef MIN
29 #define MIN(a,b) ((a)<(b)?(a):(b))
30 #endif
31
32 #define MVE_OPCODE_ENDOFSTREAM          0x00
33 #define MVE_OPCODE_ENDOFCHUNK           0x01
34 #define MVE_OPCODE_CREATETIMER          0x02
35 #define MVE_OPCODE_INITAUDIOBUFFERS     0x03
36 #define MVE_OPCODE_STARTSTOPAUDIO       0x04
37 #define MVE_OPCODE_INITVIDEOBUFFERS     0x05
38 #define MVE_OPCODE_UNKNOWN              0x06
39 #define MVE_OPCODE_DISPLAYVIDEO         0x07
40 #define MVE_OPCODE_AUDIOFRAMEDATA       0x08
41 #define MVE_OPCODE_AUDIOFRAMESILENCE    0x09
42 #define MVE_OPCODE_INITVIDEOMODE        0x0A
43 #define MVE_OPCODE_CREATEGRADIENT       0x0B
44 #define MVE_OPCODE_SETPALETTE           0x0C
45 #define MVE_OPCODE_SETPALETTECOMPRESSED 0x0D
46 #define MVE_OPCODE_UNKNOWN2             0x0E
47 #define MVE_OPCODE_SETDECODINGMAP       0x0F
48 #define MVE_OPCODE_UNKNOWN3             0x10
49 #define MVE_OPCODE_VIDEODATA            0x11
50 #define MVE_OPCODE_UNKNOWN4             0x12
51 #define MVE_OPCODE_UNKNOWN5             0x13
52 #define MVE_OPCODE_UNKNOWN6             0x14
53 #define MVE_OPCODE_UNKNOWN7             0x15
54
55 //#define DEBUG
56
57 static int g_spdFactorNum=0;
58 static int g_spdFactorDenom=10;
59
60 static short get_short(unsigned char *data)
61 {
62     short value;
63     value = data[0] | (data[1] << 8);
64     return value;
65 }
66
67 static int get_int(unsigned char *data)
68 {
69     int value;
70     value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
71     return value;
72 }
73
74 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
75 {
76     Warning("mveplay: unknown chunk type %02x/%02x\n", major, minor);
77     return 1;
78 }
79
80 /*************************
81  * general handlers
82  *************************/
83 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
84 {
85     return 0;
86 }
87
88 /*************************
89  * timer handlers
90  *************************/
91
92 /*
93  * timer variables
94  */
95 static fix fix_frame_delay = F0_0;
96 static int timer_started   = 0;
97 static fix timer_expire    = F0_0;
98
99 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
100 {
101     long long temp;
102     int micro_frame_delay = get_int(data) * (int)get_short(data+4);
103
104     if (g_spdFactorNum != 0)
105     {
106         temp = micro_frame_delay;
107         temp *= g_spdFactorNum;
108         temp /= g_spdFactorDenom;
109         micro_frame_delay = (int)temp;
110     }
111         fix_frame_delay = approx_usec_to_fsec(micro_frame_delay);
112
113     return 1;
114 }
115
116 static void timer_stop(void)
117 {
118         timer_expire = F0_0;
119         timer_started = 0;
120 }
121
122 static void timer_start(void)
123 {
124         timer_expire = timer_get_fixed_seconds();
125
126         timer_expire += fix_frame_delay;
127
128     timer_started=1;
129 }
130
131 static void do_timer_wait(void)
132 {
133         fix ts, tv;
134
135     if (! timer_started)
136         return;
137
138         tv = timer_get_fixed_seconds();
139
140         if (tv > timer_expire)
141                 goto end;
142
143         ts = timer_expire - tv;
144
145         timer_delay(ts);
146
147 end:
148         timer_expire += fix_frame_delay;
149 }
150
151 /*************************
152  * audio handlers
153  *************************/
154 #define TOTAL_AUDIO_BUFFERS 64
155
156 static void mve_audio_callback(void *userdata, Uint8 *stream, int len);
157 static short *mve_audio_buffers[TOTAL_AUDIO_BUFFERS];
158 static int    mve_audio_buflens[TOTAL_AUDIO_BUFFERS];
159 static int    mve_audio_curbuf_curpos=0;
160 static int mve_audio_bufhead=0;
161 static int mve_audio_buftail=0;
162 static int mve_audio_playing=0;
163 static int mve_audio_canplay=0;
164 static int mve_audio_compressed=0;
165 static SDL_AudioSpec *mve_audio_spec=NULL;
166
167 static void mve_audio_callback(void *userdata, Uint8 *stream, int len)
168 {
169     int total=0;
170     int length;
171     if (mve_audio_bufhead == mve_audio_buftail)
172         return /* 0 */;
173
174 #ifdef DEBUG
175         fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
176 #endif
177
178     while (mve_audio_bufhead != mve_audio_buftail                                       /* while we have more buffers  */
179             &&  len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos))   /* and while we need more data */
180     {
181         length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
182         __builtin_memcpy(stream,                                                                 /* cur output position */
183                 (unsigned char *)(mve_audio_buffers[mve_audio_bufhead])+mve_audio_curbuf_curpos, /* cur input position  */
184                 length);                                                                         /* cur input length    */
185
186         total += length;
187         stream += length;                                                               /* advance output */
188         len -= length;                                                                  /* decrement avail ospace */
189         d_free(mve_audio_buffers[mve_audio_bufhead]);                                   /* free the buffer */
190         mve_audio_buffers[mve_audio_bufhead]=NULL;                                      /* free the buffer */
191         mve_audio_buflens[mve_audio_bufhead]=0;                                         /* free the buffer */
192
193         if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS)                                 /* next buffer */
194             mve_audio_bufhead = 0;
195         mve_audio_curbuf_curpos = 0;
196     }
197
198 #ifdef DEBUG
199         fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
200 #endif
201 /*    return total; */
202
203     if (len != 0                                                                        /* ospace remaining  */
204             &&  mve_audio_bufhead != mve_audio_buftail)                                 /* buffers remaining */
205     {
206         __builtin_memcpy(stream,                                                                     /* dest   */
207                 (unsigned char *)(mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos,   /* src    */
208                 len);                                                                                /* length */
209
210         mve_audio_curbuf_curpos += len;                                                 /* advance input */
211         stream += len;                                                                  /* advance output (unnecessary) */
212         len -= len;                                                                     /* advance output (unnecessary) */
213
214         if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead])            /* if this ends the current chunk */
215         {
216             d_free(mve_audio_buffers[mve_audio_bufhead]);                               /* free buffer */
217             mve_audio_buffers[mve_audio_bufhead]=NULL;
218             mve_audio_buflens[mve_audio_bufhead]=0;
219
220             if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS)                             /* next buffer */
221                 mve_audio_bufhead = 0;
222             mve_audio_curbuf_curpos = 0;
223         }
224     }
225
226 #ifdef DEBUG
227         fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
228 #endif
229 }
230
231 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
232 {
233     int flags;
234     int sample_rate;
235     int desired_buffer;
236
237 #ifdef DEBUG
238         fprintf(stderr, "creating audio buffers\n");
239 #endif
240
241     flags = get_short(data + 2);
242     sample_rate = get_short(data + 4);
243     desired_buffer = get_int(data + 6);
244
245 #ifdef DEBUG
246         fprintf(stderr, "stereo=%d 16bit=%d compressed=%d sample_rate=%d desired_buffer=%d\n",
247         flags & 1, (flags >> 1) & 1, (flags >> 2) & 1, sample_rate, desired_buffer);
248 #endif
249
250     mve_audio_compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED;
251         if (!mve_audio_spec)
252                 mve_audio_spec = (SDL_AudioSpec *)d_malloc(sizeof(SDL_AudioSpec));
253     mve_audio_spec->freq = sample_rate;
254 #ifdef WORDS_BIGENDIAN
255     mve_audio_spec->format = (flags & MVE_AUDIO_FLAGS_16BIT)?AUDIO_S16MSB:AUDIO_U8;
256 #else
257     mve_audio_spec->format = (flags & MVE_AUDIO_FLAGS_16BIT)?AUDIO_S16LSB:AUDIO_U8;
258 #endif
259     mve_audio_spec->channels = (flags & MVE_AUDIO_FLAGS_STEREO)?2:1;
260     mve_audio_spec->samples = 32768;
261     mve_audio_spec->callback = mve_audio_callback;
262     mve_audio_spec->userdata = NULL;
263     if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
264     {
265 #ifdef DEBUG
266                 fprintf(stderr, "   success\n");
267 #endif
268         mve_audio_canplay = 1;
269     }
270     else
271     {
272 #ifdef DEBUG
273                 fprintf(stderr, "   failure : %s\n", SDL_GetError());
274 #endif
275                 Warning("mveplay: failed to create audio buffers\n");
276         mve_audio_canplay = 0;
277     }
278
279     memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
280     memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
281
282     return 1;
283 }
284
285 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
286 {
287     if (mve_audio_canplay  &&  !mve_audio_playing  &&  mve_audio_bufhead != mve_audio_buftail)
288     {
289         SDL_PauseAudio(0);
290         mve_audio_playing = 1;
291     }
292
293     return 1;
294 }
295
296 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
297 {
298     static const int selected_chan=1;
299     int chan;
300     int nsamp;
301     if (mve_audio_canplay)
302     {
303         if (mve_audio_playing)
304             SDL_LockAudio();
305
306         chan = get_short(data + 2);
307         nsamp = get_short(data + 4);
308         if (chan & selected_chan)
309         {
310             mve_audio_buflens[mve_audio_buftail] = nsamp;
311             if (mve_audio_buffers[mve_audio_buftail])
312                 d_free(mve_audio_buffers[mve_audio_buftail]);
313             mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp+4);
314             if (major == MVE_OPCODE_AUDIOFRAMEDATA)
315                 if (mve_audio_compressed)
316                     mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
317                 else
318                     memcpy(mve_audio_buffers[mve_audio_buftail], data + 6, nsamp);
319             else
320                 // silence
321                 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
322
323             if (++mve_audio_buftail == TOTAL_AUDIO_BUFFERS)
324                 mve_audio_buftail = 0;
325             
326             if (mve_audio_buftail == mve_audio_bufhead)
327                 Warning("mveplay: d'oh!  buffer ring overrun (%d)\n", mve_audio_bufhead);
328         }
329
330         if (mve_audio_playing)
331             SDL_UnlockAudio();
332     }
333
334     return 1;
335 }
336
337 /*************************
338  * video handlers
339  *************************/
340 static grs_bitmap *g_screen;
341 static int g_screenWidth, g_screenHeight;
342 static int g_width, g_height;
343 static unsigned char g_palette[768];
344 static unsigned char *g_vBackBuf1, *g_vBackBuf2 = NULL;
345 static unsigned char *g_pCurMap=NULL;
346 static int g_nMapLength=0;
347
348 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
349 {
350     short w, h;
351     w = get_short(data);
352     h = get_short(data+2);
353     g_width = w << 3;
354     g_height = h << 3;
355 #ifdef DEBUG
356         fprintf(stderr, "g_width, g_height: %d, %d\n", g_width, g_height);
357 #endif
358     Assert((g_width == g_screen->bm_w) && (g_height == g_screen->bm_h));
359         if (!g_vBackBuf1)
360                 g_vBackBuf1 = d_malloc(g_width * g_height);
361         if (!g_vBackBuf2)
362                 g_vBackBuf2 = d_malloc(g_width * g_height);
363     memset(g_vBackBuf1, 0, g_width * g_height);
364     memset(g_vBackBuf2, 0, g_width * g_height);
365     return 1;
366 }
367
368 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
369 {
370     memcpy(g_screen->bm_data, g_vBackBuf1, g_width * g_height);
371
372     return 1;
373 }
374
375 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
376 {
377     short width, height;
378     width = get_short(data);
379     height = get_short(data+2);
380     g_screenWidth = width;
381     g_screenHeight = height;
382     memset(g_palette, 0, 765);
383         // 255 needs to default to white, for subtitles, etc
384         memset(g_palette + 765, 63, 3);
385     return 1;
386 }
387
388 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
389 {
390     short start, count;
391     start = get_short(data);
392     count = get_short(data+2);
393     memcpy(g_palette + 3*start, data+4, 3*count);
394     gr_palette_load(g_palette);
395
396     return 1;
397 }
398
399 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
400 {
401     g_pCurMap = data;
402     g_nMapLength = len;
403     return 1;
404 }
405
406 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
407
408 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
409 {
410     short nFrameHot, nFrameCold;
411     short nXoffset, nYoffset;
412     short nXsize, nYsize;
413     short nFlags;
414     unsigned char *temp;
415
416     nFrameHot  = get_short(data);
417     nFrameCold = get_short(data+2);
418     nXoffset   = get_short(data+4);
419     nYoffset   = get_short(data+6);
420     nXsize     = get_short(data+8);
421     nYsize     = get_short(data+10);
422     nFlags     = get_short(data+12);
423
424     if (nFlags & 1)
425     {
426         temp = g_vBackBuf1;
427         g_vBackBuf1 = g_vBackBuf2;
428         g_vBackBuf2 = temp;
429     }
430
431     /* convert the frame */
432     decodeFrame(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
433
434     return 1;
435 }
436
437 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
438 {
439     g_pCurMap=NULL;
440     return 1;
441 }
442
443 /************************************************************
444  * public mveplay functions
445  ************************************************************/
446
447 void mveplay_initializeMovie(MVESTREAM *mve, grs_bitmap *mve_bitmap)
448 {
449     g_screen = mve_bitmap;
450
451     mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM,          end_movie_handler);
452     mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK,           end_chunk_handler);
453     mve_set_handler(mve, MVE_OPCODE_CREATETIMER,          create_timer_handler);
454     mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS,     create_audiobuf_handler);
455     mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO,       play_audio_handler);
456     mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS,     create_videobuf_handler);
457     mve_set_handler(mve, MVE_OPCODE_UNKNOWN,              default_seg_handler);
458     mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO,         display_video_handler);
459     mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA,       audio_data_handler);
460     mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE,    audio_data_handler);
461     mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE,        init_video_handler);
462     mve_set_handler(mve, MVE_OPCODE_CREATEGRADIENT,       default_seg_handler);
463     mve_set_handler(mve, MVE_OPCODE_SETPALETTE,           video_palette_handler);
464     mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, default_seg_handler);
465     mve_set_handler(mve, MVE_OPCODE_UNKNOWN2,             default_seg_handler);
466     mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP,       video_codemap_handler);
467     mve_set_handler(mve, MVE_OPCODE_UNKNOWN3,             default_seg_handler);
468     mve_set_handler(mve, MVE_OPCODE_VIDEODATA,            video_data_handler);
469     mve_set_handler(mve, MVE_OPCODE_UNKNOWN4,             default_seg_handler);
470     //mve_set_handler(mve, MVE_OPCODE_UNKNOWN5,             default_seg_handler);
471     mve_set_handler(mve, MVE_OPCODE_UNKNOWN6,             default_seg_handler);
472     //mve_set_handler(mve, MVE_OPCODE_UNKNOWN7,             default_seg_handler);
473 }
474
475 int mveplay_stepMovie(MVESTREAM *mve)
476 {
477     static int init_timer=0;
478     int cont=1;
479
480         if (!timer_started)
481                 timer_start();
482
483         cont = mve_play_next_chunk(mve);
484         if (fix_frame_delay  && !init_timer) {
485                 timer_start();
486                 init_timer = 1;
487         }
488
489         do_timer_wait();
490
491         return cont;
492 }
493
494 void mveplay_restartTimer(MVESTREAM *mve)
495 {
496         timer_start();
497 }
498
499 void mveplay_shutdownMovie(MVESTREAM *mve)
500 {
501     int i;
502
503         timer_stop();
504     
505     if (mve_audio_canplay) {
506         // only close audio if we opened it
507         SDL_CloseAudio();
508         mve_audio_canplay = 0;
509     }
510     for (i = 0; i < TOTAL_AUDIO_BUFFERS; i++)
511         if (mve_audio_buffers[i] != NULL)
512             d_free(mve_audio_buffers[i]);
513     memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
514     memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
515         mve_audio_curbuf_curpos=0;
516         mve_audio_bufhead=0;
517         mve_audio_buftail=0;
518         mve_audio_playing=0;
519         mve_audio_canplay=0;
520         mve_audio_compressed=0;
521         if (mve_audio_spec)
522                 d_free(mve_audio_spec);
523         mve_audio_spec=NULL;
524
525     d_free(g_vBackBuf1);
526         g_vBackBuf1 = NULL;
527     d_free(g_vBackBuf2);
528         g_vBackBuf2 = NULL;
529         g_pCurMap=NULL;
530         g_nMapLength=0;
531 }
532
533
534 /************************************************************
535  * internal decoding functions
536  ************************************************************/
537
538 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
539
540 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
541 {
542     int i, j;
543     int xb, yb;
544
545     xb = g_width >> 3;
546     yb = g_height >> 3;
547     for (j=0; j<yb; j++)
548     {
549         for (i=0; i<xb/2; i++)
550         {
551             dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
552             if (pFrame < g_vBackBuf1)
553                 Warning("mveplay: danger!  pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
554             else if (pFrame >= g_vBackBuf1 + g_width*g_height)
555                 Warning("mveplay: danger!  pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
556
557             dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
558             if (pFrame < g_vBackBuf1)
559                 Warning("mveplay: danger!  pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
560             else if (pFrame >= g_vBackBuf1 + g_width*g_height)
561                 Warning("mveplay: danger!  pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
562
563             ++pMap;
564             --mapRemain;
565         }
566
567         pFrame += 7*g_width;
568     }
569 }
570
571 static void relClose(int i, int *x, int *y)
572 {
573     int ma, mi;
574
575     ma = i >> 4;
576     mi = i & 0xf;
577
578     *x = mi - 8;
579     *y = ma - 8;
580 }
581
582 static void relFar(int i, int sign, int *x, int *y)
583 {
584     if (i < 56)
585     {
586         *x = sign * (8 + (i % 7));
587         *y = sign *      (i / 7);
588     }
589     else
590     {
591         *x = sign * (-14 + (i - 56) % 29);
592         *y = sign * (8 + (i - 56) / 29);
593     }
594 }
595
596 /* copies an 8x8 block from pSrc to pDest.
597    pDest and pSrc are both g_width bytes wide */
598 static void copyFrame(unsigned char *pDest, unsigned char *pSrc)
599 {
600     int i;
601
602     for (i=0; i<8; i++)
603     {
604         memcpy(pDest, pSrc, 8);
605         pDest += g_width;
606         pSrc += g_width;
607     }
608 }
609
610 // Fill in the next eight bytes with p[0], p[1], p[2], or p[3],
611 // depending on the corresponding two-bit value in pat0 and pat1
612 static void patternRow4Pixels(unsigned char *pFrame,
613                               unsigned char pat0, unsigned char pat1,
614                               unsigned char *p)
615 {
616     unsigned short mask=0x0003;
617     unsigned short shift=0;
618     unsigned short pattern = (pat1 << 8) | pat0;
619
620     while (mask != 0)
621     {
622         *pFrame++ = p[(mask & pattern) >> shift];
623         mask <<= 2;
624         shift += 2;
625     }
626 }
627
628 // Fill in the next four 2x2 pixel blocks with p[0], p[1], p[2], or p[3],
629 // depending on the corresponding two-bit value in pat0.
630 static void patternRow4Pixels2(unsigned char *pFrame,
631                                unsigned char pat0,
632                                unsigned char *p)
633 {
634     unsigned char mask=0x03;
635     unsigned char shift=0;
636     unsigned char pel;
637
638     while (mask != 0)
639     {
640         pel = p[(mask & pat0) >> shift];
641         pFrame[0] = pel;
642         pFrame[1] = pel;
643         pFrame[g_width + 0] = pel;
644         pFrame[g_width + 1] = pel;
645         pFrame += 2;
646         mask <<= 2;
647         shift += 2;
648     }
649 }
650
651 // Fill in the next four 2x1 pixel blocks with p[0], p[1], p[2], or p[3],
652 // depending on the corresponding two-bit value in pat.
653 static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p)
654 {
655     unsigned char mask=0x03;
656     unsigned char shift=0;
657     unsigned char pel;
658
659     while (mask != 0)
660     {
661         pel = p[(mask & pat) >> shift];
662         pFrame[0] = pel;
663         pFrame[1] = pel;
664         pFrame += 2;
665         mask <<= 2;
666         shift += 2;
667     }
668 }
669
670 // Fill in the next 4x4 pixel block with p[0], p[1], p[2], or p[3],
671 // depending on the corresponding two-bit value in pat0, pat1, pat2, and pat3.
672 static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p)
673 {
674     unsigned long mask = 0x00000003UL;
675     int shift=0;
676     int i;
677     unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
678
679     for (i=0; i<16; i++)
680     {
681         pFrame[i&3] = p[(pat & mask) >> shift];
682
683         if ((i&3) == 3)
684             pFrame += g_width;
685
686         mask <<= 2;
687         shift += 2;
688     }
689 }
690
691 // fills the next 8 pixels with either p[0] or p[1], depending on pattern
692 static void patternRow2Pixels(unsigned char *pFrame, unsigned char pattern, unsigned char *p)
693 {
694     unsigned char mask=0x01;
695     
696     while (mask != 0)
697     {
698         *pFrame++ = p[(mask & pattern) ? 1 : 0];
699         mask <<= 1;
700     }
701 }
702
703 // fills the next four 2 x 2 pixel boxes with either p[0] or p[1], depending on pattern
704 static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pattern, unsigned char *p)
705 {
706     unsigned char pel;
707     unsigned char mask=0x1;
708
709     while (mask != 0x10)
710     {
711         pel = p[(mask & pattern) ? 1 : 0];
712
713         pFrame[0] = pel;              // upper-left
714         pFrame[1] = pel;              // upper-right
715         pFrame[g_width + 0] = pel;    // lower-left
716         pFrame[g_width + 1] = pel;    // lower-right
717         pFrame += 2;
718
719         mask <<= 1;
720     }
721 }
722
723 // fills pixels in the next 4 x 4 pixel boxes with either p[0] or p[1], depending on pat0 and pat1.
724 static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p)
725 {
726     unsigned char pel;
727     unsigned short mask = 0x0001;
728     int i;
729     int j;
730     unsigned short pat = (pat1 << 8) | pat0;
731
732     for (i=0; i<4; i++)
733     {
734         for (j=0; j<4; j++) 
735         {
736             pel = p[(pat & mask) ? 1 : 0];
737
738             pFrame[j + i * g_width] = pel;
739
740             mask <<= 1;
741         }
742     }
743 }
744
745 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
746 {
747     unsigned char p[4];
748     unsigned char pat[16];
749     int i, j, k;
750     int x, y;
751
752     /* Data is processed in 8x8 pixel blocks.
753        There are 16 ways to encode each block.
754     */
755
756     switch(codeType)
757     {
758         case 0x0:
759                   /* block is copied from block in current frame */
760                   copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
761         case 0x1:
762                   /* block is unchanged from two frames ago */
763                   *pFrame += 8;
764                   break;
765
766         case 0x2:
767                   /* Block is copied from nearby (below and/or to the right) within the
768                      new frame.  The offset within the buffer from which to grab the
769                      patch of 8 pixels is given by grabbing a byte B from the data
770                      stream, which is broken into a positive x and y offset according
771                      to the following mapping:
772
773                         if B < 56:
774                             x = 8 + (B % 7)
775                             y = B / 7
776                         else
777                             x = -14 + ((B - 56) % 29)
778                             y =   8 + ((B - 56) / 29)
779                   */
780                   relFar(*(*pData)++, 1, &x, &y);
781                   copyFrame(*pFrame, *pFrame + x + y*g_width);
782                   *pFrame += 8;
783                   --*pDataRemain;
784                   break;
785
786          case 0x3:
787                   /* Block is copied from nearby (above and/or to the left) within the
788                      new frame.
789
790                         if B < 56:
791                             x = -(8 + (B % 7))
792                             y = -(B / 7)
793                         else
794                             x = -(-14 + ((B - 56) % 29))
795                             y = -(  8 + ((B - 56) / 29))
796                   */
797                   relFar(*(*pData)++, -1, &x, &y);
798                   copyFrame(*pFrame, *pFrame + x + y*g_width);
799                   *pFrame += 8;
800                   --*pDataRemain;
801                   break;
802
803         case 0x4:
804                   /* Similar to 0x2 and 0x3, except this method copies from the
805                      "current" frame, rather than the "new" frame, and instead of the
806                      lopsided mapping they use, this one uses one which is symmetric
807                      and centered around the top-left corner of the block.  This uses
808                      only 1 byte still, though, so the range is decreased, since we
809                      have to encode all directions in a single byte.  The byte we pull
810                      from the data stream, I'll call B.  Call the highest 4 bits of B
811                      BH and the lowest 4 bytes BL.  Then the offset from which to copy
812                      the data is:
813
814                          x = -8 + BL
815                          y = -8 + BH
816                   */
817                   relClose(*(*pData)++, &x, &y);
818                   copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
819                   *pFrame += 8;
820                   --*pDataRemain;
821                   break;
822
823         case 0x5:
824                   /* Similar to 0x4, but instead of one byte for the offset, this uses
825                      two bytes to encode a larger range, the first being the x offset
826                      as a signed 8-bit value, and the second being the y offset as a
827                      signed 8-bit value.
828                   */
829                   x = (signed char)*(*pData)++;
830                   y = (signed char)*(*pData)++;
831                   copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
832                   *pFrame += 8;
833                   *pDataRemain -= 2;
834                   break;
835
836         case 0x6:
837                   /* I can't figure out how any file containing a block of this type
838                      could still be playable, since it appears that it would leave the
839                      internal bookkeeping in an inconsistent state in the BG player
840                      code.  Ahh, well.  Perhaps it was a bug in the BG player code that
841                      just didn't happen to be exposed by any of the included movies.
842                      Anyway, this skips the next two blocks, doing nothing to them.
843                      Note that if you've reached the end of a row, this means going on
844                      to the next row.
845                   */
846                   for (i=0; i<2; i++)
847                   {
848                       *pFrame += 16;
849                       if (++*curXb == (g_width >> 3))
850                       {
851                           *pFrame += 7*g_width;
852                           *curXb = 0;
853                           if (++*curYb == (g_height >> 3))
854                               return;
855                       }
856                   }
857                   break;
858
859         case 0x7:
860                   /* Ok, here's where it starts to get really...interesting.  This is,
861                      incidentally, the part where they started using self-modifying
862                      code.  So, most of the following encodings are "patterned" blocks,
863                      where we are given a number of pixel values and then bitmapped
864                      values to specify which pixel values belong to which squares.  For
865                      this encoding, we are given the following in the data stream:
866                      
867                          P0 P1
868
869                      These are pixel values (i.e. 8-bit indices into the palette).  If
870                      P0 <= P1, we then get 8 more bytes from the data stream, one for
871                      each row in the block:
872
873                          B0 B1 B2 B3 B4 B5 B6 B7
874
875                      For each row, the leftmost pixel is represented by the low-order
876                      bit, and the rightmost by the high-order bit.  Use your imagination
877                      in between.  If a bit is set, the pixel value is P1 and if it is
878                      unset, the pixel value is P0.
879
880                      So, for example, if we had:
881
882                          11 22 fe 83 83 83 83 83 83 fe
883
884                      This would represent the following layout:
885
886                          11 22 22 22 22 22 22 22     ; fe == 11111110
887                          22 22 11 11 11 11 11 22     ; 83 == 10000011
888                          22 22 11 11 11 11 11 22     ; 83 == 10000011
889                          22 22 11 11 11 11 11 22     ; 83 == 10000011
890                          22 22 11 11 11 11 11 22     ; 83 == 10000011
891                          22 22 11 11 11 11 11 22     ; 83 == 10000011
892                          22 22 11 11 11 11 11 22     ; 83 == 10000011
893                          11 22 22 22 22 22 22 22     ; fe == 11111110
894
895                      If, on the other hand, P0 > P1, we get two more bytes from the
896                      data stream:
897
898                          B0 B1
899
900                      Each of these bytes contains two 4-bit patterns. These patterns 
901                      work like the patterns above with 8 bytes, except each bit 
902                      represents a 2x2 pixel region. 
903
904                      B0 contains the pattern for the top two rows and B1 contains 
905                      the pattern for the bottom two rows.  Note that the low-order
906                      nibble of each byte contains the pattern for the upper of the
907                      two rows that that byte controls.
908
909                      So if we had:
910                      
911                          22 11 7e 83
912
913                      The output would be:
914                      
915                          11 11 22 22 22 22 22 22     ; e == 1 1 1 0
916                          11 11 22 22 22 22 22 22     ; 
917                          22 22 22 22 22 22 11 11     ; 7 == 0 1 1 1
918                          22 22 22 22 22 22 11 11     ; 
919                          11 11 11 11 11 11 22 22     ; 3 == 1 0 0 0
920                          11 11 11 11 11 11 22 22     ; 
921                          22 22 22 22 11 11 11 11     ; 8 == 0 0 1 1
922                          22 22 22 22 11 11 11 11     ; 
923                   */
924                   p[0] = *(*pData)++;
925                   p[1] = *(*pData)++;
926                   if (p[0] <= p[1])
927                   {
928                       for (i=0; i<8; i++)
929                       {
930                           patternRow2Pixels(*pFrame, *(*pData)++, p);
931                           *pFrame += g_width;
932                       }
933                   }
934                   else
935                   {
936                       for (i=0; i<2; i++)
937                       {
938                           patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
939                           *pFrame += 2*g_width;
940                           patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
941                           *pFrame += 2*g_width;
942                       }
943                   }
944                   *pFrame -= (8*g_width - 8);
945                   break;
946
947         case 0x8: 
948                   /* Ok, this one is basically like encoding 0x7, only more
949                      complicated.  Again, we start out by getting two bytes on the data
950                      stream:
951
952                          P0 P1
953
954                      if P0 <= P1 then we get the following from the data stream:
955
956                                B0 B1
957                          P2 P3 B2 B3
958                          P4 P5 B4 B5
959                          P6 P7 B6 B7
960                      
961                      P0 P1 and B0 B1 are used for the top-left corner, P2 P3 B2 B3 for
962                      the bottom-left corner, P4 P5 B4 B5 for the top-right, P6 P7 B6 B7
963                      for the bottom-right.  (So, each codes for a 4x4 pixel array.)
964                      Since we have 16 bits in B0 B1, there is one bit for each pixel in
965                      the array.  The convention for the bit-mapping is, again, left to
966                      right and top to bottom.
967
968                      So, basically, the top-left quarter of the block is an arbitrary
969                      pattern with 2 pixels, the bottom-left a different arbitrary
970                      pattern with 2 different pixels, and so on.  
971
972                      For example if the next 16 bytes were:
973
974                         00 22 f9 9f  44 55 aa 55  11 33 cc 33  66 77 01 ef
975
976                      We'd draw:
977                         
978                         22 22 22 22 | 11 11 33 33     ; f = 1111, c = 1100
979                         22 00 00 22 | 11 11 33 33     ; 9 = 1001, c = 1100
980                         22 00 00 22 | 33 33 11 11     ; 9 = 1001, 3 = 0011
981                         22 22 22 22 | 33 33 11 11     ; f = 1111, 3 = 0011
982                         ------------+------------
983                         44 55 44 55 | 66 66 66 66     ; a = 1010, 0 = 0000
984                         44 55 44 55 | 77 66 66 66     ; a = 1010, 1 = 0001
985                         55 44 55 44 | 66 77 77 77     ; 5 = 0101, e = 1110
986                         55 44 55 44 | 77 77 77 77     ; 5 = 0101, f = 1111
987                         
988                     I've added a dividing line in the above to clearly delineate the
989                     quadrants.
990
991
992                     Now, if P0 > P1 then we get 10 more bytes from the data stream:
993
994                         B0 B1 B2 B3 P2 P3 B4 B5 B6 B7
995
996                     Now, if P2 <= P3, then the first six bytes [P0 P1 B0 B1 B2 B3]
997                     represent the left half of the block and the latter six bytes
998                     [P2 P3 B4 B5 B6 B7] represent the right half.
999
1000                     For example:
1001
1002                         22 00 01 37 f7 31   11 66 8c e6 73 31
1003
1004                     yeilds:
1005                 
1006                         22 22 22 22 | 11 11 11 66     ; 0: 0000 | 8: 1000
1007                         00 22 22 22 | 11 11 66 66     ; 1: 0001 | C: 1100
1008                         00 00 22 22 | 11 66 66 66     ; 3: 0011 | e: 1110
1009                         00 00 00 22 | 11 66 11 66     ; 7: 0111 | 6: 0101
1010                         00 00 00 00 | 66 66 66 11     ; f: 1111 | 7: 0111
1011                         00 00 00 22 | 66 66 11 11     ; 7: 0111 | 3: 0011   
1012                         00 00 22 22 | 66 66 11 11     ; 3: 0011 | 3: 0011
1013                         00 22 22 22 | 66 11 11 11     ; 1: 0001 | 1: 0001
1014
1015
1016                     On the other hand, if P0 > P1 and P2 > P3, then
1017                     [P0 P1 B0 B1 B2 B3] represent the top half of the
1018                     block and [P2 P3 B4 B5 B6 B7] represent the bottom half.
1019
1020                     For example:
1021
1022                         22 00 cc 66 33 19   66 11 18 24 42 81
1023
1024                     yeilds:
1025
1026                         22 22 00 00 22 22 00 00     ; cc: 11001100
1027                         22 00 00 22 22 00 00 22     ; 66: 01100110
1028                         00 00 22 22 00 00 22 22     ; 33: 00110011
1029                         00 22 22 00 00 22 22 22     ; 19: 00011001
1030                         -----------------------     
1031                         66 66 66 11 11 66 66 66     ; 18: 00011000
1032                         66 66 11 66 66 11 66 66     ; 24: 00100100
1033                         66 11 66 66 66 66 11 66     ; 42: 01000010
1034                         11 66 66 66 66 66 66 11     ; 81: 10000001
1035                   */
1036                   if ( (*pData)[0] <= (*pData)[1])
1037                   {
1038                       // four quadrant case
1039                       for (i=0; i<4; i++)
1040                       {
1041                           p[0] = *(*pData)++;
1042                           p[1] = *(*pData)++;
1043                           pat[0] = *(*pData)++;
1044                           pat[1] = *(*pData)++;
1045                           patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
1046                                   
1047                           // alternate between moving down and moving up and right
1048                           if (i & 1)
1049                               *pFrame += 4 - 4*g_width; // up and right
1050                           else
1051                               *pFrame += 4*g_width;     // down
1052                       }
1053                   }
1054                   else if ( (*pData)[6] <= (*pData)[7])
1055                   {
1056                       // split horizontal
1057                       for (i=0; i<4; i++)
1058                       {
1059                           if ((i & 1) == 0)
1060                           {
1061                               p[0] = *(*pData)++;
1062                               p[1] = *(*pData)++;
1063                           }
1064                           pat[0] = *(*pData)++;
1065                           pat[1] = *(*pData)++;
1066                           patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
1067
1068                           if (i & 1)
1069                               *pFrame -= (4*g_width - 4);
1070                           else
1071                               *pFrame += 4*g_width;
1072                       }
1073                   }
1074                   else
1075                   {
1076                       // split vertical
1077                       for (i=0; i<8; i++)
1078                       {
1079                           if ((i & 3) == 0)
1080                           {
1081                               p[0] = *(*pData)++;
1082                               p[1] = *(*pData)++;
1083                           }
1084                           patternRow2Pixels(*pFrame, *(*pData)++, p);
1085                           *pFrame += g_width;
1086                       }
1087                       *pFrame -= (8*g_width - 8);
1088                   }
1089                   break;
1090
1091         case 0x9:
1092                   /* Similar to the previous 2 encodings, only more complicated.  And
1093                      it will get worse before it gets better.  No longer are we dealing
1094                      with patterns over two pixel values.  Now we are dealing with
1095                      patterns over 4 pixel values with 2 bits assigned to each pixel
1096                      (or block of pixels).
1097
1098                      So, first on the data stream are our 4 pixel values:
1099
1100                          P0 P1 P2 P3
1101
1102                      Now, if P0 <= P1  AND  P2 <= P3, we get 16 bytes of pattern, each
1103                      2 bits representing a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3).  The
1104                      ordering is again left to right and top to bottom.  The most
1105                      significant bits represent the left side at the top, and so on.
1106
1107                      If P0 <= P1  AND  P2 > P3, we get 4 bytes of pattern, each 2 bits
1108                      representing a 2x2 pixel.  Ordering is left to right and top to
1109                      bottom.
1110
1111                      if P0 > P1  AND  P2 <= P3, we get 8 bytes of pattern, each 2 bits
1112                      representing a 2x1 pixel (i.e. 2 pixels wide, and 1 high).
1113
1114                      if P0 > P1  AND  P2 > P3, we get 8 bytes of pattern, each 2 bits
1115                      representing a 1x2 pixel (i.e. 1 pixel wide, and 2 high).
1116                   */
1117                   if ( (*pData)[0] <= (*pData)[1])
1118                   {
1119                       if ( (*pData)[2] <= (*pData)[3])
1120                       {
1121                           p[0] = *(*pData)++;
1122                           p[1] = *(*pData)++;
1123                           p[2] = *(*pData)++;
1124                           p[3] = *(*pData)++;
1125
1126                           for (i=0; i<8; i++)
1127                           {
1128                               pat[0] = *(*pData)++;
1129                               pat[1] = *(*pData)++;
1130                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1131                               *pFrame += g_width;
1132                           }
1133
1134                           *pFrame -= (8*g_width - 8);
1135                       }
1136                       else
1137                       {
1138                           p[0] = *(*pData)++;
1139                           p[1] = *(*pData)++;
1140                           p[2] = *(*pData)++;
1141                           p[3] = *(*pData)++;
1142
1143                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
1144                           *pFrame += 2*g_width;
1145                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
1146                           *pFrame += 2*g_width;
1147                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
1148                           *pFrame += 2*g_width;
1149                           patternRow4Pixels2(*pFrame, *(*pData)++, p);
1150                           *pFrame -= (6*g_width - 8);
1151                       }
1152                   }
1153                   else
1154                   {
1155                       if ( (*pData)[2] <= (*pData)[3])
1156                       {
1157                           // draw 2x1 strips
1158                           p[0] = *(*pData)++;
1159                           p[1] = *(*pData)++;
1160                           p[2] = *(*pData)++;
1161                           p[3] = *(*pData)++;
1162
1163                           for (i=0; i<8; i++)
1164                           {
1165                               pat[0] = *(*pData)++;
1166                               patternRow4Pixels2x1(*pFrame, pat[0], p);
1167                               *pFrame += g_width;
1168                           }
1169
1170                           *pFrame -= (8*g_width - 8);
1171                       }
1172                       else
1173                       {
1174                           // draw 1x2 strips
1175                           p[0] = *(*pData)++;
1176                           p[1] = *(*pData)++;
1177                           p[2] = *(*pData)++;
1178                           p[3] = *(*pData)++;
1179
1180                           for (i=0; i<4; i++)
1181                           {
1182                               pat[0] = *(*pData)++;
1183                               pat[1] = *(*pData)++;
1184                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1185                               *pFrame += g_width;
1186                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1187                               *pFrame += g_width;
1188                           }
1189
1190                           *pFrame -= (8*g_width - 8);
1191                       }
1192                   }
1193                   break;
1194
1195         case 0xa:
1196                   /* Similar to the previous, only a little more complicated.
1197
1198                      We are still dealing with patterns over 4 pixel values with 2 bits
1199                      assigned to each pixel (or block of pixels).
1200
1201                      So, first on the data stream are our 4 pixel values:
1202
1203                          P0 P1 P2 P3
1204
1205                      Now, if P0 <= P1, the block is divided into 4 quadrants, ordered
1206                      (as with opcode 0x8) TL, BL, TR, BR.  In this case the next data
1207                      in the data stream should be:
1208
1209                                          B0  B1  B2  B3
1210                          P4  P5  P6  P7  B4  B5  B6  B7
1211                          P8  P9  P10 P11 B8  B9  B10 B11
1212                          P12 P13 P14 P15 B12 B13 B14 B15
1213
1214                      Each 2 bits represent a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3).
1215                      The ordering is again left to right and top to bottom.  The most
1216                      significant bits represent the right side at the top, and so on.
1217
1218                      If P0 > P1 then the next data on the data stream is:
1219                      
1220                                      B0 B1 B2  B3  B4  B5  B6  B7
1221                          P4 P5 P6 P7 B8 B9 B10 B11 B12 B13 B14 B15
1222
1223                      Now, in this case, if P4 <= P5,
1224                      [P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the left half of
1225                      the block and the other bytes represent the right half.  If P4 >
1226                      P5, then [P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the top
1227                      half of the block and the other bytes represent the bottom half.
1228                   */
1229                   if ( (*pData)[0] <= (*pData)[1])
1230                   {
1231                       for (i=0; i<4; i++)
1232                       {
1233                           p[0] = *(*pData)++;
1234                           p[1] = *(*pData)++;
1235                           p[2] = *(*pData)++;
1236                           p[3] = *(*pData)++;
1237                           pat[0] = *(*pData)++;
1238                           pat[1] = *(*pData)++;
1239                           pat[2] = *(*pData)++;
1240                           pat[3] = *(*pData)++;
1241
1242                           patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
1243
1244                           if (i & 1)
1245                               *pFrame -= (4*g_width - 4);
1246                           else
1247                               *pFrame += 4*g_width;
1248                       }
1249                   }
1250                   else
1251                   {
1252                       if ( (*pData)[12] <= (*pData)[13])
1253                       {
1254                           // split vertical
1255                           for (i=0; i<4; i++)
1256                           {
1257                               if ((i&1) == 0)
1258                               {
1259                                   p[0] = *(*pData)++;
1260                                   p[1] = *(*pData)++;
1261                                   p[2] = *(*pData)++;
1262                                   p[3] = *(*pData)++;
1263                               }
1264
1265                               pat[0] = *(*pData)++;
1266                               pat[1] = *(*pData)++;
1267                               pat[2] = *(*pData)++;
1268                               pat[3] = *(*pData)++;
1269
1270                               patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
1271
1272                               if (i & 1)
1273                                   *pFrame -= (4*g_width - 4);
1274                               else
1275                                   *pFrame += 4*g_width;
1276                           }
1277                       }
1278                       else
1279                       {
1280                           // split horizontal
1281                           for (i=0; i<8; i++)
1282                           {
1283                               if ((i&3) == 0)
1284                               {
1285                                   p[0] = *(*pData)++;
1286                                   p[1] = *(*pData)++;
1287                                   p[2] = *(*pData)++;
1288                                   p[3] = *(*pData)++;
1289                               }
1290
1291                               pat[0] = *(*pData)++;
1292                               pat[1] = *(*pData)++;
1293                               patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1294                               *pFrame += g_width;
1295                           }
1296
1297                           *pFrame -= (8*g_width - 8);
1298                       }
1299                   }
1300                   break;
1301
1302         case 0xb:
1303                   /* In this encoding we get raw pixel data in the data stream -- 64
1304                      bytes of pixel data.  1 byte for each pixel, and in the standard
1305                      order (l->r, t->b).
1306                   */
1307                   for (i=0; i<8; i++)
1308                   {
1309                       memcpy(*pFrame, *pData, 8);
1310                       *pFrame += g_width;
1311                       *pData += 8;
1312                       *pDataRemain -= 8;
1313                   }
1314                   *pFrame -= (8*g_width - 8);
1315                   break;
1316
1317         case 0xc:
1318                   /* In this encoding we get raw pixel data in the data stream -- 16
1319                      bytes of pixel data.  1 byte for each block of 2x2 pixels, and in
1320                      the standard order (l->r, t->b).
1321                   */
1322                   for (i=0; i<4; i++)
1323                   {
1324                       for (j=0; j<2; j++)
1325                       {
1326                           for (k=0; k<4; k++)
1327                           {
1328                               (*pFrame)[2*k]   = (*pData)[k];
1329                               (*pFrame)[2*k+1] = (*pData)[k];
1330                           }
1331                           *pFrame += g_width;
1332                       }
1333                       *pData += 4;
1334                       *pDataRemain -= 4;
1335                   }
1336                   *pFrame -= (8*g_width - 8);
1337                   break;
1338
1339         case 0xd:
1340                   /* In this encoding we get raw pixel data in the data stream -- 4
1341                      bytes of pixel data.  1 byte for each block of 4x4 pixels, and in
1342                      the standard order (l->r, t->b).
1343                   */
1344                   for (i=0; i<2; i++)
1345                   {
1346                       for (j=0; j<4; j++)
1347                       {
1348                           for (k=0; k<4; k++)
1349                           {
1350                               (*pFrame)[k*g_width+j] = (*pData)[0];
1351                               (*pFrame)[k*g_width+j+4] = (*pData)[1];
1352                           }
1353                       }
1354                       *pFrame += 4*g_width;
1355                       *pData += 2;
1356                       *pDataRemain -= 2;
1357                   }
1358                   *pFrame -= (8*g_width - 8);
1359                   break;
1360
1361         case 0xe:
1362                   /* This encoding represents a solid 8x8 frame.  We get 1 byte of pixel
1363                      data from the data stream.
1364                   */
1365                   for (i=0; i<8; i++)
1366                   {
1367                       memset(*pFrame, **pData, 8);
1368                       *pFrame += g_width;
1369                   }
1370                   ++*pData;
1371                   --*pDataRemain;
1372                   *pFrame -= (8*g_width - 8);
1373                   break;
1374
1375         case 0xf:
1376                   /* This encoding represents a "dithered" frame, which is
1377                      checkerboarded with alternate pixels of two colors.  We get 2
1378                      bytes of pixel data from the data stream, and these bytes are
1379                      alternated:
1380
1381                          P0 P1 P0 P1 P0 P1 P0 P1
1382                          P1 P0 P1 P0 P1 P0 P1 P0
1383                          ...
1384                          P0 P1 P0 P1 P0 P1 P0 P1
1385                          P1 P0 P1 P0 P1 P0 P1 P0
1386                   */
1387                   for (i=0; i<8; i++)
1388                   {
1389                       for (j=0; j<8; j++)
1390                       {
1391                           (*pFrame)[j] = (*pData)[(i+j)&1];
1392                       }
1393                       *pFrame += g_width;
1394                   }
1395                   *pData += 2;
1396                   *pDataRemain -= 2;
1397                   *pFrame -= (8*g_width - 8);
1398                   break;
1399
1400         default:
1401             break;
1402     }
1403 }