10 #include "mve_audio.h"
15 #define MIN(a,b) ((a)<(b)?(a):(b))
19 static int g_spdFactorNum=0;
20 static int g_spdFactorDenom=10;
21 static int playing = 1;
23 void initializeMovie(MVESTREAM *mve);
24 void playMovie(MVESTREAM *mve);
25 void shutdownMovie(MVESTREAM *mve);
28 static int doPlay(const char *filename)
30 MVESTREAM *mve = mve_open(filename);
33 fprintf(stderr, "can't open MVE file '%s'\n", filename);
47 static short get_short(unsigned char *data)
50 value = data[0] | (data[1] << 8);
54 static unsigned short get_ushort(unsigned char *data)
57 value = data[0] | (data[1] << 8);
61 static int get_int(unsigned char *data)
64 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
68 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
70 /* fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor); */
74 /*************************
76 *************************/
77 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
82 /*************************
84 *************************/
89 static int micro_frame_delay=0;
90 static int timer_started=0;
91 static struct timeval timer_expire = {0, 0};
93 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
95 __extension__ long long temp;
96 micro_frame_delay = get_int(data) * (int)get_short(data+4);
97 if (g_spdFactorNum != 0)
99 temp = micro_frame_delay;
100 temp *= g_spdFactorNum;
101 temp /= g_spdFactorDenom;
102 micro_frame_delay = (int)temp;
108 static void timer_start(void)
111 gettimeofday(&timer_expire, NULL);
112 timer_expire.tv_usec += micro_frame_delay;
113 if (timer_expire.tv_usec > 1000000)
115 nsec = timer_expire.tv_usec / 1000000;
116 timer_expire.tv_sec += nsec;
117 timer_expire.tv_usec -= nsec*1000000;
122 static void do_timer_wait(void)
125 struct timespec ts, tsRem;
130 gettimeofday(&tv, NULL);
131 if (tv.tv_sec > timer_expire.tv_sec)
133 else if (tv.tv_sec == timer_expire.tv_sec && tv.tv_usec >= timer_expire.tv_usec)
136 ts.tv_sec = timer_expire.tv_sec - tv.tv_sec;
137 ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec);
140 ts.tv_nsec += 1000000000UL;
143 if (nanosleep(&ts, &tsRem) == -1 && errno == EINTR)
147 timer_expire.tv_usec += micro_frame_delay;
148 if (timer_expire.tv_usec > 1000000)
150 nsec = timer_expire.tv_usec / 1000000;
151 timer_expire.tv_sec += nsec;
152 timer_expire.tv_usec -= nsec*1000000;
156 /*************************
158 *************************/
159 static void mve_audio_callback(void *userdata, unsigned char *stream, int len);
160 static short *mve_audio_buffers[64];
161 static int mve_audio_buflens[64];
162 static int mve_audio_curbuf_curpos=0;
163 static int mve_audio_bufhead=0;
164 static int mve_audio_buftail=0;
165 static int mve_audio_playing=0;
166 static int mve_audio_canplay=0;
168 static SDL_AudioSpec *mve_audio_spec=NULL;
170 static int mve_audio_compressed = 0;
172 static void mve_audio_callback(void *userdata, unsigned char *stream, int len)
177 if (mve_audio_bufhead == mve_audio_buftail)
180 //fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
182 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
183 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
185 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
186 memcpy(stream, /* cur output position */
187 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead])+mve_audio_curbuf_curpos, /* cur input position */
188 length); /* cur input length */
191 stream += length; /* advance output */
192 len -= length; /* decrement avail ospace */
193 free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
194 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
195 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
197 if (++mve_audio_bufhead == 64) /* next buffer */
198 mve_audio_bufhead = 0;
199 mve_audio_curbuf_curpos = 0;
202 //fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
205 if (len != 0 /* ospace remaining */
206 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
208 memcpy(stream, /* dest */
209 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */
212 mve_audio_curbuf_curpos += len; /* advance input */
213 stream += len; /* advance output (unnecessary) */
214 len -= len; /* advance output (unnecessary) */
216 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
218 free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
219 mve_audio_buffers[mve_audio_bufhead]=NULL;
220 mve_audio_buflens[mve_audio_bufhead]=0;
222 if (++mve_audio_bufhead == 64) /* next buffer */
223 mve_audio_bufhead = 0;
224 mve_audio_curbuf_curpos = 0;
228 //fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
232 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
245 flags = get_ushort(data + 2);
246 sample_rate = get_ushort(data + 4);
247 desired_buffer = get_int(data + 6);
249 stereo = (flags & 0x0001) ? 1 : 0;
250 bitsize = (flags & 0x0002) ? 1 : 0;
253 compressed = flags & 0x0004 ? 1 : 0;
258 mve_audio_compressed = compressed;
261 format = AUDIO_S16LSB;
266 fprintf(stderr, "creating audio buffers:\n");
267 fprintf(stderr, "sample rate = %d, stereo = %d, bitsize = %d, compressed = %d\n",
268 sample_rate, stereo, bitsize ? 16 : 8, compressed);
270 mve_audio_spec = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
271 mve_audio_spec->freq = sample_rate;
272 mve_audio_spec->format = format;
273 mve_audio_spec->channels = (stereo) ? 2 : 1;
274 mve_audio_spec->samples = 4096;
275 mve_audio_spec->callback = mve_audio_callback;
276 mve_audio_spec->userdata = NULL;
277 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
279 fprintf(stderr, " success\n");
280 mve_audio_canplay = 1;
284 fprintf(stderr, " failure : %s\n", SDL_GetError());
285 mve_audio_canplay = 0;
288 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
289 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
295 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
298 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
301 mve_audio_playing = 1;
307 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
310 static const int selected_chan=1;
313 if (mve_audio_canplay)
315 if (mve_audio_playing)
318 chan = get_ushort(data + 2);
319 nsamp = get_ushort(data + 4);
320 if (chan & selected_chan)
322 /* HACK: +4 mveaudio_uncompress adds 4 more bytes */
324 if (mve_audio_compressed) {
327 mve_audio_buflens[mve_audio_buftail] = nsamp;
328 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
329 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
334 mve_audio_buflens[mve_audio_buftail] = nsamp;
335 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
336 memcpy(mve_audio_buffers[mve_audio_buftail], data, nsamp);
339 mve_audio_buflens[mve_audio_buftail] = nsamp;
340 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
342 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
345 if (++mve_audio_buftail == 64)
346 mve_audio_buftail = 0;
348 if (mve_audio_buftail == mve_audio_bufhead)
349 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
352 if (mve_audio_playing)
360 /*************************
362 *************************/
363 int g_width, g_height;
364 void *g_vBackBuf1, *g_vBackBuf2;
367 static SDL_Surface *g_screen;
369 static int g_screenWidth, g_screenHeight;
370 static unsigned char g_palette[768];
371 static unsigned char *g_pCurMap=NULL;
372 static int g_nMapLength=0;
373 static int g_truecolor;
375 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
378 short count, truecolor;
380 h = get_short(data+2);
383 count = get_short(data+4);
389 truecolor = get_short(data+6);
397 /* TODO: * 4 causes crashes on some files */
398 g_vBackBuf1 = malloc(g_width * g_height * 8);
400 g_vBackBuf2 = (unsigned short *)g_vBackBuf1 + (g_width * g_height);
402 g_vBackBuf2 = (unsigned char *)g_vBackBuf1 + (g_width * g_height);
405 memset(g_vBackBuf1, 0, g_width * g_height * 4);
407 fprintf(stderr, "DEBUG: w,h=%d,%d count=%d, tc=%d\n", w, h, count, truecolor);
409 g_truecolor = truecolor;
415 static int do_sdl_events()
419 while (SDL_PollEvent(&event)) {
424 if (event.key.keysym.sym == SDLK_ESCAPE)
430 case SDL_MOUSEBUTTONDOWN:
432 if (event.button.button == SDL_BUTTON_LEFT) {
433 printf("GRID: %d,%d (pix:%d,%d)\n",
434 event.button.x / 16, event.button.y / 8,
435 event.button.x, event.button.y);
448 static unsigned short stab[65536];
449 static unsigned int itab[65536];
450 static int table_inited;
452 unsigned short *pixelbuf;
453 static void ConvertAndDraw()
457 unsigned short *pDests;
458 unsigned int *pDesti;
459 unsigned short *pSrcs;
460 unsigned char *pixels = (unsigned char *)g_vBackBuf1;
464 pSrcs = (unsigned short *)pixels;
467 if (table_inited == 0) {
472 for (i = 0; i < 65536; i++) {
473 r = (i & 0x7c00) >> 10;
474 g = (i & 0x03e0) >> 5;
475 b = (i & 0x001f) >> 0;
478 stab[i] |= (r << 10)&0x7c00;
479 stab[i] |= (g << 5)&0x03e0;
480 stab[i] |= (b << 0)&0x001f;
487 if (g_screenWidth > g_width) {
488 pDests += ((g_screenWidth - g_width) / 2) / 2;
490 if (g_screenHeight > g_height) {
491 pDests += ((g_screenHeight - g_height) / 2) * g_screenWidth;
494 for (y=0; y<g_height; y++) {
495 for (x = 0; x < g_width; x++) {
496 //pDests[x] = stab[*pSrcs];
497 pDests[x] = (1<<15)|*pSrcs;
501 pDests += g_screenWidth;
505 /* original slow 8 bit code */
507 unsigned char *pal = g_palette;
508 unsigned char *pDest;
509 unsigned char *pixels = g_vBackBuf1;
510 SDL_Surface *screenSprite, *initSprite;
514 initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, 8, 0, 0, 0, 0);
517 for(i = 0; i < 256; i++)
519 initSprite->format->palette->colors[i].r = (*pal++) << 2;
520 initSprite->format->palette->colors[i].g = (*pal++) << 2;
521 initSprite->format->palette->colors[i].b = (*pal++) << 2;
522 initSprite->format->palette->colors[i].unused = 0;
526 pDest = initSprite->pixels;
527 for (i=0; i<g_height; i++)
529 memcpy(pDest, pixels, g_width * (g_truecolor?2:1));
530 pixels += g_width* (g_truecolor?2:1);
531 pDest += initSprite->pitch;
534 screenSprite = SDL_DisplayFormat(initSprite);
535 SDL_FreeSurface(initSprite);
537 if (g_screenWidth > screenSprite->w) x = (g_screenWidth - screenSprite->w) >> 1;
539 if (g_screenHeight > screenSprite->h) y = (g_screenHeight - screenSprite->h) >> 1;
543 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
544 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
545 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
547 SDL_FreeSurface(screenSprite);
553 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
562 /* DDOI - This is probably really fricking slow */
563 int bitmap = bm_create (16, g_screenWidth, g_screenHeight, pixelbuf, 0);
564 gr_set_bitmap (bitmap);
569 os_poll (); /* DDOI - run event loop(s) */
571 if (key_check (KEY_ESC)) playing = 0;
576 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
579 width = get_short(data);
580 height = get_short(data+2);
582 g_screen = SDL_SetVideoMode(width, height, 16, SDL_ANYFORMAT|SDL_DOUBLEBUF);
584 // DDOI - Allocate RGB565 pixel buffer
585 pixelbuf = (unsigned short *)malloc (width * height * 2);
586 g_screenWidth = width;
587 g_screenHeight = height;
588 memset(g_palette, 0, 768);
592 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
595 start = get_short(data);
596 count = get_short(data+2);
597 memcpy(g_palette + 3*start, data+4, 3*count);
601 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
608 void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
610 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
612 short nFrameHot, nFrameCold;
613 short nXoffset, nYoffset;
614 short nXsize, nYsize;
615 unsigned short nFlags;
618 nFrameHot = get_short(data);
619 nFrameCold = get_short(data+2);
620 nXoffset = get_short(data+4);
621 nYoffset = get_short(data+6);
622 nXsize = get_short(data+8);
623 nYsize = get_short(data+10);
624 nFlags = get_ushort(data+12);
628 temp = (unsigned char *)g_vBackBuf1;
629 g_vBackBuf1 = g_vBackBuf2;
633 /* convert the frame */
635 decodeFrame16((unsigned char *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
638 decodeFrame8(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
645 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
651 void initializeMovie(MVESTREAM *mve)
655 for (i = 0; i < 32; i++) {
656 mve_set_handler(mve, i, default_seg_handler);
659 mve_set_handler(mve, 0x00, end_movie_handler);
660 mve_set_handler(mve, 0x01, end_chunk_handler);
661 mve_set_handler(mve, 0x02, create_timer_handler);
662 mve_set_handler(mve, 0x03, create_audiobuf_handler);
663 mve_set_handler(mve, 0x04, play_audio_handler);
664 mve_set_handler(mve, 0x05, create_videobuf_handler);
665 mve_set_handler(mve, 0x07, display_video_handler);
666 mve_set_handler(mve, 0x08, audio_data_handler);
667 mve_set_handler(mve, 0x09, audio_data_handler);
668 mve_set_handler(mve, 0x0a, init_video_handler);
669 mve_set_handler(mve, 0x0c, video_palette_handler);
670 mve_set_handler(mve, 0x0f, video_codemap_handler);
671 mve_set_handler(mve, 0x11, video_data_handler);
674 void playMovie(MVESTREAM *mve)
678 while (cont && playing)
680 cont = mve_play_next_chunk(mve);
681 if (micro_frame_delay && !init_timer)
691 void shutdownMovie(MVESTREAM *mve)