7 #include "mvelib.h" /* next buffer */
10 #include "mve_audio.h"
13 #define MIN(a,b) ((a)<(b)?(a):(b))
17 static int g_spdFactorNum=0;
18 static int g_spdFactorDenom=10;
20 void initializeMovie(MVESTREAM *mve);
21 void playMovie(MVESTREAM *mve);
22 void shutdownMovie(MVESTREAM *mve);
25 static int doPlay(const char *filename)
27 MVESTREAM *mve = mve_open(filename);
30 fprintf(stderr, "can't open MVE file '%s'\n", filename);
44 static short get_short(unsigned char *data)
47 value = data[0] | (data[1] << 8);
51 static unsigned short get_ushort(unsigned char *data)
54 value = data[0] | (data[1] << 8);
58 static int get_int(unsigned char *data)
61 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
65 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
67 /* fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor); */
71 /*************************
73 *************************/
74 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
79 /*************************
81 *************************/
86 static int micro_frame_delay=0;
87 static int timer_started=0;
88 static struct timeval timer_expire = {0, 0};
90 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
92 __extension__ long long temp;
93 micro_frame_delay = get_int(data) * (int)get_short(data+4);
94 if (g_spdFactorNum != 0)
96 temp = micro_frame_delay;
97 temp *= g_spdFactorNum;
98 temp /= g_spdFactorDenom;
99 micro_frame_delay = (int)temp;
105 static void timer_start(void)
108 gettimeofday(&timer_expire, NULL);
109 timer_expire.tv_usec += micro_frame_delay;
110 if (timer_expire.tv_usec > 1000000)
112 nsec = timer_expire.tv_usec / 1000000;
113 timer_expire.tv_sec += nsec;
114 timer_expire.tv_usec -= nsec*1000000;
119 static void do_timer_wait(void)
122 struct timespec ts, tsRem;
127 gettimeofday(&tv, NULL);
128 if (tv.tv_sec > timer_expire.tv_sec)
130 else if (tv.tv_sec == timer_expire.tv_sec && tv.tv_usec >= timer_expire.tv_usec)
133 ts.tv_sec = timer_expire.tv_sec - tv.tv_sec;
134 ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec);
137 ts.tv_nsec += 1000000000UL;
140 if (nanosleep(&ts, &tsRem) == -1 && errno == EINTR)
144 timer_expire.tv_usec += micro_frame_delay;
145 if (timer_expire.tv_usec > 1000000)
147 nsec = timer_expire.tv_usec / 1000000;
148 timer_expire.tv_sec += nsec;
149 timer_expire.tv_usec -= nsec*1000000;
153 /*************************
155 *************************/
156 static void mve_audio_callback(void *userdata, unsigned char *stream, int len);
157 static short *mve_audio_buffers[64];
158 static int mve_audio_buflens[64];
159 static int mve_audio_curbuf_curpos=0;
160 static int mve_audio_bufhead=0;
161 static int mve_audio_buftail=0;
162 static int mve_audio_playing=0;
163 static int mve_audio_canplay=0;
165 static SDL_AudioSpec *mve_audio_spec=NULL;
167 static int mve_audio_compressed = 0;
169 static void mve_audio_callback(void *userdata, unsigned char *stream, int len)
174 if (mve_audio_bufhead == mve_audio_buftail)
177 //fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
179 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
180 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
182 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
183 memcpy(stream, /* cur output position */
184 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead])+mve_audio_curbuf_curpos, /* cur input position */
185 length); /* cur input length */
188 stream += length; /* advance output */
189 len -= length; /* decrement avail ospace */
190 free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
191 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
192 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
194 if (++mve_audio_bufhead == 64) /* next buffer */
195 mve_audio_bufhead = 0;
196 mve_audio_curbuf_curpos = 0;
199 //fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
202 if (len != 0 /* ospace remaining */
203 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
205 memcpy(stream, /* dest */
206 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */
209 mve_audio_curbuf_curpos += len; /* advance input */
210 stream += len; /* advance output (unnecessary) */
211 len -= len; /* advance output (unnecessary) */
213 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
215 free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
216 mve_audio_buffers[mve_audio_bufhead]=NULL;
217 mve_audio_buflens[mve_audio_bufhead]=0;
219 if (++mve_audio_bufhead == 64) /* next buffer */
220 mve_audio_bufhead = 0;
221 mve_audio_curbuf_curpos = 0;
225 //fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
229 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
242 flags = get_ushort(data + 2);
243 sample_rate = get_ushort(data + 4);
244 desired_buffer = get_int(data + 6);
246 stereo = (flags & 0x0001) ? 1 : 0;
247 bitsize = (flags & 0x0002) ? 1 : 0;
250 compressed = flags & 0x0004 ? 1 : 0;
255 mve_audio_compressed = compressed;
258 format = AUDIO_S16LSB;
263 fprintf(stderr, "creating audio buffers:\n");
264 fprintf(stderr, "sample rate = %d, stereo = %d, bitsize = %d, compressed = %d\n",
265 sample_rate, stereo, bitsize ? 16 : 8, compressed);
267 mve_audio_spec = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
268 mve_audio_spec->freq = sample_rate;
269 mve_audio_spec->format = format;
270 mve_audio_spec->channels = (stereo) ? 2 : 1;
271 mve_audio_spec->samples = 4096;
272 mve_audio_spec->callback = mve_audio_callback;
273 mve_audio_spec->userdata = NULL;
274 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
276 fprintf(stderr, " success\n");
277 mve_audio_canplay = 1;
281 fprintf(stderr, " failure : %s\n", SDL_GetError());
282 mve_audio_canplay = 0;
285 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
286 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
292 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)
307 static const int selected_chan=1;
310 if (mve_audio_canplay)
312 if (mve_audio_playing)
315 chan = get_ushort(data + 2);
316 nsamp = get_ushort(data + 4);
317 if (chan & selected_chan)
319 /* HACK: +4 mveaudio_uncompress adds 4 more bytes */
321 if (mve_audio_compressed) {
324 mve_audio_buflens[mve_audio_buftail] = nsamp;
325 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
326 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
331 mve_audio_buflens[mve_audio_buftail] = nsamp;
332 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
333 memcpy(mve_audio_buffers[mve_audio_buftail], data, nsamp);
336 mve_audio_buflens[mve_audio_buftail] = nsamp;
337 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
339 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
342 if (++mve_audio_buftail == 64)
343 mve_audio_buftail = 0;
345 if (mve_audio_buftail == mve_audio_bufhead)
346 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
349 if (mve_audio_playing)
357 /*************************
359 *************************/
360 int g_width, g_height;
361 void *g_vBackBuf1, *g_vBackBuf2;
364 static SDL_Surface *g_screen;
366 static int g_screenWidth, g_screenHeight;
367 static unsigned char g_palette[768];
368 static unsigned char *g_pCurMap=NULL;
369 static int g_nMapLength=0;
370 static int g_truecolor;
372 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
375 short count, truecolor;
377 h = get_short(data+2);
380 count = get_short(data+4);
386 truecolor = get_short(data+6);
394 /* TODO: * 4 causes crashes on some files */
395 g_vBackBuf1 = malloc(g_width * g_height * 8);
397 g_vBackBuf2 = (unsigned short *)g_vBackBuf1 + (g_width * g_height);
399 g_vBackBuf2 = (unsigned char *)g_vBackBuf1 + (g_width * g_height);
402 memset(g_vBackBuf1, 0, g_width * g_height * 4);
404 fprintf(stderr, "DEBUG: w,h=%d,%d count=%d, tc=%d\n", w, h, count, truecolor);
406 g_truecolor = truecolor;
412 static int do_sdl_events()
416 while (SDL_PollEvent(&event)) {
421 if (event.key.keysym.sym == SDLK_ESCAPE)
427 case SDL_MOUSEBUTTONDOWN:
429 if (event.button.button == SDL_BUTTON_LEFT) {
430 printf("GRID: %d,%d (pix:%d,%d)\n",
431 event.button.x / 16, event.button.y / 8,
432 event.button.x, event.button.y);
445 static unsigned short stab[65536];
446 static unsigned int itab[65536];
447 static int table_inited;
449 unsigned short *pixelbuf;
450 static void ConvertAndDraw()
454 unsigned short *pDests;
455 unsigned int *pDesti;
456 unsigned short *pSrcs;
457 unsigned char *pixels = (unsigned char *)g_vBackBuf1;
461 pSrcs = (unsigned short *)pixels;
464 if (table_inited == 0) {
469 for (i = 0; i < 65536; i++) {
470 r = (i & 0x7c00) >> 10;
471 g = (i & 0x03e0) >> 5;
472 b = (i & 0x001f) >> 0;
475 stab[i] |= (r << 10)&0x7c00;
476 stab[i] |= (g << 5)&0x03e0;
477 stab[i] |= (b << 0)&0x001f;
484 if (g_screenWidth > g_width) {
485 pDests += ((g_screenWidth - g_width) / 2) / 2;
487 if (g_screenHeight > g_height) {
488 pDests += ((g_screenHeight - g_height) / 2) * g_screenWidth;
491 for (y=0; y<g_height; y++) {
492 for (x = 0; x < g_width; x++) {
493 //pDests[x] = stab[*pSrcs];
494 pDests[x] = (1<<15)|*pSrcs;
498 pDests += g_screenWidth;
502 /* original slow 8 bit code */
504 unsigned char *pal = g_palette;
505 unsigned char *pDest;
506 unsigned char *pixels = g_vBackBuf1;
507 SDL_Surface *screenSprite, *initSprite;
511 initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, 8, 0, 0, 0, 0);
514 for(i = 0; i < 256; i++)
516 initSprite->format->palette->colors[i].r = (*pal++) << 2;
517 initSprite->format->palette->colors[i].g = (*pal++) << 2;
518 initSprite->format->palette->colors[i].b = (*pal++) << 2;
519 initSprite->format->palette->colors[i].unused = 0;
523 pDest = initSprite->pixels;
524 for (i=0; i<g_height; i++)
526 memcpy(pDest, pixels, g_width * (g_truecolor?2:1));
527 pixels += g_width* (g_truecolor?2:1);
528 pDest += initSprite->pitch;
531 screenSprite = SDL_DisplayFormat(initSprite);
532 SDL_FreeSurface(initSprite);
534 if (g_screenWidth > screenSprite->w) x = (g_screenWidth - screenSprite->w) >> 1;
536 if (g_screenHeight > screenSprite->h) y = (g_screenHeight - screenSprite->h) >> 1;
540 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
541 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
542 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
544 SDL_FreeSurface(screenSprite);
550 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
559 /* DDOI - This is probably really fricking slow */
560 int bitmap = bm_create (16, g_screenWidth, g_screenHeight, pixelbuf, 0);
561 gr_set_bitmap (bitmap);
569 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
572 width = get_short(data);
573 height = get_short(data+2);
575 g_screen = SDL_SetVideoMode(width, height, 16, SDL_ANYFORMAT|SDL_DOUBLEBUF);
577 // DDOI - Allocate RGB565 pixel buffer
578 pixelbuf = (unsigned short *)malloc (width * height * 2);
579 g_screenWidth = width;
580 g_screenHeight = height;
581 memset(g_palette, 0, 768);
585 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
588 start = get_short(data);
589 count = get_short(data+2);
590 memcpy(g_palette + 3*start, data+4, 3*count);
594 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
601 void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
603 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
605 short nFrameHot, nFrameCold;
606 short nXoffset, nYoffset;
607 short nXsize, nYsize;
608 unsigned short nFlags;
611 nFrameHot = get_short(data);
612 nFrameCold = get_short(data+2);
613 nXoffset = get_short(data+4);
614 nYoffset = get_short(data+6);
615 nXsize = get_short(data+8);
616 nYsize = get_short(data+10);
617 nFlags = get_ushort(data+12);
621 temp = (unsigned char *)g_vBackBuf1;
622 g_vBackBuf1 = g_vBackBuf2;
626 /* convert the frame */
628 decodeFrame16((unsigned char *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
631 decodeFrame8(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
638 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
644 void initializeMovie(MVESTREAM *mve)
648 for (i = 0; i < 32; i++) {
649 mve_set_handler(mve, i, default_seg_handler);
652 mve_set_handler(mve, 0x00, end_movie_handler);
653 mve_set_handler(mve, 0x01, end_chunk_handler);
654 mve_set_handler(mve, 0x02, create_timer_handler);
655 mve_set_handler(mve, 0x03, create_audiobuf_handler);
656 mve_set_handler(mve, 0x04, play_audio_handler);
657 mve_set_handler(mve, 0x05, create_videobuf_handler);
658 mve_set_handler(mve, 0x07, display_video_handler);
659 mve_set_handler(mve, 0x08, audio_data_handler);
660 mve_set_handler(mve, 0x09, audio_data_handler);
661 mve_set_handler(mve, 0x0a, init_video_handler);
662 mve_set_handler(mve, 0x0c, video_palette_handler);
663 mve_set_handler(mve, 0x0f, video_codemap_handler);
664 mve_set_handler(mve, 0x11, video_data_handler);
667 void playMovie(MVESTREAM *mve)
673 cont = mve_play_next_chunk(mve);
674 if (micro_frame_delay && !init_timer)
684 void shutdownMovie(MVESTREAM *mve)