5 #include "mvelib.h" /* next buffer */
12 #include <sys/types.h>
16 #include <SDL/SDL_thread.h>
21 #define d_malloc(a) malloc(a)
22 #define d_free(a) free(a)
26 #define MIN(a,b) ((a)<(b)?(a):(b))
30 static int doPlay(const char *filename);
32 static void usage(void)
34 fprintf(stderr, "usage: mveplay filename\n");
39 static int g_spdFactorNum=0;
40 static int g_spdFactorDenom=10;
43 int main(int c, char **v)
49 g_spdFactorNum = atoi(v[2]);
51 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
53 fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
63 static void initializeMovie(MVESTREAM *mve);
64 static void playMovie(MVESTREAM *mve);
65 static void shutdownMovie(MVESTREAM *mve);
67 void initializeMovie(MVESTREAM *mve);
68 void shutdownMovie(MVESTREAM *mve);
72 static int doPlay(const char *filename)
77 filehandle = open(filename, O_RDONLY);
81 fprintf(stderr, "can't open MVE file '%s'\n", filename);
85 mve = mve_open(filehandle);
97 static short get_short(unsigned char *data)
100 value = data[0] | (data[1] << 8);
104 static int get_int(unsigned char *data)
107 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
111 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
113 fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
117 /*************************
119 *************************/
120 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
125 /*************************
127 *************************/
132 static int micro_frame_delay=0;
134 static int timer_started=0;
135 static Uint32 timer_expire = 0;
138 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
141 micro_frame_delay = get_int(data) * (int)get_short(data+4);
142 if (g_spdFactorNum != 0)
144 temp = micro_frame_delay;
145 temp *= g_spdFactorNum;
146 temp /= g_spdFactorDenom;
147 micro_frame_delay = (int)temp;
154 static void timer_start(void)
156 timer_expire = SDL_GetTicks();
157 timer_expire += micro_frame_delay / 1000;
161 static void do_timer_wait(void)
168 if (tv > timer_expire)
171 ts = timer_expire - tv;
175 timer_expire += micro_frame_delay / 1000;
179 /*************************
181 *************************/
182 static void mve_audio_callback(void *userdata, Uint8 *stream, int len);
183 static short *mve_audio_buffers[64];
184 static int mve_audio_buflens[64];
185 static int mve_audio_curbuf_curpos=0;
186 static int mve_audio_bufhead=0;
187 static int mve_audio_buftail=0;
188 static int mve_audio_playing=0;
189 static int mve_audio_canplay=0;
190 static int mve_audio_compressed=0;
191 static SDL_AudioSpec *mve_audio_spec=NULL;
192 static SDL_mutex *mve_audio_mutex = NULL;
194 static void mve_audio_callback(void *userdata, Uint8 *stream, int len)
198 if (mve_audio_bufhead == mve_audio_buftail)
201 fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
203 SDL_mutexP(mve_audio_mutex);
205 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
206 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
208 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
209 __builtin_memcpy(stream, /* cur output position */
210 mve_audio_buffers[mve_audio_bufhead]+mve_audio_curbuf_curpos, /* cur input position */
211 length); /* cur input length */
214 stream += length; /* advance output */
215 len -= length; /* decrement avail ospace */
216 d_free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
217 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
218 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
220 if (++mve_audio_bufhead == 64) /* next buffer */
221 mve_audio_bufhead = 0;
222 mve_audio_curbuf_curpos = 0;
225 fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
228 if (len != 0 /* ospace remaining */
229 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
231 __builtin_memcpy(stream, /* dest */
232 mve_audio_buffers[mve_audio_bufhead] + mve_audio_curbuf_curpos, /* src */
235 mve_audio_curbuf_curpos += len; /* advance input */
236 stream += len; /* advance output (unnecessary) */
237 len -= len; /* advance output (unnecessary) */
239 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
241 d_free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
242 mve_audio_buffers[mve_audio_bufhead]=NULL;
243 mve_audio_buflens[mve_audio_bufhead]=0;
245 if (++mve_audio_bufhead == 64) /* next buffer */
246 mve_audio_bufhead = 0;
247 mve_audio_curbuf_curpos = 0;
251 fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
252 SDL_mutexV(mve_audio_mutex);
255 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
261 fprintf(stderr, "creating audio buffers\n");
263 mve_audio_mutex = SDL_CreateMutex();
265 flags = get_short(data + 2);
266 sample_rate = get_short(data + 4);
267 desired_buffer = get_int(data + 6);
269 fprintf(stderr, "stereo=%d 16bit=%d compressed=%d sample_rate=%d desired_buffer=%d\n",
270 flags & 1, (flags >> 1) & 1, (flags >> 2) & 1, sample_rate, desired_buffer);
272 mve_audio_compressed = (flags >> 2) & 1;
273 mve_audio_spec = (SDL_AudioSpec *)d_malloc(sizeof(SDL_AudioSpec));
274 mve_audio_spec->freq = sample_rate;
275 #ifdef WORDS_BIGENDIAN
276 mve_audio_spec->format = ((flags >> 1) & 1)?AUDIO_S16MSB:AUDIO_U8;
278 mve_audio_spec->format = ((flags >> 1) & 1)?AUDIO_S16LSB:AUDIO_U8;
280 mve_audio_spec->channels = (flags &1 )?2:1;
281 mve_audio_spec->samples = 32768;
282 mve_audio_spec->callback = mve_audio_callback;
283 mve_audio_spec->userdata = NULL;
284 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
286 fprintf(stderr, " success\n");
287 mve_audio_canplay = 1;
291 fprintf(stderr, " failure : %s\n", SDL_GetError());
292 mve_audio_canplay = 0;
295 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
296 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
301 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
303 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
306 mve_audio_playing = 1;
312 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
314 static const int selected_chan=1;
317 if (mve_audio_canplay)
319 if (mve_audio_playing)
322 chan = get_short(data + 2);
323 nsamp = get_short(data + 4);
324 if (chan & selected_chan)
326 SDL_mutexP(mve_audio_mutex);
327 mve_audio_buflens[mve_audio_buftail] = nsamp;
328 mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp);
330 if (mve_audio_compressed)
331 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
333 memcpy(mve_audio_buffers[mve_audio_buftail], data + 6, nsamp);
335 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
337 if (++mve_audio_buftail == 64)
338 mve_audio_buftail = 0;
340 if (mve_audio_buftail == mve_audio_bufhead)
341 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
342 SDL_mutexV(mve_audio_mutex);
345 if (mve_audio_playing)
352 /*************************
354 *************************/
355 static SDL_Surface *g_screen;
356 static int g_screenWidth, g_screenHeight;
357 static int g_width, g_height;
358 static unsigned char g_palette[768];
359 static unsigned char *g_vBackBuf1, *g_vBackBuf2;
360 static unsigned char *g_pCurMap=NULL;
361 static int g_nMapLength=0;
363 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
367 h = get_short(data+2);
370 g_vBackBuf1 = d_malloc(g_width * g_height);
371 g_vBackBuf2 = d_malloc(g_width * g_height);
372 memset(g_vBackBuf1, 0, g_width * g_height);
373 memset(g_vBackBuf2, 0, g_width * g_height);
377 //static int stupefaction=0;
378 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
381 unsigned char *pal = g_palette;
382 unsigned char *pDest;
383 unsigned char *pixels = g_vBackBuf1;
384 SDL_Surface *screenSprite;
388 SDL_Surface *initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, 8, 0, 0, 0, 0);
389 for(i = 0; i < 256; i++)
391 initSprite->format->palette->colors[i].r = (*pal++) << 2;
392 initSprite->format->palette->colors[i].g = (*pal++) << 2;
393 initSprite->format->palette->colors[i].b = (*pal++) << 2;
394 initSprite->format->palette->colors[i].unused = 0;
397 pDest = initSprite->pixels;
398 for (i=0; i<g_height; i++)
400 memcpy(pDest, pixels, g_width);
402 pDest += initSprite->pitch;
405 screenSprite = SDL_DisplayFormat(initSprite);
406 SDL_FreeSurface(initSprite);
408 if (g_screenWidth > screenSprite->w) x = (g_screenWidth - screenSprite->w) >> 1;
410 if (g_screenHeight > screenSprite->h) y = (g_screenHeight - screenSprite->h) >> 1;
414 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
415 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
416 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
417 if ( (g_screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF )
420 SDL_UpdateRects(g_screen, 1, &renderArea);
421 SDL_FreeSurface(screenSprite);
425 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
428 width = get_short(data);
429 height = get_short(data+2);
430 g_screen = SDL_SetVideoMode(width, height, 16, SDL_ANYFORMAT);
431 g_screenWidth = width;
432 g_screenHeight = height;
433 memset(g_palette, 0, 768);
437 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
440 start = get_short(data);
441 count = get_short(data+2);
442 memcpy(g_palette + 3*start, data+4, 3*count);
446 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
453 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
455 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
457 short nFrameHot, nFrameCold;
458 short nXoffset, nYoffset;
459 short nXsize, nYsize;
463 nFrameHot = get_short(data);
464 nFrameCold = get_short(data+2);
465 nXoffset = get_short(data+4);
466 nYoffset = get_short(data+6);
467 nXsize = get_short(data+8);
468 nYsize = get_short(data+10);
469 nFlags = get_short(data+12);
474 g_vBackBuf1 = g_vBackBuf2;
478 /* convert the frame */
479 decodeFrame(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
484 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
490 void initializeMovie(MVESTREAM *mve)
492 mve_set_handler(mve, 0x00, end_movie_handler);
493 mve_set_handler(mve, 0x01, end_chunk_handler);
494 mve_set_handler(mve, 0x02, create_timer_handler);
495 mve_set_handler(mve, 0x03, create_audiobuf_handler);
496 mve_set_handler(mve, 0x04, play_audio_handler);
497 mve_set_handler(mve, 0x05, create_videobuf_handler);
498 mve_set_handler(mve, 0x06, default_seg_handler);
499 mve_set_handler(mve, 0x07, display_video_handler);
500 mve_set_handler(mve, 0x08, audio_data_handler);
501 mve_set_handler(mve, 0x09, audio_data_handler);
502 mve_set_handler(mve, 0x0a, init_video_handler);
503 mve_set_handler(mve, 0x0b, default_seg_handler);
504 mve_set_handler(mve, 0x0c, video_palette_handler);
505 mve_set_handler(mve, 0x0d, default_seg_handler);
506 mve_set_handler(mve, 0x0e, default_seg_handler);
507 mve_set_handler(mve, 0x0f, video_codemap_handler);
508 mve_set_handler(mve, 0x10, default_seg_handler);
509 mve_set_handler(mve, 0x11, video_data_handler);
510 mve_set_handler(mve, 0x12, default_seg_handler);
511 //mve_set_handler(mve, 0x13, default_seg_handler);
512 mve_set_handler(mve, 0x14, default_seg_handler);
513 //mve_set_handler(mve, 0x15, default_seg_handler);
517 static void playMovie(MVESTREAM *mve)
523 cont = mve_play_next_chunk(mve);
524 if (micro_frame_delay && !init_timer)
538 void shutdownMovie(MVESTREAM *mve)
542 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
544 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
553 for (i=0; i<xb/2; i++)
555 dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
556 if (pFrame < g_vBackBuf1)
557 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
558 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
559 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
560 dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
561 if (pFrame < g_vBackBuf1)
562 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
563 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
564 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
574 static void relClose(int i, int *x, int *y)
585 static void relFar(int i, int sign, int *x, int *y)
589 *x = sign * (8 + (i % 7));
594 *x = sign * (-14 + (i - 56) % 29);
595 *y = sign * (8 + (i - 56) / 29);
599 static void copyFrame(unsigned char *pDest, unsigned char *pSrc)
605 memcpy(pDest, pSrc, 8);
611 static void patternRow4Pixels(unsigned char *pFrame,
612 unsigned char pat0, unsigned char pat1,
615 unsigned short mask=0x0003;
616 unsigned short shift=0;
617 unsigned short pattern = (pat1 << 8) | pat0;
621 *pFrame++ = p[(mask & pattern) >> shift];
627 static void patternRow4Pixels2(unsigned char *pFrame,
631 unsigned char mask=0x03;
632 unsigned char shift=0;
638 pel = p[(mask & pat0) >> shift];
641 pFrame[g_width + 0] = pel;
642 pFrame[g_width + 2] = pel;
650 static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p)
652 unsigned char mask=0x03;
653 unsigned char shift=0;
658 pel = p[(mask & pat) >> shift];
667 static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p)
669 unsigned long mask = 0x00000003UL;
672 unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
676 pFrame[i&3] = p[(pat & mask) >> shift];
687 static void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p)
689 unsigned char mask=0x01;
693 *pFrame++ = p[(mask & pat) ? 1 : 0];
698 static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p)
701 unsigned char mask=0x1;
706 pel = p[(mask & pat) ? 1 : 0];
709 pFrame[g_width + 0] = pel;
710 pFrame[g_width + 2] = pel;
717 static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p)
719 unsigned short mask = 0x0001;
721 unsigned short pat = (pat1 << 8) | pat0;
725 pFrame[i&3] = p[(pat & mask) ? 1 : 0];
734 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
737 unsigned char pat[16];
744 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
750 relFar(*(*pData)++, 1, &x, &y);
751 copyFrame(*pFrame, *pFrame + x + y*g_width);
757 relFar(*(*pData)++, -1, &x, &y);
758 copyFrame(*pFrame, *pFrame + x + y*g_width);
764 relClose(*(*pData)++, &x, &y);
765 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
771 x = (char)*(*pData)++;
772 y = (char)*(*pData)++;
773 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
782 if (++*curXb == (g_width >> 3))
784 *pFrame += 7*g_width;
786 if (++*curYb == (g_height >> 3))
799 patternRow2Pixels(*pFrame, *(*pData)++, p);
807 patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
808 *pFrame += 2*g_width;
809 patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
810 *pFrame += 2*g_width;
813 *pFrame -= (8*g_width - 8);
817 if ( (*pData)[0] <= (*pData)[1])
823 pat[0] = *(*pData)++;
824 pat[1] = *(*pData)++;
825 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
828 *pFrame -= (4*g_width - 4);
830 *pFrame += 4*g_width;
833 else if ( (*pData)[6] <= (*pData)[7])
842 pat[0] = *(*pData)++;
843 pat[1] = *(*pData)++;
844 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
847 *pFrame -= (4*g_width - 4);
849 *pFrame += 4*g_width;
861 patternRow2Pixels(*pFrame, *(*pData)++, p);
864 *pFrame -= (8*g_width - 8);
869 if ( (*pData)[0] <= (*pData)[1])
871 if ( (*pData)[2] <= (*pData)[3])
880 pat[0] = *(*pData)++;
881 pat[1] = *(*pData)++;
882 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
886 *pFrame -= (8*g_width - 8);
895 patternRow4Pixels2(*pFrame, *(*pData)++, p);
896 *pFrame += 2*g_width;
897 patternRow4Pixels2(*pFrame, *(*pData)++, p);
898 *pFrame += 2*g_width;
899 patternRow4Pixels2(*pFrame, *(*pData)++, p);
900 *pFrame += 2*g_width;
901 patternRow4Pixels2(*pFrame, *(*pData)++, p);
902 *pFrame -= (6*g_width - 8);
907 if ( (*pData)[2] <= (*pData)[3])
916 pat[0] = *(*pData)++;
917 patternRow4Pixels2x1(*pFrame, pat[0], p);
921 *pFrame -= (8*g_width - 8);
932 pat[0] = *(*pData)++;
933 pat[1] = *(*pData)++;
934 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
936 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
940 *pFrame -= (8*g_width - 8);
946 if ( (*pData)[0] <= (*pData)[1])
954 pat[0] = *(*pData)++;
955 pat[1] = *(*pData)++;
956 pat[2] = *(*pData)++;
957 pat[3] = *(*pData)++;
959 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
962 *pFrame -= (4*g_width - 4);
964 *pFrame += 4*g_width;
969 if ( (*pData)[12] <= (*pData)[13])
981 pat[0] = *(*pData)++;
982 pat[1] = *(*pData)++;
983 pat[2] = *(*pData)++;
984 pat[3] = *(*pData)++;
986 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
989 *pFrame -= (4*g_width - 4);
991 *pFrame += 4*g_width;
1006 pat[0] = *(*pData)++;
1007 pat[1] = *(*pData)++;
1008 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1012 *pFrame -= (8*g_width - 8);
1020 memcpy(*pFrame, *pData, 8);
1025 *pFrame -= (8*g_width - 8);
1035 (*pFrame)[j+2*k] = (*pData)[k];
1036 (*pFrame)[g_width+j+2*k] = (*pData)[k];
1043 *pFrame -= (8*g_width - 8);
1053 (*pFrame)[k*g_width+j] = (*pData)[0];
1054 (*pFrame)[k*g_width+j+4] = (*pData)[1];
1057 *pFrame += 4*g_width;
1061 *pFrame -= (8*g_width - 8);
1067 memset(*pFrame, **pData, 8);
1072 *pFrame -= (8*g_width - 8);
1080 (*pFrame)[j] = (*pData)[(i+j)&1];
1086 *pFrame -= (8*g_width - 8);