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