1 #include "mvelib.h" /* next buffer */
12 #include <SDL/SDL_thread.h>
15 #define MIN(a,b) ((a)<(b)?(a):(b))
19 static int doPlay(const char *filename);
21 static void usage(void)
23 fprintf(stderr, "usage: mveplay filename\n");
28 static int g_spdFactorNum=0;
29 static int g_spdFactorDenom=10;
32 int main(int c, char **v)
38 g_spdFactorNum = atoi(v[2]);
40 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
42 fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
52 static void initializeMovie(MVESTREAM *mve);
53 static void playMovie(MVESTREAM *mve);
54 static void shutdownMovie(MVESTREAM *mve);
56 void initializeMovie(MVESTREAM *mve);
57 void shutdownMovie(MVESTREAM *mve);
61 static int doPlay(const char *filename)
66 filehandle = open(filename, O_RDONLY);
70 fprintf(stderr, "can't open MVE file '%s'\n", filename);
74 mve = mve_open(filehandle);
86 static short get_short(unsigned char *data)
89 value = data[0] | (data[1] << 8);
93 static int get_int(unsigned char *data)
96 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
100 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
102 fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
106 /*************************
108 *************************/
109 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
114 /*************************
116 *************************/
121 static int micro_frame_delay=0;
123 static int timer_started=0;
124 static Uint32 timer_expire = 0;
127 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
130 micro_frame_delay = get_int(data) * (int)get_short(data+4);
131 if (g_spdFactorNum != 0)
133 temp = micro_frame_delay;
134 temp *= g_spdFactorNum;
135 temp /= g_spdFactorDenom;
136 micro_frame_delay = (int)temp;
143 static void timer_start(void)
145 timer_expire = SDL_GetTicks();
146 timer_expire += micro_frame_delay / 1000;
150 static void do_timer_wait(void)
157 if (tv > timer_expire)
160 ts = timer_expire - tv;
164 timer_expire += micro_frame_delay / 1000;
168 /*************************
170 *************************/
171 static void mve_audio_callback(void *userdata, Uint8 *stream, int len);
172 static short *mve_audio_buffers[64];
173 static int mve_audio_buflens[64];
174 static int mve_audio_curbuf_curpos=0;
175 static int mve_audio_bufhead=0;
176 static int mve_audio_buftail=0;
177 static int mve_audio_playing=0;
178 static int mve_audio_canplay=0;
179 static SDL_AudioSpec *mve_audio_spec=NULL;
180 static SDL_mutex *mve_audio_mutex = NULL;
182 static void mve_audio_callback(void *userdata, Uint8 *stream, int len)
186 if (mve_audio_bufhead == mve_audio_buftail)
189 fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
191 if (!mve_audio_mutex) {
192 fprintf(stderr, "mve_audio_callback: creating mutex");
193 mve_audio_mutex = SDL_CreateMutex();
195 SDL_mutexP(mve_audio_mutex);
197 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
198 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
200 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
201 __builtin_memcpy(stream, /* cur output position */
202 mve_audio_buffers[mve_audio_bufhead]+mve_audio_curbuf_curpos, /* cur input position */
203 length); /* cur input length */
206 stream += length; /* advance output */
207 len -= length; /* decrement avail ospace */
208 free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
209 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
210 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
212 if (++mve_audio_bufhead == 64) /* next buffer */
213 mve_audio_bufhead = 0;
214 mve_audio_curbuf_curpos = 0;
217 fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
220 if (len != 0 /* ospace remaining */
221 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
223 __builtin_memcpy(stream, /* dest */
224 mve_audio_buffers[mve_audio_bufhead] + mve_audio_curbuf_curpos, /* src */
227 mve_audio_curbuf_curpos += len; /* advance input */
228 stream += len; /* advance output (unnecessary) */
229 len -= len; /* advance output (unnecessary) */
231 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
233 free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
234 mve_audio_buffers[mve_audio_bufhead]=NULL;
235 mve_audio_buflens[mve_audio_bufhead]=0;
237 if (++mve_audio_bufhead == 64) /* next buffer */
238 mve_audio_bufhead = 0;
239 mve_audio_curbuf_curpos = 0;
243 fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
244 SDL_mutexV(mve_audio_mutex);
247 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
252 fprintf(stderr, "creating audio buffers\n");
254 sample_rate = get_short(data + 4);
255 desired_buffer = get_int(data + 6);
256 mve_audio_spec = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
257 mve_audio_spec->freq = sample_rate;
258 mve_audio_spec->format = AUDIO_S16LSB;
259 mve_audio_spec->channels = 2;
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)
265 fprintf(stderr, " success\n");
266 mve_audio_canplay = 1;
270 fprintf(stderr, " failure : %s\n", SDL_GetError());
271 mve_audio_canplay = 0;
274 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
275 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
280 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
282 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
285 mve_audio_playing = 1;
291 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
293 static const int selected_chan=1;
296 if (mve_audio_canplay)
298 if (mve_audio_playing)
301 chan = get_short(data + 2);
302 nsamp = get_short(data + 4);
303 if (chan & selected_chan)
305 if (!mve_audio_mutex) {
306 fprintf(stderr, "audio_data_handler: creating mutex");
307 mve_audio_mutex = SDL_CreateMutex();
309 SDL_mutexP(mve_audio_mutex);
310 mve_audio_buflens[mve_audio_buftail] = nsamp;
311 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
313 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
315 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
317 if (++mve_audio_buftail == 64)
318 mve_audio_buftail = 0;
320 if (mve_audio_buftail == mve_audio_bufhead)
321 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
322 SDL_mutexV(mve_audio_mutex);
325 if (mve_audio_playing)
332 /*************************
334 *************************/
335 static SDL_Surface *g_screen;
336 static int g_screenWidth, g_screenHeight;
337 static int g_width, g_height;
338 static unsigned char g_palette[768];
339 static unsigned char *g_vBackBuf1, *g_vBackBuf2;
340 static unsigned char *g_pCurMap=NULL;
341 static int g_nMapLength=0;
343 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
347 h = get_short(data+2);
350 g_vBackBuf1 = malloc(g_width * g_height);
351 g_vBackBuf2 = malloc(g_width * g_height);
352 memset(g_vBackBuf1, 0, g_width * g_height);
353 memset(g_vBackBuf2, 0, g_width * g_height);
357 //static int stupefaction=0;
358 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
361 unsigned char *pal = g_palette;
362 unsigned char *pDest;
363 unsigned char *pixels = g_vBackBuf1;
364 SDL_Surface *screenSprite;
368 SDL_Surface *initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, 8, 0, 0, 0, 0);
369 for(i = 0; i < 256; i++)
371 initSprite->format->palette->colors[i].r = (*pal++) << 2;
372 initSprite->format->palette->colors[i].g = (*pal++) << 2;
373 initSprite->format->palette->colors[i].b = (*pal++) << 2;
374 initSprite->format->palette->colors[i].unused = 0;
377 pDest = initSprite->pixels;
378 for (i=0; i<g_height; i++)
380 memcpy(pDest, pixels, g_width);
382 pDest += initSprite->pitch;
385 screenSprite = SDL_DisplayFormat(initSprite);
386 SDL_FreeSurface(initSprite);
388 if (g_screenWidth > screenSprite->w) x = (g_screenWidth - screenSprite->w) >> 1;
390 if (g_screenHeight > screenSprite->h) y = (g_screenHeight - screenSprite->h) >> 1;
394 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
395 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
396 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
397 if ( (g_screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF )
400 SDL_UpdateRects(g_screen, 1, &renderArea);
401 SDL_FreeSurface(screenSprite);
405 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
408 width = get_short(data);
409 height = get_short(data+2);
410 g_screen = SDL_SetVideoMode(width, height, 16, SDL_ANYFORMAT);
411 g_screenWidth = width;
412 g_screenHeight = height;
413 memset(g_palette, 0, 768);
417 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
420 start = get_short(data);
421 count = get_short(data+2);
422 memcpy(g_palette + 3*start, data+4, 3*count);
426 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
433 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
435 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
437 short nFrameHot, nFrameCold;
438 short nXoffset, nYoffset;
439 short nXsize, nYsize;
443 nFrameHot = get_short(data);
444 nFrameCold = get_short(data+2);
445 nXoffset = get_short(data+4);
446 nYoffset = get_short(data+6);
447 nXsize = get_short(data+8);
448 nYsize = get_short(data+10);
449 nFlags = get_short(data+12);
454 g_vBackBuf1 = g_vBackBuf2;
458 /* convert the frame */
459 decodeFrame(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
464 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
470 void initializeMovie(MVESTREAM *mve)
472 mve_set_handler(mve, 0x00, end_movie_handler);
473 mve_set_handler(mve, 0x01, end_chunk_handler);
474 mve_set_handler(mve, 0x02, create_timer_handler);
475 mve_set_handler(mve, 0x03, create_audiobuf_handler);
476 mve_set_handler(mve, 0x04, play_audio_handler);
477 mve_set_handler(mve, 0x05, create_videobuf_handler);
478 mve_set_handler(mve, 0x07, display_video_handler);
479 mve_set_handler(mve, 0x08, audio_data_handler);
480 mve_set_handler(mve, 0x09, audio_data_handler);
481 mve_set_handler(mve, 0x0a, init_video_handler);
482 mve_set_handler(mve, 0x0c, video_palette_handler);
483 mve_set_handler(mve, 0x0f, video_codemap_handler);
484 mve_set_handler(mve, 0x11, video_data_handler);
488 static void playMovie(MVESTREAM *mve)
494 cont = mve_play_next_chunk(mve);
495 if (micro_frame_delay && !init_timer)
509 void shutdownMovie(MVESTREAM *mve)
513 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
515 static void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
524 for (i=0; i<xb/2; i++)
526 dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
527 if (pFrame < g_vBackBuf1)
528 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
529 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
530 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
531 dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
532 if (pFrame < g_vBackBuf1)
533 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
534 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
535 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
545 static void relClose(int i, int *x, int *y)
556 static void relFar(int i, int sign, int *x, int *y)
560 *x = sign * (8 + (i % 7));
565 *x = sign * (-14 + (i - 56) % 29);
566 *y = sign * (8 + (i - 56) / 29);
570 static void copyFrame(unsigned char *pDest, unsigned char *pSrc)
576 memcpy(pDest, pSrc, 8);
582 static void patternRow4Pixels(unsigned char *pFrame,
583 unsigned char pat0, unsigned char pat1,
586 unsigned short mask=0x0003;
587 unsigned short shift=0;
588 unsigned short pattern = (pat1 << 8) | pat0;
592 *pFrame++ = p[(mask & pattern) >> shift];
598 static void patternRow4Pixels2(unsigned char *pFrame,
602 unsigned char mask=0x03;
603 unsigned char shift=0;
609 pel = p[(mask & pat0) >> shift];
612 pFrame[g_width + 0] = pel;
613 pFrame[g_width + 2] = pel;
621 static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p)
623 unsigned char mask=0x03;
624 unsigned char shift=0;
629 pel = p[(mask & pat) >> shift];
638 static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p)
640 unsigned long mask = 0x00000003UL;
643 unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
647 pFrame[i&3] = p[(pat & mask) >> shift];
658 static void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p)
660 unsigned char mask=0x01;
664 *pFrame++ = p[(mask & pat) ? 1 : 0];
669 static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p)
672 unsigned char mask=0x1;
677 pel = p[(mask & pat) ? 1 : 0];
680 pFrame[g_width + 0] = pel;
681 pFrame[g_width + 2] = pel;
688 static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p)
690 unsigned short mask = 0x0001;
692 unsigned short pat = (pat1 << 8) | pat0;
696 pFrame[i&3] = p[(pat & mask) ? 1 : 0];
705 static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
708 unsigned char pat[16];
715 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
721 relFar(*(*pData)++, 1, &x, &y);
722 copyFrame(*pFrame, *pFrame + x + y*g_width);
728 relFar(*(*pData)++, -1, &x, &y);
729 copyFrame(*pFrame, *pFrame + x + y*g_width);
735 relClose(*(*pData)++, &x, &y);
736 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
742 x = (char)*(*pData)++;
743 y = (char)*(*pData)++;
744 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
753 if (++*curXb == (g_width >> 3))
755 *pFrame += 7*g_width;
757 if (++*curYb == (g_height >> 3))
770 patternRow2Pixels(*pFrame, *(*pData)++, p);
778 patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
779 *pFrame += 2*g_width;
780 patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
781 *pFrame += 2*g_width;
784 *pFrame -= (8*g_width - 8);
788 if ( (*pData)[0] <= (*pData)[1])
794 pat[0] = *(*pData)++;
795 pat[1] = *(*pData)++;
796 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
799 *pFrame -= (4*g_width - 4);
801 *pFrame += 4*g_width;
804 else if ( (*pData)[6] <= (*pData)[7])
813 pat[0] = *(*pData)++;
814 pat[1] = *(*pData)++;
815 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
818 *pFrame -= (4*g_width - 4);
820 *pFrame += 4*g_width;
832 patternRow2Pixels(*pFrame, *(*pData)++, p);
835 *pFrame -= (8*g_width - 8);
840 if ( (*pData)[0] <= (*pData)[1])
842 if ( (*pData)[2] <= (*pData)[3])
851 pat[0] = *(*pData)++;
852 pat[1] = *(*pData)++;
853 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
857 *pFrame -= (8*g_width - 8);
866 patternRow4Pixels2(*pFrame, *(*pData)++, p);
867 *pFrame += 2*g_width;
868 patternRow4Pixels2(*pFrame, *(*pData)++, p);
869 *pFrame += 2*g_width;
870 patternRow4Pixels2(*pFrame, *(*pData)++, p);
871 *pFrame += 2*g_width;
872 patternRow4Pixels2(*pFrame, *(*pData)++, p);
873 *pFrame -= (6*g_width - 8);
878 if ( (*pData)[2] <= (*pData)[3])
887 pat[0] = *(*pData)++;
888 patternRow4Pixels2x1(*pFrame, pat[0], p);
892 *pFrame -= (8*g_width - 8);
903 pat[0] = *(*pData)++;
904 pat[1] = *(*pData)++;
905 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
907 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
911 *pFrame -= (8*g_width - 8);
917 if ( (*pData)[0] <= (*pData)[1])
925 pat[0] = *(*pData)++;
926 pat[1] = *(*pData)++;
927 pat[2] = *(*pData)++;
928 pat[3] = *(*pData)++;
930 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
933 *pFrame -= (4*g_width - 4);
935 *pFrame += 4*g_width;
940 if ( (*pData)[12] <= (*pData)[13])
952 pat[0] = *(*pData)++;
953 pat[1] = *(*pData)++;
954 pat[2] = *(*pData)++;
955 pat[3] = *(*pData)++;
957 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
960 *pFrame -= (4*g_width - 4);
962 *pFrame += 4*g_width;
977 pat[0] = *(*pData)++;
978 pat[1] = *(*pData)++;
979 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
983 *pFrame -= (8*g_width - 8);
991 memcpy(*pFrame, *pData, 8);
996 *pFrame -= (8*g_width - 8);
1006 (*pFrame)[j+2*k] = (*pData)[k];
1007 (*pFrame)[g_width+j+2*k] = (*pData)[k];
1014 *pFrame -= (8*g_width - 8);
1024 (*pFrame)[k*g_width+j] = (*pData)[0];
1025 (*pFrame)[k*g_width+j+4] = (*pData)[1];
1028 *pFrame += 4*g_width;
1032 *pFrame -= (8*g_width - 8);
1038 memset(*pFrame, **pData, 8);
1043 *pFrame -= (8*g_width - 8);
1051 (*pFrame)[j] = (*pData)[(i+j)&1];
1057 *pFrame -= (8*g_width - 8);