1 /* $Id: mveplay.c,v 1.11 2003-02-12 09:14:24 btb Exp $ */
15 #include <sys/types.h>
23 #include "mve_audio.h"
34 #define MIN(a,b) ((a)<(b)?(a):(b))
37 #define MVE_OPCODE_ENDOFSTREAM 0x00
38 #define MVE_OPCODE_ENDOFCHUNK 0x01
39 #define MVE_OPCODE_CREATETIMER 0x02
40 #define MVE_OPCODE_INITAUDIOBUFFERS 0x03
41 #define MVE_OPCODE_STARTSTOPAUDIO 0x04
42 #define MVE_OPCODE_INITVIDEOBUFFERS 0x05
44 #define MVE_OPCODE_DISPLAYVIDEO 0x07
45 #define MVE_OPCODE_AUDIOFRAMEDATA 0x08
46 #define MVE_OPCODE_AUDIOFRAMESILENCE 0x09
47 #define MVE_OPCODE_INITVIDEOMODE 0x0A
49 #define MVE_OPCODE_SETPALETTE 0x0C
50 #define MVE_OPCODE_SETPALETTECOMPRESSED 0x0D
52 #define MVE_OPCODE_SETDECODINGMAP 0x0F
54 #define MVE_OPCODE_VIDEODATA 0x11
56 #define MVE_AUDIO_FLAGS_STEREO 1
57 #define MVE_AUDIO_FLAGS_16BIT 2
58 #define MVE_AUDIO_FLAGS_COMPRESSED 4
61 static int g_spdFactorDenom=10;
62 static int playing = 1;
64 void initializeMovie(MVESTREAM *mve);
65 void playMovie(MVESTREAM *mve);
66 void shutdownMovie(MVESTREAM *mve);
68 static short get_short(unsigned char *data)
71 value = data[0] | (data[1] << 8);
75 static unsigned short get_ushort(unsigned char *data)
78 value = data[0] | (data[1] << 8);
82 static int get_int(unsigned char *data)
85 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
89 static unsigned int unhandled_chunks[32*256];
91 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
93 unhandled_chunks[major<<8|minor]++;
94 //fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
98 /*************************
100 *************************/
101 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
106 /*************************
108 *************************/
113 static int micro_frame_delay=0;
114 static int timer_started=0;
115 static struct timeval timer_expire = {0, 0};
117 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
119 __extension__ long long temp;
120 micro_frame_delay = get_int(data) * (int)get_short(data+4);
121 if (g_spdFactorNum != 0)
123 temp = micro_frame_delay;
124 temp *= g_spdFactorNum;
125 temp /= g_spdFactorDenom;
126 micro_frame_delay = (int)temp;
132 static void timer_stop(void)
134 timer_expire.tv_sec = 0;
135 timer_expire.tv_usec = 0;
139 static void timer_start(void)
142 gettimeofday(&timer_expire, NULL);
143 timer_expire.tv_usec += micro_frame_delay;
144 if (timer_expire.tv_usec > 1000000)
146 nsec = timer_expire.tv_usec / 1000000;
147 timer_expire.tv_sec += nsec;
148 timer_expire.tv_usec -= nsec*1000000;
153 static void do_timer_wait(void)
161 gettimeofday(&tv, NULL);
162 if (tv.tv_sec > timer_expire.tv_sec)
164 else if (tv.tv_sec == timer_expire.tv_sec && tv.tv_usec >= timer_expire.tv_usec)
167 ts.tv_sec = timer_expire.tv_sec - tv.tv_sec;
168 ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec);
171 ts.tv_nsec += 1000000000UL;
175 usleep(ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
177 if (nanosleep(&ts, NULL) == -1 && errno == EINTR)
182 timer_expire.tv_usec += micro_frame_delay;
183 if (timer_expire.tv_usec > 1000000)
185 nsec = timer_expire.tv_usec / 1000000;
186 timer_expire.tv_sec += nsec;
187 timer_expire.tv_usec -= nsec*1000000;
191 /*************************
193 *************************/
195 #define TOTAL_AUDIO_BUFFERS 64
197 static void mve_audio_callback(void *userdata, unsigned char *stream, int len);
198 static short *mve_audio_buffers[TOTAL_AUDIO_BUFFERS];
199 static int mve_audio_buflens[TOTAL_AUDIO_BUFFERS];
200 static int mve_audio_curbuf_curpos=0;
201 static int mve_audio_bufhead=0;
202 static int mve_audio_buftail=0;
203 static int mve_audio_playing=0;
204 static int mve_audio_canplay=0;
205 static int mve_audio_compressed=0;
206 static SDL_AudioSpec *mve_audio_spec=NULL;
208 static void mve_audio_callback(void *userdata, unsigned char *stream, int len)
212 if (mve_audio_bufhead == mve_audio_buftail)
215 //fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
217 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
218 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
220 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
221 memcpy(stream, /* cur output position */
222 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead])+mve_audio_curbuf_curpos, /* cur input position */
223 length); /* cur input length */
226 stream += length; /* advance output */
227 len -= length; /* decrement avail ospace */
228 free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
229 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
230 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
232 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
233 mve_audio_bufhead = 0;
234 mve_audio_curbuf_curpos = 0;
237 //fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
240 if (len != 0 /* ospace remaining */
241 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
243 memcpy(stream, /* dest */
244 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */
247 mve_audio_curbuf_curpos += len; /* advance input */
248 stream += len; /* advance output (unnecessary) */
249 len -= len; /* advance output (unnecessary) */
251 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
253 free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
254 mve_audio_buffers[mve_audio_bufhead]=NULL;
255 mve_audio_buflens[mve_audio_bufhead]=0;
257 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
258 mve_audio_bufhead = 0;
259 mve_audio_curbuf_curpos = 0;
263 //fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
267 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
280 flags = get_ushort(data + 2);
281 sample_rate = get_ushort(data + 4);
282 desired_buffer = get_int(data + 6);
284 stereo = (flags & MVE_AUDIO_FLAGS_STEREO) ? 1 : 0;
285 bitsize = (flags & MVE_AUDIO_FLAGS_16BIT) ? 1 : 0;
288 compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED ? 1 : 0;
293 mve_audio_compressed = compressed;
296 format = AUDIO_S16LSB;
301 fprintf(stderr, "creating audio buffers:\n");
302 fprintf(stderr, "sample rate = %d, stereo = %d, bitsize = %d, compressed = %d\n",
303 sample_rate, stereo, bitsize ? 16 : 8, compressed);
305 mve_audio_spec = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
306 mve_audio_spec->freq = sample_rate;
307 mve_audio_spec->format = format;
308 mve_audio_spec->channels = (stereo) ? 2 : 1;
309 mve_audio_spec->samples = 4096;
310 mve_audio_spec->callback = mve_audio_callback;
311 mve_audio_spec->userdata = NULL;
312 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
314 fprintf(stderr, " success\n");
315 mve_audio_canplay = 1;
319 fprintf(stderr, " failure : %s\n", SDL_GetError());
320 mve_audio_canplay = 0;
323 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
324 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
330 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
333 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
336 mve_audio_playing = 1;
342 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
345 static const int selected_chan=1;
348 if (mve_audio_canplay)
350 if (mve_audio_playing)
353 chan = get_ushort(data + 2);
354 nsamp = get_ushort(data + 4);
355 if (chan & selected_chan)
357 /* HACK: +4 mveaudio_uncompress adds 4 more bytes */
358 if (major == MVE_OPCODE_AUDIOFRAMEDATA) {
359 if (mve_audio_compressed) {
362 mve_audio_buflens[mve_audio_buftail] = nsamp;
363 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
364 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
369 mve_audio_buflens[mve_audio_buftail] = nsamp;
370 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
371 memcpy(mve_audio_buffers[mve_audio_buftail], data, nsamp);
374 mve_audio_buflens[mve_audio_buftail] = nsamp;
375 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
377 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
380 if (++mve_audio_buftail == TOTAL_AUDIO_BUFFERS)
381 mve_audio_buftail = 0;
383 if (mve_audio_buftail == mve_audio_bufhead)
384 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
387 if (mve_audio_playing)
395 /*************************
397 *************************/
398 int g_width, g_height;
399 void *g_vBackBuf1, *g_vBackBuf2 = NULL;
402 static SDL_Surface *g_screen;
404 static grs_bitmap *g_screen;
406 static int g_screenWidth, g_screenHeight;
407 static unsigned char g_palette[768];
408 static unsigned char *g_pCurMap=NULL;
409 static int g_nMapLength=0;
410 static int g_truecolor;
411 static int g_palette_changed = 0;
413 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
416 short count, truecolor;
419 h = get_short(data+2);
422 count = get_short(data+4);
428 truecolor = get_short(data+6);
437 Assert((g_width == g_screen->bm_w) && (g_height == g_screen->bm_h));
440 /* TODO: * 4 causes crashes on some files */
441 g_vBackBuf1 = malloc(g_width * g_height * 8);
443 g_vBackBuf2 = (unsigned short *)g_vBackBuf1 + (g_width * g_height);
445 g_vBackBuf2 = (unsigned char *)g_vBackBuf1 + (g_width * g_height);
448 memset(g_vBackBuf1, 0, g_width * g_height * 4);
450 fprintf(stderr, "DEBUG: w,h=%d,%d count=%d, tc=%d\n", w, h, count, truecolor);
452 g_truecolor = truecolor;
458 static int do_sdl_events()
462 while (SDL_PollEvent(&event)) {
469 if (event.key.keysym.sym == SDLK_ESCAPE)
476 case SDL_MOUSEBUTTONDOWN:
478 if (event.button.button == SDL_BUTTON_LEFT) {
479 printf("GRID: %d,%d (pix:%d,%d)\n",
480 event.button.x / 16, event.button.y / 8,
481 event.button.x, event.button.y);
493 static void ConvertAndDraw()
496 unsigned char *pal = g_palette;
497 unsigned char *pDest;
498 unsigned char *pixels = g_vBackBuf1;
499 SDL_Surface *screenSprite, *initSprite;
503 initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, g_truecolor?16:8, 0x7C00, 0x03E0, 0x001F, 0);
506 for(i = 0; i < 256; i++) {
507 initSprite->format->palette->colors[i].r = (*pal++) << 2;
508 initSprite->format->palette->colors[i].g = (*pal++) << 2;
509 initSprite->format->palette->colors[i].b = (*pal++) << 2;
510 initSprite->format->palette->colors[i].unused = 0;
514 pDest = initSprite->pixels;
516 if (0 /*g_truecolor*/) {
518 unsigned short *pSrcs, *pDests;
520 pSrcs = (unsigned short *)pixels;
521 pDests = (unsigned short *)pDest;
523 for (y=0; y<g_height; y++) {
524 for (x = 0; x < g_width; x++) {
525 pDests[x] = (1<<15)|*pSrcs;
528 pDests += g_screenWidth;
533 for (i=0; i<g_height; i++) {
534 memcpy(pDest, pixels, g_width * (g_truecolor?2:1));
535 pixels += g_width* (g_truecolor?2:1);
536 pDest += initSprite->pitch;
540 screenSprite = SDL_DisplayFormat(initSprite);
541 SDL_FreeSurface(initSprite);
543 if (g_screenWidth > screenSprite->w)
544 x = (g_screenWidth - screenSprite->w) >> 1;
547 if (g_screenHeight > screenSprite->h)
548 y = (g_screenHeight - screenSprite->h) >> 1;
553 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
554 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
555 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
557 SDL_FreeSurface(screenSprite);
561 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
570 if (g_palette_changed)
572 gr_palette_load(g_palette);
573 g_palette_changed = 0;
576 memcpy(g_screen->bm_data, g_vBackBuf1, g_width * g_height);
582 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
585 width = get_short(data);
586 height = get_short(data+2);
588 g_screen = SDL_SetVideoMode(width, height, 16, SDL_ANYFORMAT|SDL_DOUBLEBUF);
590 g_screenWidth = width;
591 g_screenHeight = height;
592 memset(g_palette, 0, 765);
593 // 255 needs to default to white, for subtitles, etc
594 memset(g_palette + 765, 63, 3);
598 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
601 start = get_short(data);
602 count = get_short(data+2);
603 memcpy(g_palette + 3*start, data+4, 3*count);
604 g_palette_changed = 1;
609 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
616 void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
617 void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
619 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
621 short nFrameHot, nFrameCold;
622 short nXoffset, nYoffset;
623 short nXsize, nYsize;
624 unsigned short nFlags;
627 nFrameHot = get_short(data);
628 nFrameCold = get_short(data+2);
629 nXoffset = get_short(data+4);
630 nYoffset = get_short(data+6);
631 nXsize = get_short(data+8);
632 nYsize = get_short(data+10);
633 nFlags = get_ushort(data+12);
637 temp = (unsigned char *)g_vBackBuf1;
638 g_vBackBuf1 = g_vBackBuf2;
642 /* convert the frame */
644 decodeFrame16((unsigned char *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
646 decodeFrame8(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
652 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
658 void initializeMovie(MVESTREAM *mve)
662 for (i = 0; i < 32; i++)
663 mve_set_handler(mve, i, default_seg_handler);
665 memset(unhandled_chunks, 0, 32*256);
667 mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler);
668 mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler);
669 mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler);
670 mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler);
671 mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler);
672 mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler);
674 mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler);
675 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler);
676 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler);
677 mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler);
679 mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler);
680 mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, video_palette_handler);
681 mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler);
683 mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler);
686 void playMovie(MVESTREAM *mve)
690 while (cont && playing)
692 cont = mve_play_next_chunk(mve);
693 if (micro_frame_delay && !init_timer)
703 void shutdownMovie(MVESTREAM *mve)
707 for (i = 0; i < 32*256; i++) {
708 if (unhandled_chunks[i]) {
709 fprintf(stderr, "unhandled chunks of type %02x/%02x: %d\n", i>>8, i&0xFF, unhandled_chunks[i]);
715 void mveplay_initializeMovie(MVESTREAM *mve, grs_bitmap *mve_bitmap)
719 g_screen = mve_bitmap;
721 for (i = 0; i < 32; i++)
722 mve_set_handler(mve, i, default_seg_handler);
724 mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler);
725 mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler);
726 mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler);
727 mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler);
728 mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler);
729 mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler);
731 mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler);
732 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler);
733 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler);
734 mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler);
736 mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler);
737 mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, default_seg_handler);
739 mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler);
741 mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler);
745 int mveplay_stepMovie(MVESTREAM *mve)
747 static int init_timer=0;
753 cont = mve_play_next_chunk(mve);
754 if (micro_frame_delay && !init_timer) {
764 void mveplay_restartTimer(MVESTREAM *mve)
769 void mveplay_shutdownMovie(MVESTREAM *mve)
776 if (mve_audio_canplay) {
777 // only close audio if we opened it
778 mve_audio_canplay = 0;
780 for (i = 0; i < TOTAL_AUDIO_BUFFERS; i++)
781 if (mve_audio_buffers[i] != NULL)
782 free(mve_audio_buffers[i]);
783 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
784 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
785 mve_audio_curbuf_curpos=0;
790 mve_audio_compressed=0;
792 free(mve_audio_spec);