1 /* $Id: mveplay.c,v 1.10 2003-02-12 08:58:38 btb Exp $ */
13 #include <sys/types.h>
21 #include "mve_audio.h"
32 #define MIN(a,b) ((a)<(b)?(a):(b))
35 #define MVE_OPCODE_ENDOFSTREAM 0x00
36 #define MVE_OPCODE_ENDOFCHUNK 0x01
37 #define MVE_OPCODE_CREATETIMER 0x02
38 #define MVE_OPCODE_INITAUDIOBUFFERS 0x03
39 #define MVE_OPCODE_STARTSTOPAUDIO 0x04
40 #define MVE_OPCODE_INITVIDEOBUFFERS 0x05
42 #define MVE_OPCODE_DISPLAYVIDEO 0x07
43 #define MVE_OPCODE_AUDIOFRAMEDATA 0x08
44 #define MVE_OPCODE_AUDIOFRAMESILENCE 0x09
45 #define MVE_OPCODE_INITVIDEOMODE 0x0A
47 #define MVE_OPCODE_SETPALETTE 0x0C
48 #define MVE_OPCODE_SETPALETTECOMPRESSED 0x0D
50 #define MVE_OPCODE_SETDECODINGMAP 0x0F
52 #define MVE_OPCODE_VIDEODATA 0x11
54 #define MVE_AUDIO_FLAGS_STEREO 1
55 #define MVE_AUDIO_FLAGS_16BIT 2
56 #define MVE_AUDIO_FLAGS_COMPRESSED 4
59 static int g_spdFactorDenom=10;
60 static int playing = 1;
62 void initializeMovie(MVESTREAM *mve);
63 void playMovie(MVESTREAM *mve);
64 void shutdownMovie(MVESTREAM *mve);
66 static short get_short(unsigned char *data)
69 value = data[0] | (data[1] << 8);
73 static unsigned short get_ushort(unsigned char *data)
76 value = data[0] | (data[1] << 8);
80 static int get_int(unsigned char *data)
83 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
87 static unsigned int unhandled_chunks[32*256];
89 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
91 unhandled_chunks[major<<8|minor]++;
92 //fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
96 /*************************
98 *************************/
99 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
104 /*************************
106 *************************/
111 static int micro_frame_delay=0;
112 static int timer_started=0;
113 static struct timeval timer_expire = {0, 0};
115 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
117 __extension__ long long temp;
118 micro_frame_delay = get_int(data) * (int)get_short(data+4);
119 if (g_spdFactorNum != 0)
121 temp = micro_frame_delay;
122 temp *= g_spdFactorNum;
123 temp /= g_spdFactorDenom;
124 micro_frame_delay = (int)temp;
130 static void timer_stop(void)
132 timer_expire.tv_sec = 0;
133 timer_expire.tv_usec = 0;
137 static void timer_start(void)
140 gettimeofday(&timer_expire, NULL);
141 timer_expire.tv_usec += micro_frame_delay;
142 if (timer_expire.tv_usec > 1000000)
144 nsec = timer_expire.tv_usec / 1000000;
145 timer_expire.tv_sec += nsec;
146 timer_expire.tv_usec -= nsec*1000000;
151 static void do_timer_wait(void)
159 gettimeofday(&tv, NULL);
160 if (tv.tv_sec > timer_expire.tv_sec)
162 else if (tv.tv_sec == timer_expire.tv_sec && tv.tv_usec >= timer_expire.tv_usec)
165 ts.tv_sec = timer_expire.tv_sec - tv.tv_sec;
166 ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec);
169 ts.tv_nsec += 1000000000UL;
173 usleep(ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
175 if (nanosleep(&ts, NULL) == -1 && errno == EINTR)
180 timer_expire.tv_usec += micro_frame_delay;
181 if (timer_expire.tv_usec > 1000000)
183 nsec = timer_expire.tv_usec / 1000000;
184 timer_expire.tv_sec += nsec;
185 timer_expire.tv_usec -= nsec*1000000;
189 /*************************
191 *************************/
193 #define TOTAL_AUDIO_BUFFERS 64
195 static void mve_audio_callback(void *userdata, unsigned char *stream, int len);
196 static short *mve_audio_buffers[TOTAL_AUDIO_BUFFERS];
197 static int mve_audio_buflens[TOTAL_AUDIO_BUFFERS];
198 static int mve_audio_curbuf_curpos=0;
199 static int mve_audio_bufhead=0;
200 static int mve_audio_buftail=0;
201 static int mve_audio_playing=0;
202 static int mve_audio_canplay=0;
203 static int mve_audio_compressed=0;
204 static SDL_AudioSpec *mve_audio_spec=NULL;
206 static void mve_audio_callback(void *userdata, unsigned char *stream, int len)
210 if (mve_audio_bufhead == mve_audio_buftail)
213 //fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
215 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
216 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
218 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
219 memcpy(stream, /* cur output position */
220 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead])+mve_audio_curbuf_curpos, /* cur input position */
221 length); /* cur input length */
224 stream += length; /* advance output */
225 len -= length; /* decrement avail ospace */
226 free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
227 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
228 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
230 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
231 mve_audio_bufhead = 0;
232 mve_audio_curbuf_curpos = 0;
235 //fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
238 if (len != 0 /* ospace remaining */
239 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
241 memcpy(stream, /* dest */
242 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */
245 mve_audio_curbuf_curpos += len; /* advance input */
246 stream += len; /* advance output (unnecessary) */
247 len -= len; /* advance output (unnecessary) */
249 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
251 free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
252 mve_audio_buffers[mve_audio_bufhead]=NULL;
253 mve_audio_buflens[mve_audio_bufhead]=0;
255 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
256 mve_audio_bufhead = 0;
257 mve_audio_curbuf_curpos = 0;
261 //fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
265 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
278 flags = get_ushort(data + 2);
279 sample_rate = get_ushort(data + 4);
280 desired_buffer = get_int(data + 6);
282 stereo = (flags & MVE_AUDIO_FLAGS_STEREO) ? 1 : 0;
283 bitsize = (flags & MVE_AUDIO_FLAGS_16BIT) ? 1 : 0;
286 compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED ? 1 : 0;
291 mve_audio_compressed = compressed;
294 format = AUDIO_S16LSB;
299 fprintf(stderr, "creating audio buffers:\n");
300 fprintf(stderr, "sample rate = %d, stereo = %d, bitsize = %d, compressed = %d\n",
301 sample_rate, stereo, bitsize ? 16 : 8, compressed);
303 mve_audio_spec = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
304 mve_audio_spec->freq = sample_rate;
305 mve_audio_spec->format = format;
306 mve_audio_spec->channels = (stereo) ? 2 : 1;
307 mve_audio_spec->samples = 4096;
308 mve_audio_spec->callback = mve_audio_callback;
309 mve_audio_spec->userdata = NULL;
310 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
312 fprintf(stderr, " success\n");
313 mve_audio_canplay = 1;
317 fprintf(stderr, " failure : %s\n", SDL_GetError());
318 mve_audio_canplay = 0;
321 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
322 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
328 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
331 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
334 mve_audio_playing = 1;
340 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
343 static const int selected_chan=1;
346 if (mve_audio_canplay)
348 if (mve_audio_playing)
351 chan = get_ushort(data + 2);
352 nsamp = get_ushort(data + 4);
353 if (chan & selected_chan)
355 /* HACK: +4 mveaudio_uncompress adds 4 more bytes */
356 if (major == MVE_OPCODE_AUDIOFRAMEDATA) {
357 if (mve_audio_compressed) {
360 mve_audio_buflens[mve_audio_buftail] = nsamp;
361 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
362 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
367 mve_audio_buflens[mve_audio_buftail] = nsamp;
368 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
369 memcpy(mve_audio_buffers[mve_audio_buftail], data, nsamp);
372 mve_audio_buflens[mve_audio_buftail] = nsamp;
373 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
375 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
378 if (++mve_audio_buftail == TOTAL_AUDIO_BUFFERS)
379 mve_audio_buftail = 0;
381 if (mve_audio_buftail == mve_audio_bufhead)
382 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
385 if (mve_audio_playing)
393 /*************************
395 *************************/
396 int g_width, g_height;
397 void *g_vBackBuf1, *g_vBackBuf2 = NULL;
400 static SDL_Surface *g_screen;
402 static grs_bitmap *g_screen;
404 static int g_screenWidth, g_screenHeight;
405 static unsigned char g_palette[768];
406 static unsigned char *g_pCurMap=NULL;
407 static int g_nMapLength=0;
408 static int g_truecolor;
409 static int g_palette_changed = 0;
411 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
414 short count, truecolor;
417 h = get_short(data+2);
420 count = get_short(data+4);
426 truecolor = get_short(data+6);
435 Assert((g_width == g_screen->bm_w) && (g_height == g_screen->bm_h));
438 /* TODO: * 4 causes crashes on some files */
439 g_vBackBuf1 = malloc(g_width * g_height * 8);
441 g_vBackBuf2 = (unsigned short *)g_vBackBuf1 + (g_width * g_height);
443 g_vBackBuf2 = (unsigned char *)g_vBackBuf1 + (g_width * g_height);
446 memset(g_vBackBuf1, 0, g_width * g_height * 4);
448 fprintf(stderr, "DEBUG: w,h=%d,%d count=%d, tc=%d\n", w, h, count, truecolor);
450 g_truecolor = truecolor;
456 static int do_sdl_events()
460 while (SDL_PollEvent(&event)) {
467 if (event.key.keysym.sym == SDLK_ESCAPE)
474 case SDL_MOUSEBUTTONDOWN:
476 if (event.button.button == SDL_BUTTON_LEFT) {
477 printf("GRID: %d,%d (pix:%d,%d)\n",
478 event.button.x / 16, event.button.y / 8,
479 event.button.x, event.button.y);
491 static void ConvertAndDraw()
494 unsigned char *pal = g_palette;
495 unsigned char *pDest;
496 unsigned char *pixels = g_vBackBuf1;
497 SDL_Surface *screenSprite, *initSprite;
501 initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, g_truecolor?16:8, 0x7C00, 0x03E0, 0x001F, 0);
504 for(i = 0; i < 256; i++) {
505 initSprite->format->palette->colors[i].r = (*pal++) << 2;
506 initSprite->format->palette->colors[i].g = (*pal++) << 2;
507 initSprite->format->palette->colors[i].b = (*pal++) << 2;
508 initSprite->format->palette->colors[i].unused = 0;
512 pDest = initSprite->pixels;
514 if (0 /*g_truecolor*/) {
516 unsigned short *pSrcs, *pDests;
518 pSrcs = (unsigned short *)pixels;
519 pDests = (unsigned short *)pDest;
521 for (y=0; y<g_height; y++) {
522 for (x = 0; x < g_width; x++) {
523 pDests[x] = (1<<15)|*pSrcs;
526 pDests += g_screenWidth;
531 for (i=0; i<g_height; i++) {
532 memcpy(pDest, pixels, g_width * (g_truecolor?2:1));
533 pixels += g_width* (g_truecolor?2:1);
534 pDest += initSprite->pitch;
538 screenSprite = SDL_DisplayFormat(initSprite);
539 SDL_FreeSurface(initSprite);
541 if (g_screenWidth > screenSprite->w)
542 x = (g_screenWidth - screenSprite->w) >> 1;
545 if (g_screenHeight > screenSprite->h)
546 y = (g_screenHeight - screenSprite->h) >> 1;
551 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
552 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
553 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
555 SDL_FreeSurface(screenSprite);
559 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
568 if (g_palette_changed)
570 gr_palette_load(g_palette);
571 g_palette_changed = 0;
574 memcpy(g_screen->bm_data, g_vBackBuf1, g_width * g_height);
580 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
583 width = get_short(data);
584 height = get_short(data+2);
586 g_screen = SDL_SetVideoMode(width, height, 16, SDL_ANYFORMAT|SDL_DOUBLEBUF);
588 g_screenWidth = width;
589 g_screenHeight = height;
590 memset(g_palette, 0, 765);
591 // 255 needs to default to white, for subtitles, etc
592 memset(g_palette + 765, 63, 3);
596 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
599 start = get_short(data);
600 count = get_short(data+2);
601 memcpy(g_palette + 3*start, data+4, 3*count);
602 g_palette_changed = 1;
607 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
614 void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
615 void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
617 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
619 short nFrameHot, nFrameCold;
620 short nXoffset, nYoffset;
621 short nXsize, nYsize;
622 unsigned short nFlags;
625 nFrameHot = get_short(data);
626 nFrameCold = get_short(data+2);
627 nXoffset = get_short(data+4);
628 nYoffset = get_short(data+6);
629 nXsize = get_short(data+8);
630 nYsize = get_short(data+10);
631 nFlags = get_ushort(data+12);
635 temp = (unsigned char *)g_vBackBuf1;
636 g_vBackBuf1 = g_vBackBuf2;
640 /* convert the frame */
642 decodeFrame16((unsigned char *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
644 decodeFrame8(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
650 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
656 void initializeMovie(MVESTREAM *mve)
660 for (i = 0; i < 32; i++)
661 mve_set_handler(mve, i, default_seg_handler);
663 memset(unhandled_chunks, 0, 32*256);
665 mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler);
666 mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler);
667 mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler);
668 mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler);
669 mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler);
670 mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler);
672 mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler);
673 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler);
674 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler);
675 mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler);
677 mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler);
678 mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, video_palette_handler);
679 mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler);
681 mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler);
684 void playMovie(MVESTREAM *mve)
688 while (cont && playing)
690 cont = mve_play_next_chunk(mve);
691 if (micro_frame_delay && !init_timer)
701 void shutdownMovie(MVESTREAM *mve)
705 for (i = 0; i < 32*256; i++) {
706 if (unhandled_chunks[i]) {
707 fprintf(stderr, "unhandled chunks of type %02x/%02x: %d\n", i>>8, i&0xFF, unhandled_chunks[i]);
713 void mveplay_initializeMovie(MVESTREAM *mve, grs_bitmap *mve_bitmap)
717 g_screen = mve_bitmap;
719 for (i = 0; i < 32; i++)
720 mve_set_handler(mve, i, default_seg_handler);
722 mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler);
723 mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler);
724 mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler);
725 mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler);
726 mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler);
727 mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler);
729 mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler);
730 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler);
731 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler);
732 mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler);
734 mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler);
735 mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, default_seg_handler);
737 mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler);
739 mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler);
743 int mveplay_stepMovie(MVESTREAM *mve)
745 static int init_timer=0;
751 cont = mve_play_next_chunk(mve);
752 if (micro_frame_delay && !init_timer) {
762 void mveplay_restartTimer(MVESTREAM *mve)
767 void mveplay_shutdownMovie(MVESTREAM *mve)
774 if (mve_audio_canplay) {
775 // only close audio if we opened it
776 mve_audio_canplay = 0;
778 for (i = 0; i < TOTAL_AUDIO_BUFFERS; i++)
779 if (mve_audio_buffers[i] != NULL)
780 free(mve_audio_buffers[i]);
781 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
782 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
783 mve_audio_curbuf_curpos=0;
788 mve_audio_compressed=0;
790 free(mve_audio_spec);