1 #include "mvelib.h" /* next buffer */
12 #include <SDL/SDL_thread.h>
17 #define d_malloc(a) malloc(a)
18 #define d_free(a) free(a)
22 #define MIN(a,b) ((a)<(b)?(a):(b))
26 static int doPlay(const char *filename);
28 static void usage(void)
30 fprintf(stderr, "usage: mveplay filename\n");
35 static int g_spdFactorNum=0;
36 static int g_spdFactorDenom=10;
39 int main(int c, char **v)
45 g_spdFactorNum = atoi(v[2]);
47 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
49 fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
59 static void initializeMovie(MVESTREAM *mve);
60 static void playMovie(MVESTREAM *mve);
61 static void shutdownMovie(MVESTREAM *mve);
63 void initializeMovie(MVESTREAM *mve);
64 void shutdownMovie(MVESTREAM *mve);
68 static int doPlay(const char *filename)
73 filehandle = open(filename, O_RDONLY);
77 fprintf(stderr, "can't open MVE file '%s'\n", filename);
81 mve = mve_open(filehandle);
93 static short get_short(unsigned char *data)
96 value = data[0] | (data[1] << 8);
100 static int get_int(unsigned char *data)
103 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
107 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
109 fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
113 /*************************
115 *************************/
116 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
121 /*************************
123 *************************/
128 static int micro_frame_delay=0;
130 static int timer_started=0;
131 static Uint32 timer_expire = 0;
134 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
137 micro_frame_delay = get_int(data) * (int)get_short(data+4);
138 if (g_spdFactorNum != 0)
140 temp = micro_frame_delay;
141 temp *= g_spdFactorNum;
142 temp /= g_spdFactorDenom;
143 micro_frame_delay = (int)temp;
150 static void timer_start(void)
152 timer_expire = SDL_GetTicks();
153 timer_expire += micro_frame_delay / 1000;
157 static void do_timer_wait(void)
164 if (tv > timer_expire)
167 ts = timer_expire - tv;
171 timer_expire += micro_frame_delay / 1000;
175 /*************************
177 *************************/
178 static void mve_audio_callback(void *userdata, Uint8 *stream, int len);
179 static short *mve_audio_buffers[64];
180 static int mve_audio_buflens[64];
181 static int mve_audio_curbuf_curpos=0;
182 static int mve_audio_bufhead=0;
183 static int mve_audio_buftail=0;
184 static int mve_audio_playing=0;
185 static int mve_audio_canplay=0;
186 static int mve_audio_compressed=0;
187 static SDL_AudioSpec *mve_audio_spec=NULL;
188 static SDL_mutex *mve_audio_mutex = NULL;
190 static void mve_audio_callback(void *userdata, Uint8 *stream, int len)
194 if (mve_audio_bufhead == mve_audio_buftail)
197 fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
199 SDL_mutexP(mve_audio_mutex);
201 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
202 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
204 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
205 __builtin_memcpy(stream, /* cur output position */
206 mve_audio_buffers[mve_audio_bufhead]+mve_audio_curbuf_curpos, /* cur input position */
207 length); /* cur input length */
210 stream += length; /* advance output */
211 len -= length; /* decrement avail ospace */
212 d_free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
213 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
214 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
216 if (++mve_audio_bufhead == 64) /* next buffer */
217 mve_audio_bufhead = 0;
218 mve_audio_curbuf_curpos = 0;
221 fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
224 if (len != 0 /* ospace remaining */
225 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
227 __builtin_memcpy(stream, /* dest */
228 mve_audio_buffers[mve_audio_bufhead] + mve_audio_curbuf_curpos, /* src */
231 mve_audio_curbuf_curpos += len; /* advance input */
232 stream += len; /* advance output (unnecessary) */
233 len -= len; /* advance output (unnecessary) */
235 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
237 d_free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
238 mve_audio_buffers[mve_audio_bufhead]=NULL;
239 mve_audio_buflens[mve_audio_bufhead]=0;
241 if (++mve_audio_bufhead == 64) /* next buffer */
242 mve_audio_bufhead = 0;
243 mve_audio_curbuf_curpos = 0;
247 fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
248 SDL_mutexV(mve_audio_mutex);
251 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
257 fprintf(stderr, "creating audio buffers\n");
259 mve_audio_mutex = SDL_CreateMutex();
261 flags = get_short(data + 2);
262 sample_rate = get_short(data + 4);
263 desired_buffer = get_int(data + 6);
265 fprintf(stderr, "stereo=%d 16bit=%d compressed=%d sample_rate=%d desired_buffer=%d\n",
266 flags & 1, (flags >> 1) & 1, (flags >> 2) & 1, sample_rate, desired_buffer);
268 mve_audio_compressed = (flags >> 2) & 1;
269 mve_audio_spec = (SDL_AudioSpec *)d_malloc(sizeof(SDL_AudioSpec));
270 mve_audio_spec->freq = sample_rate;
271 mve_audio_spec->format = ((flags >> 1) & 1)?AUDIO_S16LSB:AUDIO_U8;
272 mve_audio_spec->channels = (flags &1 )?2:1;
273 mve_audio_spec->samples = 32768;
274 mve_audio_spec->callback = mve_audio_callback;
275 mve_audio_spec->userdata = NULL;
276 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
278 fprintf(stderr, " success\n");
279 mve_audio_canplay = 1;
283 fprintf(stderr, " failure : %s\n", SDL_GetError());
284 mve_audio_canplay = 0;
287 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
288 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
293 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
295 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
298 mve_audio_playing = 1;
304 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
306 static const int selected_chan=1;
309 if (mve_audio_canplay)
311 if (mve_audio_playing)
314 chan = get_short(data + 2);
315 nsamp = get_short(data + 4);
316 if (chan & selected_chan)
318 SDL_mutexP(mve_audio_mutex);
319 mve_audio_buflens[mve_audio_buftail] = nsamp;
320 mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp);
322 if (mve_audio_compressed)
323 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
325 memcpy(mve_audio_buffers[mve_audio_buftail], data + 6, nsamp);
327 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
329 if (++mve_audio_buftail == 64)
330 mve_audio_buftail = 0;
332 if (mve_audio_buftail == mve_audio_bufhead)
333 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
334 SDL_mutexV(mve_audio_mutex);
337 if (mve_audio_playing)
344 /*************************
346 *************************/
347 static SDL_Surface *g_screen;
348 static int g_screenWidth, g_screenHeight;
349 static int g_width, g_height;
350 static unsigned char g_palette[768];
351 static unsigned char *g_vBackBuf1, *g_vBackBuf2;
352 static unsigned char *g_pCurMap=NULL;
353 static int g_nMapLength=0;
355 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
359 h = get_short(data+2);
362 g_vBackBuf1 = d_malloc(g_width * g_height);
363 g_vBackBuf2 = d_malloc(g_width * g_height);
364 memset(g_vBackBuf1, 0, g_width * g_height);
365 memset(g_vBackBuf2, 0, g_width * g_height);
369 //static int stupefaction=0;
370 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
373 unsigned char *pal = g_palette;
374 unsigned char *pDest;
375 unsigned char *pixels = g_vBackBuf1;
376 SDL_Surface *screenSprite;
380 SDL_Surface *initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, 8, 0, 0, 0, 0);
381 for(i = 0; i < 256; i++)
383 initSprite->format->palette->colors[i].r = (*pal++) << 2;
384 initSprite->format->palette->colors[i].g = (*pal++) << 2;
385 initSprite->format->palette->colors[i].b = (*pal++) << 2;
386 initSprite->format->palette->colors[i].unused = 0;
389 pDest = initSprite->pixels;
390 for (i=0; i<g_height; i++)
392 memcpy(pDest, pixels, g_width);
394 pDest += initSprite->pitch;
397 screenSprite = SDL_DisplayFormat(initSprite);
398 SDL_FreeSurface(initSprite);
400 if (g_screenWidth > screenSprite->w) x = (g_screenWidth - screenSprite->w) >> 1;
402 if (g_screenHeight > screenSprite->h) y = (g_screenHeight - screenSprite->h) >> 1;
406 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
407 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
408 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
409 if ( (g_screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF )
412 SDL_UpdateRects(g_screen, 1, &renderArea);
413 SDL_FreeSurface(screenSprite);
417 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
420 width = get_short(data);
421 height = get_short(data+2);
422 g_screen = SDL_SetVideoMode(width, height, 16, SDL_ANYFORMAT);
423 g_screenWidth = width;
424 g_screenHeight = height;
425 memset(g_palette, 0, 768);
429 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
432 start = get_short(data);
433 count = get_short(data+2);
434 memcpy(g_palette + 3*start, data+4, 3*count);
438 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
445 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
447 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
449 short nFrameHot, nFrameCold;
450 short nXoffset, nYoffset;
451 short nXsize, nYsize;
455 nFrameHot = get_short(data);
456 nFrameCold = get_short(data+2);
457 nXoffset = get_short(data+4);
458 nYoffset = get_short(data+6);
459 nXsize = get_short(data+8);
460 nYsize = get_short(data+10);
461 nFlags = get_short(data+12);
466 g_vBackBuf1 = g_vBackBuf2;
470 /* convert the frame */
471 decodeFrame(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
476 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
482 void initializeMovie(MVESTREAM *mve)
484 mve_set_handler(mve, 0x00, end_movie_handler);
485 mve_set_handler(mve, 0x01, end_chunk_handler);
486 mve_set_handler(mve, 0x02, create_timer_handler);
487 mve_set_handler(mve, 0x03, create_audiobuf_handler);
488 mve_set_handler(mve, 0x04, play_audio_handler);
489 mve_set_handler(mve, 0x05, create_videobuf_handler);
490 mve_set_handler(mve, 0x06, default_seg_handler);
491 mve_set_handler(mve, 0x07, display_video_handler);
492 mve_set_handler(mve, 0x08, audio_data_handler);
493 mve_set_handler(mve, 0x09, audio_data_handler);
494 mve_set_handler(mve, 0x0a, init_video_handler);
495 mve_set_handler(mve, 0x0b, default_seg_handler);
496 mve_set_handler(mve, 0x0c, video_palette_handler);
497 mve_set_handler(mve, 0x0d, default_seg_handler);
498 mve_set_handler(mve, 0x0e, default_seg_handler);
499 mve_set_handler(mve, 0x0f, video_codemap_handler);
500 mve_set_handler(mve, 0x10, default_seg_handler);
501 mve_set_handler(mve, 0x11, video_data_handler);
502 mve_set_handler(mve, 0x12, default_seg_handler);
503 //mve_set_handler(mve, 0x13, default_seg_handler);
504 mve_set_handler(mve, 0x14, default_seg_handler);
505 //mve_set_handler(mve, 0x15, default_seg_handler);
509 static void playMovie(MVESTREAM *mve)
515 cont = mve_play_next_chunk(mve);
516 if (micro_frame_delay && !init_timer)
530 void shutdownMovie(MVESTREAM *mve)
534 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
536 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
545 for (i=0; i<xb/2; i++)
547 dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
548 if (pFrame < g_vBackBuf1)
549 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
550 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
551 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
552 dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
553 if (pFrame < g_vBackBuf1)
554 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
555 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
556 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
566 static void relClose(int i, int *x, int *y)
577 static void relFar(int i, int sign, int *x, int *y)
581 *x = sign * (8 + (i % 7));
586 *x = sign * (-14 + (i - 56) % 29);
587 *y = sign * (8 + (i - 56) / 29);
591 static void copyFrame(unsigned char *pDest, unsigned char *pSrc)
597 memcpy(pDest, pSrc, 8);
603 static void patternRow4Pixels(unsigned char *pFrame,
604 unsigned char pat0, unsigned char pat1,
607 unsigned short mask=0x0003;
608 unsigned short shift=0;
609 unsigned short pattern = (pat1 << 8) | pat0;
613 *pFrame++ = p[(mask & pattern) >> shift];
619 static void patternRow4Pixels2(unsigned char *pFrame,
623 unsigned char mask=0x03;
624 unsigned char shift=0;
630 pel = p[(mask & pat0) >> shift];
633 pFrame[g_width + 0] = pel;
634 pFrame[g_width + 2] = pel;
642 static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p)
644 unsigned char mask=0x03;
645 unsigned char shift=0;
650 pel = p[(mask & pat) >> shift];
659 static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p)
661 unsigned long mask = 0x00000003UL;
664 unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
668 pFrame[i&3] = p[(pat & mask) >> shift];
679 static void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p)
681 unsigned char mask=0x01;
685 *pFrame++ = p[(mask & pat) ? 1 : 0];
690 static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p)
693 unsigned char mask=0x1;
698 pel = p[(mask & pat) ? 1 : 0];
701 pFrame[g_width + 0] = pel;
702 pFrame[g_width + 2] = pel;
709 static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p)
711 unsigned short mask = 0x0001;
713 unsigned short pat = (pat1 << 8) | pat0;
717 pFrame[i&3] = p[(pat & mask) ? 1 : 0];
726 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
729 unsigned char pat[16];
736 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
742 relFar(*(*pData)++, 1, &x, &y);
743 copyFrame(*pFrame, *pFrame + x + y*g_width);
749 relFar(*(*pData)++, -1, &x, &y);
750 copyFrame(*pFrame, *pFrame + x + y*g_width);
756 relClose(*(*pData)++, &x, &y);
757 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
763 x = (char)*(*pData)++;
764 y = (char)*(*pData)++;
765 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
774 if (++*curXb == (g_width >> 3))
776 *pFrame += 7*g_width;
778 if (++*curYb == (g_height >> 3))
791 patternRow2Pixels(*pFrame, *(*pData)++, p);
799 patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
800 *pFrame += 2*g_width;
801 patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
802 *pFrame += 2*g_width;
805 *pFrame -= (8*g_width - 8);
809 if ( (*pData)[0] <= (*pData)[1])
815 pat[0] = *(*pData)++;
816 pat[1] = *(*pData)++;
817 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
820 *pFrame -= (4*g_width - 4);
822 *pFrame += 4*g_width;
825 else if ( (*pData)[6] <= (*pData)[7])
834 pat[0] = *(*pData)++;
835 pat[1] = *(*pData)++;
836 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
839 *pFrame -= (4*g_width - 4);
841 *pFrame += 4*g_width;
853 patternRow2Pixels(*pFrame, *(*pData)++, p);
856 *pFrame -= (8*g_width - 8);
861 if ( (*pData)[0] <= (*pData)[1])
863 if ( (*pData)[2] <= (*pData)[3])
872 pat[0] = *(*pData)++;
873 pat[1] = *(*pData)++;
874 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
878 *pFrame -= (8*g_width - 8);
887 patternRow4Pixels2(*pFrame, *(*pData)++, p);
888 *pFrame += 2*g_width;
889 patternRow4Pixels2(*pFrame, *(*pData)++, p);
890 *pFrame += 2*g_width;
891 patternRow4Pixels2(*pFrame, *(*pData)++, p);
892 *pFrame += 2*g_width;
893 patternRow4Pixels2(*pFrame, *(*pData)++, p);
894 *pFrame -= (6*g_width - 8);
899 if ( (*pData)[2] <= (*pData)[3])
908 pat[0] = *(*pData)++;
909 patternRow4Pixels2x1(*pFrame, pat[0], p);
913 *pFrame -= (8*g_width - 8);
924 pat[0] = *(*pData)++;
925 pat[1] = *(*pData)++;
926 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
928 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
932 *pFrame -= (8*g_width - 8);
938 if ( (*pData)[0] <= (*pData)[1])
946 pat[0] = *(*pData)++;
947 pat[1] = *(*pData)++;
948 pat[2] = *(*pData)++;
949 pat[3] = *(*pData)++;
951 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
954 *pFrame -= (4*g_width - 4);
956 *pFrame += 4*g_width;
961 if ( (*pData)[12] <= (*pData)[13])
973 pat[0] = *(*pData)++;
974 pat[1] = *(*pData)++;
975 pat[2] = *(*pData)++;
976 pat[3] = *(*pData)++;
978 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
981 *pFrame -= (4*g_width - 4);
983 *pFrame += 4*g_width;
998 pat[0] = *(*pData)++;
999 pat[1] = *(*pData)++;
1000 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
1004 *pFrame -= (8*g_width - 8);
1012 memcpy(*pFrame, *pData, 8);
1017 *pFrame -= (8*g_width - 8);
1027 (*pFrame)[j+2*k] = (*pData)[k];
1028 (*pFrame)[g_width+j+2*k] = (*pData)[k];
1035 *pFrame -= (8*g_width - 8);
1045 (*pFrame)[k*g_width+j] = (*pData)[0];
1046 (*pFrame)[k*g_width+j+4] = (*pData)[1];
1049 *pFrame += 4*g_width;
1053 *pFrame -= (8*g_width - 8);
1059 memset(*pFrame, **pData, 8);
1064 *pFrame -= (8*g_width - 8);
1072 (*pFrame)[j] = (*pData)[(i+j)&1];
1078 *pFrame -= (8*g_width - 8);