1 /* $Id: mveplay.c,v 1.11.2.1 2003/06/06 22:12:55 btb Exp $ */
2 #ifdef HAVE_CONFIG_H
3 #include <conf.h>
4 #endif
5
6 #ifndef __MSDOS__
7 #define AUDIO
8 #endif
9 //#define DEBUG
10
11 #include <string.h>
12 #include <errno.h>
13 #include <time.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19
20 #if defined(STANDALONE) || defined(AUDIO)
21 #include <SDL.h>
22 #endif
23
24 #include "mvelib.h"
25 #include "mve_audio.h"
26
27 #include "decoders.h"
28
29 #ifndef STANDALONE
30 #include "libmve.h"
31 #include "u_mem.h"
32 #include "gr.h"
33 #include "palette.h"
34 #endif
35
36 #ifdef STANDALONE
37 #define d_malloc(size) malloc(size)
38 #define d_free(ptr) free(ptr)
39 #endif
40
41 #ifndef MIN
42 #define MIN(a,b) ((a)<(b)?(a):(b))
43 #endif
44
45 #define MVE_OPCODE_ENDOFSTREAM 0x00
46 #define MVE_OPCODE_ENDOFCHUNK 0x01
47 #define MVE_OPCODE_CREATETIMER 0x02
48 #define MVE_OPCODE_INITAUDIOBUFFERS 0x03
49 #define MVE_OPCODE_STARTSTOPAUDIO 0x04
50 #define MVE_OPCODE_INITVIDEOBUFFERS 0x05
51
52 #define MVE_OPCODE_DISPLAYVIDEO 0x07
53 #define MVE_OPCODE_AUDIOFRAMEDATA 0x08
54 #define MVE_OPCODE_AUDIOFRAMESILENCE 0x09
55 #define MVE_OPCODE_INITVIDEOMODE 0x0A
56
57 #define MVE_OPCODE_SETPALETTE 0x0C
58 #define MVE_OPCODE_SETPALETTECOMPRESSED 0x0D
59
60 #define MVE_OPCODE_SETDECODINGMAP 0x0F
61
62 #define MVE_OPCODE_VIDEODATA 0x11
63
64 #define MVE_AUDIO_FLAGS_STEREO 1
65 #define MVE_AUDIO_FLAGS_16BIT 2
66 #define MVE_AUDIO_FLAGS_COMPRESSED 4
67
68 int g_spdFactorNum=0;
69 static int g_spdFactorDenom=10;
70 static int g_frameUpdated = 0;
71
72 #ifdef STANDALONE
73 static int playing = 1;
74 int g_sdlVidFlags = SDL_ANYFORMAT | SDL_DOUBLEBUF;
75 int g_loop = 0;
76
77 void initializeMovie(MVESTREAM *mve);
78 void playMovie(MVESTREAM *mve);
79 void shutdownMovie(MVESTREAM *mve);
80 #endif
81
get_short(unsigned char * data)82 static short get_short(unsigned char *data)
83 {
84 short value;
85 value = data[0] | (data[1] << 8);
86 return value;
87 }
88
get_ushort(unsigned char * data)89 static unsigned short get_ushort(unsigned char *data)
90 {
91 unsigned short value;
92 value = data[0] | (data[1] << 8);
93 return value;
94 }
95
get_int(unsigned char * data)96 static int get_int(unsigned char *data)
97 {
98 int value;
99 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
100 return value;
101 }
102
103 static unsigned int unhandled_chunks[32*256];
104
default_seg_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)105 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
106 {
107 unhandled_chunks[major<<8|minor]++;
108 //fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
109 return 1;
110 }
111
112
113 /*************************
114 * general handlers
115 *************************/
end_movie_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)116 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
117 {
118 return 0;
119 }
120
121 /*************************
122 * timer handlers
123 *************************/
124
125 #if !HAVE_STRUCT_TIMEVAL
126 struct timeval {
127 long tv_sec;
128 long tv_usec;
129 };
130 #endif
131
132 /*
133 * timer variables
134 */
135 static int timer_created = 0;
136 static int micro_frame_delay=0;
137 static int timer_started=0;
138 static struct timeval timer_expire = {0, 0};
139
140 #if !HAVE_STRUCT_TIMESPEC
141 struct timespec
142 {
143 long int tv_sec; /* Seconds. */
144 long int tv_nsec; /* Nanoseconds. */
145 };
146 #endif
147
148 #if defined(HAVE_DECL_NANOSLEEP) && !HAVE_DECL_NANOSLEEP
149 int nanosleep(struct timespec *ts, void *rem);
150 #endif
151
152 #ifdef __WIN32
153 #include <sys/timeb.h>
154
gettimeofday(struct timeval * tv,void * tz)155 int gettimeofday(struct timeval *tv, void *tz)
156 {
157 static int counter = 0;
158 struct timeb tm;
159
160 counter++; /* to avoid collisions */
161 ftime(&tm);
162 tv->tv_sec = tm.time;
163 tv->tv_usec = (tm.millitm * 1000) + counter;
164
165 return 0;
166 }
167
nanosleep(struct timespec * ts,void * rem)168 int nanosleep(struct timespec *ts, void *rem)
169 {
170 _sleep(ts->tv_sec * 1000 + ts->tv_nsec / 1000000);
171
172 return 0;
173 }
174 #endif
175
create_timer_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)176 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
177 {
178 __extension__ long long temp;
179
180 if (timer_created)
181 return 1;
182 else
183 timer_created = 1;
184
185 micro_frame_delay = get_int(data) * (int)get_short(data+4);
186 if (g_spdFactorNum != 0)
187 {
188 temp = micro_frame_delay;
189 temp *= g_spdFactorNum;
190 temp /= g_spdFactorDenom;
191 micro_frame_delay = (int)temp;
192 }
193
194 return 1;
195 }
196
timer_stop(void)197 static void timer_stop(void)
198 {
199 timer_expire.tv_sec = 0;
200 timer_expire.tv_usec = 0;
201 timer_started = 0;
202 }
203
timer_start(void)204 static void timer_start(void)
205 {
206 int nsec=0;
207 gettimeofday(&timer_expire, NULL);
208 timer_expire.tv_usec += micro_frame_delay;
209 if (timer_expire.tv_usec > 1000000)
210 {
211 nsec = timer_expire.tv_usec / 1000000;
212 timer_expire.tv_sec += nsec;
213 timer_expire.tv_usec -= nsec*1000000;
214 }
215 timer_started=1;
216 }
217
do_timer_wait(void)218 static void do_timer_wait(void)
219 {
220 int nsec=0;
221 struct timespec ts;
222 struct timeval tv;
223 if (! timer_started)
224 return;
225
226 gettimeofday(&tv, NULL);
227 if (tv.tv_sec > timer_expire.tv_sec)
228 goto end;
229 else if (tv.tv_sec == timer_expire.tv_sec && tv.tv_usec >= timer_expire.tv_usec)
230 goto end;
231
232 ts.tv_sec = timer_expire.tv_sec - tv.tv_sec;
233 ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec);
234 if (ts.tv_nsec < 0)
235 {
236 ts.tv_nsec += 1000000000UL;
237 --ts.tv_sec;
238 }
239 #ifdef __CYGWIN__
240 usleep(ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
241 #else
242 if (nanosleep(&ts, NULL) == -1 && errno == EINTR)
243 exit(1);
244 #endif
245
246 end:
247 timer_expire.tv_usec += micro_frame_delay;
248 if (timer_expire.tv_usec > 1000000)
249 {
250 nsec = timer_expire.tv_usec / 1000000;
251 timer_expire.tv_sec += nsec;
252 timer_expire.tv_usec -= nsec*1000000;
253 }
254 }
255
256 /*************************
257 * audio handlers
258 *************************/
259 #ifdef AUDIO
260 #define TOTAL_AUDIO_BUFFERS 64
261
262 static int audiobuf_created = 0;
263 static void mve_audio_callback(void *userdata, unsigned char *stream, int len);
264 static short *mve_audio_buffers[TOTAL_AUDIO_BUFFERS];
265 static int mve_audio_buflens[TOTAL_AUDIO_BUFFERS];
266 static int mve_audio_curbuf_curpos=0;
267 static int mve_audio_bufhead=0;
268 static int mve_audio_buftail=0;
269 static int mve_audio_playing=0;
270 static int mve_audio_canplay=0;
271 static int mve_audio_compressed=0;
272 static int mve_audio_enabled = 1;
273 static SDL_AudioSpec *mve_audio_spec=NULL;
274
mve_audio_callback(void * userdata,unsigned char * stream,int len)275 static void mve_audio_callback(void *userdata, unsigned char *stream, int len)
276 {
277 int total=0;
278 int length;
279 if (mve_audio_bufhead == mve_audio_buftail)
280 return /* 0 */;
281
282 //fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
283
284 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
285 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
286 {
287 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
288 memcpy(stream, /* cur output position */
289 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead])+mve_audio_curbuf_curpos, /* cur input position */
290 length); /* cur input length */
291
292 total += length;
293 stream += length; /* advance output */
294 len -= length; /* decrement avail ospace */
295 d_free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
296 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
297 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
298
299 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
300 mve_audio_bufhead = 0;
301 mve_audio_curbuf_curpos = 0;
302 }
303
304 //fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
305 /* return total; */
306
307 if (len != 0 /* ospace remaining */
308 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
309 {
310 memcpy(stream, /* dest */
311 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */
312 len); /* length */
313
314 mve_audio_curbuf_curpos += len; /* advance input */
315 stream += len; /* advance output (unnecessary) */
316 len -= len; /* advance output (unnecessary) */
317
318 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
319 {
320 d_free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
321 mve_audio_buffers[mve_audio_bufhead]=NULL;
322 mve_audio_buflens[mve_audio_bufhead]=0;
323
324 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
325 mve_audio_bufhead = 0;
326 mve_audio_curbuf_curpos = 0;
327 }
328 }
329
330 //fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
331 }
332 #endif
333
create_audiobuf_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)334 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
335 {
336 #ifdef AUDIO
337 int flags;
338 int sample_rate;
339 int desired_buffer;
340
341 int stereo;
342 int bitsize;
343 int compressed;
344
345 int format;
346
347 if (!mve_audio_enabled)
348 return 1;
349
350 if (audiobuf_created)
351 return 1;
352 else
353 audiobuf_created = 1;
354
355 flags = get_ushort(data + 2);
356 sample_rate = get_ushort(data + 4);
357 desired_buffer = get_int(data + 6);
358
359 stereo = (flags & MVE_AUDIO_FLAGS_STEREO) ? 1 : 0;
360 bitsize = (flags & MVE_AUDIO_FLAGS_16BIT) ? 1 : 0;
361
362 if (minor > 0) {
363 compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED ? 1 : 0;
364 } else {
365 compressed = 0;
366 }
367
368 mve_audio_compressed = compressed;
369
370 if (bitsize == 1) {
371 #ifdef WORDS_BIGENDIAN
372 format = AUDIO_S16MSB;
373 #else
374 format = AUDIO_S16LSB;
375 #endif
376 } else {
377 format = AUDIO_U8;
378 }
379
380 fprintf(stderr, "creating audio buffers:\n");
381 fprintf(stderr, "sample rate = %d, stereo = %d, bitsize = %d, compressed = %d\n",
382 sample_rate, stereo, bitsize ? 16 : 8, compressed);
383
384 mve_audio_spec = (SDL_AudioSpec *)d_malloc(sizeof(SDL_AudioSpec));
385 mve_audio_spec->freq = sample_rate;
386 mve_audio_spec->format = format;
387 mve_audio_spec->channels = (stereo) ? 2 : 1;
388 mve_audio_spec->samples = 4096;
389 mve_audio_spec->callback = mve_audio_callback;
390 mve_audio_spec->userdata = NULL;
391 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
392 {
393 fprintf(stderr, " success\n");
394 mve_audio_canplay = 1;
395 }
396 else
397 {
398 fprintf(stderr, " failure : %s\n", SDL_GetError());
399 mve_audio_canplay = 0;
400 }
401
402 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
403 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
404 #endif
405
406 return 1;
407 }
408
play_audio_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)409 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
410 {
411 #ifdef AUDIO
412 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
413 {
414 SDL_PauseAudio(0);
415 mve_audio_playing = 1;
416 }
417 #endif
418 return 1;
419 }
420
audio_data_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)421 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
422 {
423 #ifdef AUDIO
424 static const int selected_chan=1;
425 int chan;
426 int nsamp;
427 if (mve_audio_canplay)
428 {
429 if (mve_audio_playing)
430 SDL_LockAudio();
431
432 chan = get_ushort(data + 2);
433 nsamp = get_ushort(data + 4);
434 if (chan & selected_chan)
435 {
436 /* HACK: +4 mveaudio_uncompress adds 4 more bytes */
437 if (major == MVE_OPCODE_AUDIOFRAMEDATA) {
438 if (mve_audio_compressed) {
439 nsamp += 4;
440
441 mve_audio_buflens[mve_audio_buftail] = nsamp;
442 mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp);
443 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
444 } else {
445 nsamp -= 8;
446 data += 8;
447
448 mve_audio_buflens[mve_audio_buftail] = nsamp;
449 mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp);
450 memcpy(mve_audio_buffers[mve_audio_buftail], data, nsamp);
451 }
452 } else {
453 mve_audio_buflens[mve_audio_buftail] = nsamp;
454 mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp);
455
456 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
457 }
458
459 if (++mve_audio_buftail == TOTAL_AUDIO_BUFFERS)
460 mve_audio_buftail = 0;
461
462 if (mve_audio_buftail == mve_audio_bufhead)
463 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
464 }
465
466 if (mve_audio_playing)
467 SDL_UnlockAudio();
468 }
469 #endif
470
471 return 1;
472 }
473
474 /*************************
475 * video handlers
476 *************************/
477 static int videobuf_created = 0;
478 static int video_initialized = 0;
479 int g_width, g_height;
480 void *g_vBuffers = NULL, *g_vBackBuf1, *g_vBackBuf2;
481
482 #ifdef STANDALONE
483 static SDL_Surface *g_screen;
484 #else
485 static int g_destX, g_destY;
486 #endif
487 static int g_screenWidth, g_screenHeight;
488 static unsigned char g_palette[768];
489 static unsigned char *g_pCurMap=NULL;
490 static int g_nMapLength=0;
491 static int g_truecolor;
492
create_videobuf_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)493 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
494 {
495 short w, h;
496 short count, truecolor;
497
498 if (videobuf_created)
499 return 1;
500 else
501 videobuf_created = 1;
502
503 w = get_short(data);
504 h = get_short(data+2);
505
506 if (minor > 0) {
507 count = get_short(data+4);
508 } else {
509 count = 1;
510 }
511
512 if (minor > 1) {
513 truecolor = get_short(data+6);
514 } else {
515 truecolor = 0;
516 }
517
518 g_width = w << 3;
519 g_height = h << 3;
520
521 /* TODO: * 4 causes crashes on some files */
522 g_vBackBuf1 = g_vBuffers = d_malloc(g_width * g_height * 8);
523 if (truecolor) {
524 g_vBackBuf2 = (unsigned short *)g_vBackBuf1 + (g_width * g_height);
525 } else {
526 g_vBackBuf2 = (unsigned char *)g_vBackBuf1 + (g_width * g_height);
527 }
528
529 memset(g_vBackBuf1, 0, g_width * g_height * 4);
530
531 #ifdef DEBUG
532 fprintf(stderr, "DEBUG: w,h=%d,%d count=%d, tc=%d\n", w, h, count, truecolor);
533 #endif
534
535 g_truecolor = truecolor;
536
537 return 1;
538 }
539
540 #ifdef STANDALONE
do_sdl_events()541 static int do_sdl_events()
542 {
543 SDL_Event event;
544 int retr = 0;
545 while (SDL_PollEvent(&event)) {
546 switch(event.type) {
547 case SDL_QUIT:
548 playing=0;
549 break;
550 case SDL_KEYDOWN:
551 if (event.key.keysym.sym == SDLK_ESCAPE)
552 playing=0;
553 break;
554 case SDL_KEYUP:
555 retr = 1;
556 break;
557 case SDL_MOUSEBUTTONDOWN:
558 /*
559 if (event.button.button == SDL_BUTTON_LEFT) {
560 printf("GRID: %d,%d (pix:%d,%d)\n",
561 event.button.x / 16, event.button.y / 8,
562 event.button.x, event.button.y);
563 }
564 */
565 break;
566 default:
567 break;
568 }
569 }
570
571 return retr;
572 }
573
ConvertAndDraw()574 static void ConvertAndDraw()
575 {
576 int i;
577 unsigned char *pal = g_palette;
578 unsigned char *pDest;
579 unsigned char *pixels = g_vBackBuf1;
580 SDL_Surface *screenSprite, *initSprite;
581 SDL_Rect renderArea;
582 int x, y;
583
584 initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, g_truecolor?16:8, 0x7C00, 0x03E0, 0x001F, 0);
585
586 if (!g_truecolor) {
587 for(i = 0; i < 256; i++) {
588 initSprite->format->palette->colors[i].r = (*pal++) << 2;
589 initSprite->format->palette->colors[i].g = (*pal++) << 2;
590 initSprite->format->palette->colors[i].b = (*pal++) << 2;
591 initSprite->format->palette->colors[i].unused = 0;
592 }
593 }
594
595 pDest = initSprite->pixels;
596
597 if (0 /*g_truecolor*/) {
598
599 unsigned short *pSrcs, *pDests;
600
601 pSrcs = (unsigned short *)pixels;
602 pDests = (unsigned short *)pDest;
603
604 for (y=0; y<g_height; y++) {
605 for (x = 0; x < g_width; x++) {
606 pDests[x] = (1<<15)|*pSrcs;
607 pSrcs++;
608 }
609 pDests += g_screenWidth;
610 }
611
612 } else {
613
614 for (i=0; i<g_height; i++) {
615 memcpy(pDest, pixels, g_width * (g_truecolor?2:1));
616 pixels += g_width* (g_truecolor?2:1);
617 pDest += initSprite->pitch;
618 }
619 }
620
621 screenSprite = SDL_DisplayFormat(initSprite);
622 SDL_FreeSurface(initSprite);
623
624 if (g_screenWidth > screenSprite->w)
625 x = (g_screenWidth - screenSprite->w) >> 1;
626 else
627 x=0;
628 if (g_screenHeight > screenSprite->h)
629 y = (g_screenHeight - screenSprite->h) >> 1;
630 else
631 y=0;
632 renderArea.x = x;
633 renderArea.y = y;
634 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
635 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
636 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
637
638 SDL_FreeSurface(screenSprite);
639 }
640 #endif
641
display_video_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)642 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
643 {
644 #ifdef STANDALONE
645 ConvertAndDraw();
646
647 SDL_Flip(g_screen);
648
649 do_sdl_events();
650 #else
651 grs_bitmap *bitmap;
652
653 bitmap = gr_create_bitmap_raw(g_width, g_height, g_vBackBuf1);
654
655 if (g_destX == -1) // center it
656 g_destX = (g_screenWidth - g_width) >> 1;
657 if (g_destY == -1) // center it
658 g_destY = (g_screenHeight - g_height) >> 1;
659
660 gr_palette_load(g_palette);
661
662 gr_bitmap(g_destX, g_destY, bitmap);
663
664 gr_free_sub_bitmap(bitmap);
665 #endif
666 g_frameUpdated = 1;
667
668 return 1;
669 }
670
init_video_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)671 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
672 {
673 short width, height;
674
675 if (video_initialized)
676 return 1;
677 else
678 video_initialized = 1;
679
680 width = get_short(data);
681 height = get_short(data+2);
682 #ifdef STANDALONE
683 g_screen = SDL_SetVideoMode(width, height, 16, g_sdlVidFlags);
684 #endif
685 g_screenWidth = width;
686 g_screenHeight = height;
687 memset(g_palette, 0, 765);
688 // 255 needs to default to white, for subtitles, etc
689 memset(g_palette + 765, 63, 3);
690
691 return 1;
692 }
693
video_palette_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)694 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
695 {
696 short start, count;
697 start = get_short(data);
698 count = get_short(data+2);
699 memcpy(g_palette + 3*start, data+4, 3*count);
700
701 return 1;
702 }
703
video_codemap_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)704 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
705 {
706 g_pCurMap = data;
707 g_nMapLength = len;
708 return 1;
709 }
710
video_data_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)711 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
712 {
713 short nFrameHot, nFrameCold;
714 short nXoffset, nYoffset;
715 short nXsize, nYsize;
716 unsigned short nFlags;
717 unsigned char *temp;
718
719 nFrameHot = get_short(data);
720 nFrameCold = get_short(data+2);
721 nXoffset = get_short(data+4);
722 nYoffset = get_short(data+6);
723 nXsize = get_short(data+8);
724 nYsize = get_short(data+10);
725 nFlags = get_ushort(data+12);
726
727 if (nFlags & 1)
728 {
729 temp = (unsigned char *)g_vBackBuf1;
730 g_vBackBuf1 = g_vBackBuf2;
731 g_vBackBuf2 = temp;
732 }
733
734 /* convert the frame */
735 if (g_truecolor) {
736 decodeFrame16((unsigned char *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
737 } else {
738 decodeFrame8(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
739 }
740
741 return 1;
742 }
743
end_chunk_handler(unsigned char major,unsigned char minor,unsigned char * data,int len,void * context)744 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
745 {
746 g_pCurMap=NULL;
747 return 1;
748 }
749
750
751 #ifdef STANDALONE
initializeMovie(MVESTREAM * mve)752 void initializeMovie(MVESTREAM *mve)
753 {
754 int i;
755
756 for (i = 0; i < 32; i++)
757 mve_set_handler(mve, i, default_seg_handler);
758
759 memset(unhandled_chunks, 0, 32*256);
760
761 mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler);
762 mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler);
763 mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler);
764 mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler);
765 mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler);
766 mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler);
767
768 mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler);
769 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler);
770 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler);
771 mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler);
772
773 mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler);
774 mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, video_palette_handler);
775 mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler);
776
777 mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler);
778 }
779
playMovie(MVESTREAM * mve)780 void playMovie(MVESTREAM *mve)
781 {
782 int init_timer=0;
783 int cont=1;
784
785 mve_audio_enabled = 1;
786
787 while (cont && playing)
788 {
789 cont = mve_play_next_chunk(mve);
790 if (micro_frame_delay && !init_timer)
791 {
792 timer_start();
793 init_timer = 1;
794 }
795
796 do_timer_wait();
797
798 if (g_loop && !cont) {
799 mve_reset(mve);
800 cont = 1;
801 }
802 }
803 }
804
shutdownMovie(MVESTREAM * mve)805 void shutdownMovie(MVESTREAM *mve)
806 {
807 #ifdef DEBUG
808 int i;
809 #endif
810
811 timer_stop();
812
813 #ifdef DEBUG
814 for (i = 0; i < 32*256; i++) {
815 if (unhandled_chunks[i]) {
816 fprintf(stderr, "unhandled chunks of type %02x/%02x: %d\n", i>>8, i&0xFF, unhandled_chunks[i]);
817 }
818 }
819 #endif
820 }
821
822 #else
823 static MVESTREAM *mve = NULL;
824
MVE_rmPrepMovie(int filehandle,int x,int y,int track)825 int MVE_rmPrepMovie(int filehandle, int x, int y, int track)
826 {
827 int i;
828
829 if (mve) {
830 mve_reset(mve);
831 return 0;
832 }
833
834 mve = mve_open_filehandle(filehandle);
835
836 if (!mve)
837 return 1;
838
839 g_destX = x;
840 g_destY = y;
841
842 for (i = 0; i < 32; i++)
843 mve_set_handler(mve, i, default_seg_handler);
844
845 mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler);
846 mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler);
847 mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler);
848 mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler);
849 mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler);
850 mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler);
851
852 mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler);
853 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler);
854 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler);
855 mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler);
856
857 mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler);
858 mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, default_seg_handler);
859
860 mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler);
861
862 mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler);
863
864 return 0;
865 }
866
MVE_rmStepMovie()867 int MVE_rmStepMovie()
868 {
869 static int init_timer=0;
870 int cont=1;
871
872 if (!timer_started)
873 timer_start();
874
875 while (cont && !g_frameUpdated) // make a "step" be a frame, not a chunk...
876 cont = mve_play_next_chunk(mve);
877 g_frameUpdated = 0;
878
879 if (micro_frame_delay && !init_timer) {
880 timer_start();
881 init_timer = 1;
882 }
883
884 do_timer_wait();
885
886 if (cont)
887 return 0;
888 else
889 return MVE_ERR_EOF;
890 }
891
MVE_rmEndMovie()892 void MVE_rmEndMovie()
893 {
894 #ifdef AUDIO
895 int i;
896 #endif
897
898 timer_stop();
899 timer_created = 0;
900
901 #ifdef AUDIO
902 if (mve_audio_canplay) {
903 // only close audio if we opened it
904 SDL_CloseAudio();
905 mve_audio_canplay = 0;
906 }
907 for (i = 0; i < TOTAL_AUDIO_BUFFERS; i++)
908 if (mve_audio_buffers[i] != NULL)
909 d_free(mve_audio_buffers[i]);
910 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
911 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
912 mve_audio_curbuf_curpos=0;
913 mve_audio_bufhead=0;
914 mve_audio_buftail=0;
915 mve_audio_playing=0;
916 mve_audio_canplay=0;
917 mve_audio_compressed=0;
918 if (mve_audio_spec)
919 d_free(mve_audio_spec);
920 mve_audio_spec=NULL;
921 audiobuf_created = 0;
922 #endif
923
924 d_free(g_vBuffers);
925 g_vBuffers = NULL;
926 g_pCurMap=NULL;
927 g_nMapLength=0;
928 videobuf_created = 0;
929 video_initialized = 0;
930
931 mve_close_filehandle(mve);
932 mve = NULL;
933 }
934
935
MVE_rmHoldMovie()936 void MVE_rmHoldMovie()
937 {
938 timer_started = 0;
939 }
940
941
MVE_sndInit(int x)942 void MVE_sndInit(int x)
943 {
944 #ifdef AUDIO
945 if (x == -1)
946 mve_audio_enabled = 0;
947 else
948 mve_audio_enabled = 1;
949 #endif
950 }
951
952 #endif
953