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