1 /* $Id: mveplay.c,v 1.9 2003-01-15 02:44:31 btb Exp $ */
11 #include <sys/types.h>
22 #include "mve_audio.h"
29 #define MIN(a,b) ((a)<(b)?(a):(b))
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
57 static int g_spdFactorNum=0;
58 static int g_spdFactorDenom=10;
60 static short get_short(unsigned char *data)
63 value = data[0] | (data[1] << 8);
67 static int get_int(unsigned char *data)
70 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
74 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
76 Warning("mveplay: unknown chunk type %02x/%02x\n", major, minor);
80 /*************************
82 *************************/
83 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
88 /*************************
90 *************************/
95 static fix fix_frame_delay = F0_0;
96 static int timer_started = 0;
97 static fix timer_expire = F0_0;
99 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
102 int micro_frame_delay = get_int(data) * (int)get_short(data+4);
104 if (g_spdFactorNum != 0)
106 temp = micro_frame_delay;
107 temp *= g_spdFactorNum;
108 temp /= g_spdFactorDenom;
109 micro_frame_delay = (int)temp;
111 fix_frame_delay = approx_usec_to_fsec(micro_frame_delay);
116 static void timer_stop(void)
122 static void timer_start(void)
124 timer_expire = timer_get_fixed_seconds();
126 timer_expire += fix_frame_delay;
131 static void do_timer_wait(void)
138 tv = timer_get_fixed_seconds();
140 if (tv > timer_expire)
143 ts = timer_expire - tv;
148 timer_expire += fix_frame_delay;
151 /*************************
153 *************************/
154 #define TOTAL_AUDIO_BUFFERS 64
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;
167 static void mve_audio_callback(void *userdata, Uint8 *stream, int len)
171 if (mve_audio_bufhead == mve_audio_buftail)
175 fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
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 */
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 */
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 */
193 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
194 mve_audio_bufhead = 0;
195 mve_audio_curbuf_curpos = 0;
199 fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
203 if (len != 0 /* ospace remaining */
204 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
206 __builtin_memcpy(stream, /* dest */
207 (unsigned char *)(mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */
210 mve_audio_curbuf_curpos += len; /* advance input */
211 stream += len; /* advance output (unnecessary) */
212 len -= len; /* advance output (unnecessary) */
214 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
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;
220 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
221 mve_audio_bufhead = 0;
222 mve_audio_curbuf_curpos = 0;
227 fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
231 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
238 fprintf(stderr, "creating audio buffers\n");
241 flags = get_short(data + 2);
242 sample_rate = get_short(data + 4);
243 desired_buffer = get_int(data + 6);
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);
250 mve_audio_compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED;
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;
257 mve_audio_spec->format = (flags & MVE_AUDIO_FLAGS_16BIT)?AUDIO_S16LSB:AUDIO_U8;
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)
266 fprintf(stderr, " success\n");
268 mve_audio_canplay = 1;
273 fprintf(stderr, " failure : %s\n", SDL_GetError());
275 Warning("mveplay: failed to create audio buffers\n");
276 mve_audio_canplay = 0;
279 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
280 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
285 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
287 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
290 mve_audio_playing = 1;
296 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
298 static const int selected_chan=1;
301 if (mve_audio_canplay)
303 if (mve_audio_playing)
306 chan = get_short(data + 2);
307 nsamp = get_short(data + 4);
308 if (chan & selected_chan)
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 */
318 memcpy(mve_audio_buffers[mve_audio_buftail], data + 6, nsamp);
321 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
323 if (++mve_audio_buftail == TOTAL_AUDIO_BUFFERS)
324 mve_audio_buftail = 0;
326 if (mve_audio_buftail == mve_audio_bufhead)
327 Warning("mveplay: d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
330 if (mve_audio_playing)
337 /*************************
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;
348 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
352 h = get_short(data+2);
356 fprintf(stderr, "g_width, g_height: %d, %d\n", g_width, g_height);
358 Assert((g_width == g_screen->bm_w) && (g_height == g_screen->bm_h));
360 g_vBackBuf1 = d_malloc(g_width * g_height);
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);
368 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
370 memcpy(g_screen->bm_data, g_vBackBuf1, g_width * g_height);
375 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
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);
388 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
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);
399 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
406 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
408 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
410 short nFrameHot, nFrameCold;
411 short nXoffset, nYoffset;
412 short nXsize, nYsize;
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);
427 g_vBackBuf1 = g_vBackBuf2;
431 /* convert the frame */
432 decodeFrame(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
437 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
443 /************************************************************
444 * public mveplay functions
445 ************************************************************/
447 void mveplay_initializeMovie(MVESTREAM *mve, grs_bitmap *mve_bitmap)
449 g_screen = mve_bitmap;
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);
475 int mveplay_stepMovie(MVESTREAM *mve)
477 static int init_timer=0;
483 cont = mve_play_next_chunk(mve);
484 if (fix_frame_delay && !init_timer) {
494 void mveplay_restartTimer(MVESTREAM *mve)
499 void mveplay_shutdownMovie(MVESTREAM *mve)
505 if (mve_audio_canplay) {
506 // only close audio if we opened it
508 mve_audio_canplay = 0;
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;
520 mve_audio_compressed=0;
522 d_free(mve_audio_spec);
534 /************************************************************
535 * internal decoding functions
536 ************************************************************/
538 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
540 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
549 for (i=0; i<xb/2; i++)
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);
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);
571 static void relClose(int i, int *x, int *y)
582 static void relFar(int i, int sign, int *x, int *y)
586 *x = sign * (8 + (i % 7));
591 *x = sign * (-14 + (i - 56) % 29);
592 *y = sign * (8 + (i - 56) / 29);
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)
604 memcpy(pDest, pSrc, 8);
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,
616 unsigned short mask=0x0003;
617 unsigned short shift=0;
618 unsigned short pattern = (pat1 << 8) | pat0;
622 *pFrame++ = p[(mask & pattern) >> shift];
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,
634 unsigned char mask=0x03;
635 unsigned char shift=0;
640 pel = p[(mask & pat0) >> shift];
643 pFrame[g_width + 0] = pel;
644 pFrame[g_width + 1] = pel;
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)
655 unsigned char mask=0x03;
656 unsigned char shift=0;
661 pel = p[(mask & pat) >> shift];
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)
674 unsigned long mask = 0x00000003UL;
677 unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
681 pFrame[i&3] = p[(pat & mask) >> shift];
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)
694 unsigned char mask=0x01;
698 *pFrame++ = p[(mask & pattern) ? 1 : 0];
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)
707 unsigned char mask=0x1;
711 pel = p[(mask & pattern) ? 1 : 0];
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
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)
727 unsigned short mask = 0x0001;
730 unsigned short pat = (pat1 << 8) | pat0;
736 pel = p[(pat & mask) ? 1 : 0];
738 pFrame[j + i * g_width] = pel;
745 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
748 unsigned char pat[16];
752 /* Data is processed in 8x8 pixel blocks.
753 There are 16 ways to encode each block.
759 /* block is copied from block in current frame */
760 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
762 /* block is unchanged from two frames ago */
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:
777 x = -14 + ((B - 56) % 29)
778 y = 8 + ((B - 56) / 29)
780 relFar(*(*pData)++, 1, &x, &y);
781 copyFrame(*pFrame, *pFrame + x + y*g_width);
787 /* Block is copied from nearby (above and/or to the left) within the
794 x = -(-14 + ((B - 56) % 29))
795 y = -( 8 + ((B - 56) / 29))
797 relFar(*(*pData)++, -1, &x, &y);
798 copyFrame(*pFrame, *pFrame + x + y*g_width);
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
817 relClose(*(*pData)++, &x, &y);
818 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
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
829 x = (signed char)*(*pData)++;
830 y = (signed char)*(*pData)++;
831 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
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
849 if (++*curXb == (g_width >> 3))
851 *pFrame += 7*g_width;
853 if (++*curYb == (g_height >> 3))
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:
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:
873 B0 B1 B2 B3 B4 B5 B6 B7
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.
880 So, for example, if we had:
882 11 22 fe 83 83 83 83 83 83 fe
884 This would represent the following layout:
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
895 If, on the other hand, P0 > P1, we get two more bytes from the
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.
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.
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 ;
930 patternRow2Pixels(*pFrame, *(*pData)++, p);
938 patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
939 *pFrame += 2*g_width;
940 patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
941 *pFrame += 2*g_width;
944 *pFrame -= (8*g_width - 8);
948 /* Ok, this one is basically like encoding 0x7, only more
949 complicated. Again, we start out by getting two bytes on the data
954 if P0 <= P1 then we get the following from the data stream:
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.
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.
972 For example if the next 16 bytes were:
974 00 22 f9 9f 44 55 aa 55 11 33 cc 33 66 77 01 ef
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
988 I've added a dividing line in the above to clearly delineate the
992 Now, if P0 > P1 then we get 10 more bytes from the data stream:
994 B0 B1 B2 B3 P2 P3 B4 B5 B6 B7
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.
1002 22 00 01 37 f7 31 11 66 8c e6 73 31
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
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.
1022 22 00 cc 66 33 19 66 11 18 24 42 81
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
1036 if ( (*pData)[0] <= (*pData)[1])
1038 // four quadrant case
1043 pat[0] = *(*pData)++;
1044 pat[1] = *(*pData)++;
1045 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
1047 // alternate between moving down and moving up and right
1049 *pFrame += 4 - 4*g_width; // up and right
1051 *pFrame += 4*g_width; // down
1054 else if ( (*pData)[6] <= (*pData)[7])
1064 pat[0] = *(*pData)++;
1065 pat[1] = *(*pData)++;
1066 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
1069 *pFrame -= (4*g_width - 4);
1071 *pFrame += 4*g_width;
1084 patternRow2Pixels(*pFrame, *(*pData)++, p);
1087 *pFrame -= (8*g_width - 8);
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).
1098 So, first on the data stream are our 4 pixel values:
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.
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
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).
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).
1117 if ( (*pData)[0] <= (*pData)[1])
1119 if ( (*pData)[2] <= (*pData)[3])
1128 pat[0] = *(*pData)++;
1129 pat[1] = *(*pData)++;
1130 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1134 *pFrame -= (8*g_width - 8);
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);
1155 if ( (*pData)[2] <= (*pData)[3])
1165 pat[0] = *(*pData)++;
1166 patternRow4Pixels2x1(*pFrame, pat[0], p);
1170 *pFrame -= (8*g_width - 8);
1182 pat[0] = *(*pData)++;
1183 pat[1] = *(*pData)++;
1184 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1186 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1190 *pFrame -= (8*g_width - 8);
1196 /* Similar to the previous, only a little more complicated.
1198 We are still dealing with patterns over 4 pixel values with 2 bits
1199 assigned to each pixel (or block of pixels).
1201 So, first on the data stream are our 4 pixel values:
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:
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
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.
1218 If P0 > P1 then the next data on the data stream is:
1220 B0 B1 B2 B3 B4 B5 B6 B7
1221 P4 P5 P6 P7 B8 B9 B10 B11 B12 B13 B14 B15
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.
1229 if ( (*pData)[0] <= (*pData)[1])
1237 pat[0] = *(*pData)++;
1238 pat[1] = *(*pData)++;
1239 pat[2] = *(*pData)++;
1240 pat[3] = *(*pData)++;
1242 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
1245 *pFrame -= (4*g_width - 4);
1247 *pFrame += 4*g_width;
1252 if ( (*pData)[12] <= (*pData)[13])
1265 pat[0] = *(*pData)++;
1266 pat[1] = *(*pData)++;
1267 pat[2] = *(*pData)++;
1268 pat[3] = *(*pData)++;
1270 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
1273 *pFrame -= (4*g_width - 4);
1275 *pFrame += 4*g_width;
1291 pat[0] = *(*pData)++;
1292 pat[1] = *(*pData)++;
1293 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1297 *pFrame -= (8*g_width - 8);
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
1309 memcpy(*pFrame, *pData, 8);
1314 *pFrame -= (8*g_width - 8);
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).
1328 (*pFrame)[2*k] = (*pData)[k];
1329 (*pFrame)[2*k+1] = (*pData)[k];
1336 *pFrame -= (8*g_width - 8);
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).
1350 (*pFrame)[k*g_width+j] = (*pData)[0];
1351 (*pFrame)[k*g_width+j+4] = (*pData)[1];
1354 *pFrame += 4*g_width;
1358 *pFrame -= (8*g_width - 8);
1362 /* This encoding represents a solid 8x8 frame. We get 1 byte of pixel
1363 data from the data stream.
1367 memset(*pFrame, **pData, 8);
1372 *pFrame -= (8*g_width - 8);
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
1381 P0 P1 P0 P1 P0 P1 P0 P1
1382 P1 P0 P1 P0 P1 P0 P1 P0
1384 P0 P1 P0 P1 P0 P1 P0 P1
1385 P1 P0 P1 P0 P1 P0 P1 P0
1391 (*pFrame)[j] = (*pData)[(i+j)&1];
1397 *pFrame -= (8*g_width - 8);