1 #include "mvelib.h" /* next buffer */
9 #include <SDL/SDL_thread.h>
12 #define MIN(a,b) ((a)<(b)?(a):(b))
15 int doPlay(const char *filename);
19 fprintf(stderr, "usage: mveplay filename\n");
24 int g_spdFactorDenom=10;
26 void initializeMovie(MVESTREAM *mve);
27 void playMovie(MVESTREAM *mve);
28 void shutdownMovie(MVESTREAM *mve);
30 short get_short(unsigned char *data)
33 value = data[0] | (data[1] << 8);
37 int get_int(unsigned char *data)
40 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
44 int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
46 fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
50 /*************************
52 *************************/
53 int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
58 /*************************
60 *************************/
65 int micro_frame_delay=0;
67 Uint32 timer_expire = 0;
69 int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
72 micro_frame_delay = get_int(data) * (int)get_short(data+4);
73 if (g_spdFactorNum != 0)
75 temp = micro_frame_delay;
76 temp *= g_spdFactorNum;
77 temp /= g_spdFactorDenom;
78 micro_frame_delay = (int)temp;
84 void timer_start(void)
86 timer_expire = SDL_GetTicks();
87 timer_expire += micro_frame_delay / 1000;
91 void do_timer_wait(void)
98 if (tv > timer_expire)
101 ts = timer_expire - tv;
105 timer_expire += micro_frame_delay / 1000;
108 /*************************
110 *************************/
111 void mve_audio_callback(void *userdata, Uint8 *stream, int len);
112 short *mve_audio_buffers[64];
113 int mve_audio_buflens[64];
114 int mve_audio_curbuf_curpos=0;
115 int mve_audio_bufhead=0;
116 int mve_audio_buftail=0;
117 int mve_audio_playing=0;
118 int mve_audio_canplay=0;
119 SDL_AudioSpec *mve_audio_spec=NULL;
120 SDL_mutex *mve_audio_mutex=NULL;
122 void mve_audio_callback(void *userdata, Uint8 *stream, int len)
126 if (mve_audio_bufhead == mve_audio_buftail)
129 fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
131 if (!mve_audio_mutex) {
132 fprintf(stderr, "mve_audio_callback: creating mutex");
133 mve_audio_mutex = SDL_CreateMutex();
135 SDL_mutexP(mve_audio_mutex);
137 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
138 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
140 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
141 __builtin_memcpy(stream, /* cur output position */
142 mve_audio_buffers[mve_audio_bufhead]+mve_audio_curbuf_curpos, /* cur input position */
143 length); /* cur input length */
146 stream += length; /* advance output */
147 len -= length; /* decrement avail ospace */
148 free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
149 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
150 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
152 if (++mve_audio_bufhead == 64) /* next buffer */
153 mve_audio_bufhead = 0;
154 mve_audio_curbuf_curpos = 0;
157 fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
160 if (len != 0 /* ospace remaining */
161 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
163 __builtin_memcpy(stream, /* dest */
164 mve_audio_buffers[mve_audio_bufhead] + mve_audio_curbuf_curpos, /* src */
167 mve_audio_curbuf_curpos += len; /* advance input */
168 stream += len; /* advance output (unnecessary) */
169 len -= len; /* advance output (unnecessary) */
171 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
173 free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
174 mve_audio_buffers[mve_audio_bufhead]=NULL;
175 mve_audio_buflens[mve_audio_bufhead]=0;
177 if (++mve_audio_bufhead == 64) /* next buffer */
178 mve_audio_bufhead = 0;
179 mve_audio_curbuf_curpos = 0;
183 fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
184 SDL_mutexV(mve_audio_mutex);
187 int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
192 fprintf(stderr, "creating audio buffers\n");
194 sample_rate = get_short(data + 4);
195 desired_buffer = get_int(data + 6);
196 mve_audio_spec = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
197 mve_audio_spec->freq = sample_rate;
198 mve_audio_spec->format = AUDIO_S16LSB;
199 mve_audio_spec->channels = 2;
200 mve_audio_spec->samples = 32768;
201 mve_audio_spec->callback = mve_audio_callback;
202 mve_audio_spec->userdata = NULL;
203 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
205 fprintf(stderr, " success\n");
206 mve_audio_canplay = 1;
210 fprintf(stderr, " failure : %s\n", SDL_GetError());
211 mve_audio_canplay = 0;
214 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
215 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
220 int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
222 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
225 mve_audio_playing = 1;
231 int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
233 const int selected_chan=1;
236 if (mve_audio_canplay)
238 if (mve_audio_playing)
241 chan = get_short(data + 2);
242 nsamp = get_short(data + 4);
243 if (chan & selected_chan)
245 if (!mve_audio_mutex) {
246 fprintf(stderr, "audio_data_handler: creating mutex");
247 mve_audio_mutex = SDL_CreateMutex();
249 SDL_mutexP(mve_audio_mutex);
250 mve_audio_buflens[mve_audio_buftail] = nsamp;
251 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
253 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
255 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
257 if (++mve_audio_buftail == 64)
258 mve_audio_buftail = 0;
260 if (mve_audio_buftail == mve_audio_bufhead)
261 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
262 SDL_mutexV(mve_audio_mutex);
265 if (mve_audio_playing)
272 /*************************
274 *************************/
275 SDL_Surface *g_screen;
276 int g_screenWidth, g_screenHeight;
277 int g_width, g_height;
278 unsigned char g_palette[768];
279 unsigned char *g_vBackBuf1, *g_vBackBuf2;
280 unsigned char *g_pCurMap=NULL;
283 int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
287 h = get_short(data+2);
290 g_vBackBuf1 = malloc(g_width * g_height);
291 g_vBackBuf2 = malloc(g_width * g_height);
292 memset(g_vBackBuf1, 0, g_width * g_height);
293 memset(g_vBackBuf2, 0, g_width * g_height);
298 int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
301 unsigned char *pal = g_palette;
302 unsigned char *pDest;
303 unsigned char *pixels = g_vBackBuf1;
304 SDL_Surface *screenSprite;
308 SDL_Surface *initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, 8, 0, 0, 0, 0);
309 for(i = 0; i < 256; i++)
311 initSprite->format->palette->colors[i].r = (*pal++) << 2;
312 initSprite->format->palette->colors[i].g = (*pal++) << 2;
313 initSprite->format->palette->colors[i].b = (*pal++) << 2;
314 initSprite->format->palette->colors[i].unused = 0;
317 pDest = initSprite->pixels;
318 for (i=0; i<g_height; i++)
320 memcpy(pDest, pixels, g_width);
322 pDest += initSprite->pitch;
325 screenSprite = SDL_DisplayFormat(initSprite);
326 SDL_FreeSurface(initSprite);
328 if (g_screenWidth > screenSprite->w) x = (g_screenWidth - screenSprite->w) >> 1;
330 if (g_screenHeight > screenSprite->h) y = (g_screenHeight - screenSprite->h) >> 1;
334 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
335 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
336 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
337 if ( (g_screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF )
340 SDL_UpdateRects(g_screen, 1, &renderArea);
341 SDL_FreeSurface(screenSprite);
345 int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
348 width = get_short(data);
349 height = get_short(data+2);
350 g_screen = SDL_SetVideoMode(width, height, 16, SDL_ANYFORMAT);
351 g_screenWidth = width;
352 g_screenHeight = height;
353 memset(g_palette, 0, 768);
357 int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
360 start = get_short(data);
361 count = get_short(data+2);
362 memcpy(g_palette + 3*start, data+4, 3*count);
366 int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
373 void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
375 int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
377 short nFrameHot, nFrameCold;
378 short nXoffset, nYoffset;
379 short nXsize, nYsize;
383 nFrameHot = get_short(data);
384 nFrameCold = get_short(data+2);
385 nXoffset = get_short(data+4);
386 nYoffset = get_short(data+6);
387 nXsize = get_short(data+8);
388 nYsize = get_short(data+10);
389 nFlags = get_short(data+12);
394 g_vBackBuf1 = g_vBackBuf2;
398 /* convert the frame */
399 decodeFrame(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
404 int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
410 void initializeMovie(MVESTREAM *mve)
412 mve_set_handler(mve, 0x00, end_movie_handler);
413 mve_set_handler(mve, 0x01, end_chunk_handler);
414 mve_set_handler(mve, 0x02, create_timer_handler);
415 mve_set_handler(mve, 0x03, create_audiobuf_handler);
416 mve_set_handler(mve, 0x04, play_audio_handler);
417 mve_set_handler(mve, 0x05, create_videobuf_handler);
418 mve_set_handler(mve, 0x07, display_video_handler);
419 mve_set_handler(mve, 0x08, audio_data_handler);
420 mve_set_handler(mve, 0x09, audio_data_handler);
421 mve_set_handler(mve, 0x0a, init_video_handler);
422 mve_set_handler(mve, 0x0c, video_palette_handler);
423 mve_set_handler(mve, 0x0f, video_codemap_handler);
424 mve_set_handler(mve, 0x11, video_data_handler);
427 void playMovie(MVESTREAM *mve)
433 cont = mve_play_next_chunk(mve);
434 if (micro_frame_delay && !init_timer)
444 void shutdownMovie(MVESTREAM *mve)
448 void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
450 void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
459 for (i=0; i<xb/2; i++)
461 dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
462 if (pFrame < g_vBackBuf1)
463 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
464 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
465 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
466 dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
467 if (pFrame < g_vBackBuf1)
468 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
469 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
470 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
480 void relClose(int i, int *x, int *y)
491 void relFar(int i, int sign, int *x, int *y)
495 *x = sign * (8 + (i % 7));
500 *x = sign * (-14 + (i - 56) % 29);
501 *y = sign * (8 + (i - 56) / 29);
505 void copyFrame(unsigned char *pDest, unsigned char *pSrc)
511 memcpy(pDest, pSrc, 8);
517 void patternRow4Pixels(unsigned char *pFrame,
518 unsigned char pat0, unsigned char pat1,
521 unsigned short mask=0x0003;
522 unsigned short shift=0;
523 unsigned short pattern = (pat1 << 8) | pat0;
527 *pFrame++ = p[(mask & pattern) >> shift];
533 void patternRow4Pixels2(unsigned char *pFrame,
537 unsigned char mask=0x03;
538 unsigned char shift=0;
544 pel = p[(mask & pat0) >> shift];
547 pFrame[g_width + 0] = pel;
548 pFrame[g_width + 2] = pel;
556 void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p)
558 unsigned char mask=0x03;
559 unsigned char shift=0;
564 pel = p[(mask & pat) >> shift];
573 void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p)
575 unsigned long mask = 0x00000003UL;
578 unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
582 pFrame[i&3] = p[(pat & mask) >> shift];
593 void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p)
595 unsigned char mask=0x01;
599 *pFrame++ = p[(mask & pat) ? 1 : 0];
604 void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p)
607 unsigned char mask=0x1;
612 pel = p[(mask & pat) ? 1 : 0];
615 pFrame[g_width + 0] = pel;
616 pFrame[g_width + 2] = pel;
623 void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p)
625 unsigned short mask = 0x0001;
627 unsigned short pat = (pat1 << 8) | pat0;
631 pFrame[i&3] = p[(pat & mask) ? 1 : 0];
640 void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
643 unsigned char pat[16];
650 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
656 relFar(*(*pData)++, 1, &x, &y);
657 copyFrame(*pFrame, *pFrame + x + y*g_width);
663 relFar(*(*pData)++, -1, &x, &y);
664 copyFrame(*pFrame, *pFrame + x + y*g_width);
670 relClose(*(*pData)++, &x, &y);
671 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
677 x = (char)*(*pData)++;
678 y = (char)*(*pData)++;
679 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
688 if (++*curXb == (g_width >> 3))
690 *pFrame += 7*g_width;
692 if (++*curYb == (g_height >> 3))
705 patternRow2Pixels(*pFrame, *(*pData)++, p);
713 patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
714 *pFrame += 2*g_width;
715 patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
716 *pFrame += 2*g_width;
719 *pFrame -= (8*g_width - 8);
723 if ( (*pData)[0] <= (*pData)[1])
729 pat[0] = *(*pData)++;
730 pat[1] = *(*pData)++;
731 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
734 *pFrame -= (4*g_width - 4);
736 *pFrame += 4*g_width;
739 else if ( (*pData)[6] <= (*pData)[7])
748 pat[0] = *(*pData)++;
749 pat[1] = *(*pData)++;
750 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
753 *pFrame -= (4*g_width - 4);
755 *pFrame += 4*g_width;
767 patternRow2Pixels(*pFrame, *(*pData)++, p);
770 *pFrame -= (8*g_width - 8);
775 if ( (*pData)[0] <= (*pData)[1])
777 if ( (*pData)[2] <= (*pData)[3])
786 pat[0] = *(*pData)++;
787 pat[1] = *(*pData)++;
788 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
792 *pFrame -= (8*g_width - 8);
801 patternRow4Pixels2(*pFrame, *(*pData)++, p);
802 *pFrame += 2*g_width;
803 patternRow4Pixels2(*pFrame, *(*pData)++, p);
804 *pFrame += 2*g_width;
805 patternRow4Pixels2(*pFrame, *(*pData)++, p);
806 *pFrame += 2*g_width;
807 patternRow4Pixels2(*pFrame, *(*pData)++, p);
808 *pFrame -= (6*g_width - 8);
813 if ( (*pData)[2] <= (*pData)[3])
822 pat[0] = *(*pData)++;
823 patternRow4Pixels2x1(*pFrame, pat[0], p);
827 *pFrame -= (8*g_width - 8);
838 pat[0] = *(*pData)++;
839 pat[1] = *(*pData)++;
840 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
842 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
846 *pFrame -= (8*g_width - 8);
852 if ( (*pData)[0] <= (*pData)[1])
860 pat[0] = *(*pData)++;
861 pat[1] = *(*pData)++;
862 pat[2] = *(*pData)++;
863 pat[3] = *(*pData)++;
865 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
868 *pFrame -= (4*g_width - 4);
870 *pFrame += 4*g_width;
875 if ( (*pData)[12] <= (*pData)[13])
887 pat[0] = *(*pData)++;
888 pat[1] = *(*pData)++;
889 pat[2] = *(*pData)++;
890 pat[3] = *(*pData)++;
892 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
895 *pFrame -= (4*g_width - 4);
897 *pFrame += 4*g_width;
912 pat[0] = *(*pData)++;
913 pat[1] = *(*pData)++;
914 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
918 *pFrame -= (8*g_width - 8);
926 memcpy(*pFrame, *pData, 8);
931 *pFrame -= (8*g_width - 8);
941 (*pFrame)[j+2*k] = (*pData)[k];
942 (*pFrame)[g_width+j+2*k] = (*pData)[k];
949 *pFrame -= (8*g_width - 8);
959 (*pFrame)[k*g_width+j] = (*pData)[0];
960 (*pFrame)[k*g_width+j+4] = (*pData)[1];
963 *pFrame += 4*g_width;
967 *pFrame -= (8*g_width - 8);
973 memset(*pFrame, **pData, 8);
978 *pFrame -= (8*g_width - 8);
986 (*pFrame)[j] = (*pData)[(i+j)&1];
992 *pFrame -= (8*g_width - 8);