]> icculus.org git repositories - btb/d2x.git/blob - libmve/mve_main.c
add -nosound option to mveplayer so it can play robot movies without segfaulting
[btb/d2x.git] / libmve / mve_main.c
1 /* $Id: mve_main.c,v 1.8 2004-06-01 07:49:07 btb Exp $ */
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <string.h>
7
8 #ifdef _WIN32
9 # include <windows.h>
10 #endif
11
12 #ifdef _WIN32_WCE // should really be checking for "Pocket PC" somehow
13 # define LANDSCAPE
14 #endif
15
16 #include <SDL.h>
17
18 #include "libmve.h"
19
20 static SDL_Surface *g_screen;
21 #ifdef LANDSCAPE
22 static SDL_Surface *real_screen;
23 #endif
24 static unsigned char g_palette[768];
25 static int g_truecolor;
26 static int track;
27
28 static int doPlay(const char *filename);
29
30 static void usage(void)
31 {
32         fprintf(stderr, "usage: mveplay filename\n");
33         exit(1);
34 }
35
36 int main(int c, char **v)
37 {
38         if (c < 2)
39                 usage();
40
41         if (!strcmp(v[1], "-nosound")) {
42                 track = 0;
43                 c--;
44                 v++;
45         } else
46                 track = 1;
47
48         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
49         {
50                 fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
51                 exit(1);
52         }
53         atexit(SDL_Quit);
54
55         return doPlay(v[1]);
56 }
57
58
59 #ifdef LANDSCAPE
60 /* Create a new rotated surface for drawing */
61 SDL_Surface *CreateRotatedSurface(SDL_Surface *s)
62 {
63     return(SDL_CreateRGBSurface(s->flags, s->h, s->w,
64     s->format->BitsPerPixel,
65     s->format->Rmask,
66     s->format->Gmask,
67     s->format->Bmask,
68     s->format->Amask));
69 }
70
71 /* Used to copy the rotated scratch surface to the screen */
72 void BlitRotatedSurface(SDL_Surface *from, SDL_Surface *to)
73 {
74
75     int bpp = from->format->BytesPerPixel;
76     int w=from->w, h=from->h, pitch=to->pitch;
77     int i,j;
78     Uint8 *pfrom, *pto, *to0;
79
80     SDL_LockSurface(from);
81     SDL_LockSurface(to);
82     pfrom=(Uint8 *)from->pixels;
83     to0=(Uint8 *) to->pixels+pitch*(w-1);
84     for (i=0; i<h; i++)
85     {
86         to0+=bpp;
87         pto=to0;
88         for (j=0; j<w; j++)
89         {
90             if (bpp==1) *pto=*pfrom;
91             else if (bpp==2) *(Uint16 *)pto=*(Uint16 *)pfrom;
92             else if (bpp==4) *(Uint32 *)pto=*(Uint32 *)pfrom;
93             else if (bpp==3)
94                 {
95                     pto[0]=pfrom[0];
96                     pto[1]=pfrom[1];
97                     pto[2]=pfrom[2];
98                 }
99             pfrom+=bpp;
100             pto-=pitch;
101         }
102     }
103     SDL_UnlockSurface(from);
104     SDL_UnlockSurface(to);
105 }
106 #endif
107
108
109 static unsigned int fileRead(void *handle, void *buf, unsigned int count)
110 {
111         unsigned numread;
112
113         numread = fread(buf, 1, count, (FILE *)handle);
114         return (numread == count);
115 }
116
117 static void showFrame(unsigned char *buf, unsigned int bufw, unsigned int bufh,
118                                           unsigned int sx, unsigned int sy,
119                                           unsigned int w, unsigned int h,
120                                           unsigned int dstx, unsigned int dsty)
121 {
122         int i;
123         unsigned char *pal;
124         SDL_Surface *sprite;
125         SDL_Rect srcRect, destRect;
126
127         assert(bufw == w && bufh == h);
128
129         if (g_truecolor)
130                 sprite = SDL_CreateRGBSurfaceFrom(buf, bufw, bufh, 16, 2 * bufw, 0x7C00, 0x03E0, 0x001F, 0);
131         else
132         {
133                 sprite = SDL_CreateRGBSurfaceFrom(buf, bufw, bufh, 8, bufw, 0x7C00, 0x03E0, 0x001F, 0);
134
135                 pal = g_palette;
136                 for(i = 0; i < 256; i++)
137                 {
138                         sprite->format->palette->colors[i].r = (*pal++) << 2;
139                         sprite->format->palette->colors[i].g = (*pal++) << 2;
140                         sprite->format->palette->colors[i].b = (*pal++) << 2;
141                         sprite->format->palette->colors[i].unused = 0;
142                 }
143         }
144
145         srcRect.x = sx;
146         srcRect.y = sy;
147         srcRect.w = w;
148         srcRect.h = h;
149         destRect.x = dstx;
150         destRect.y = dsty;
151         destRect.w = w;
152         destRect.h = h;
153
154         SDL_BlitSurface(sprite, &srcRect, g_screen, &destRect);
155 #ifdef LANDSCAPE
156         BlitRotatedSurface(g_screen, real_screen);
157         if ( (real_screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF )
158                 SDL_Flip(real_screen);
159         else
160                 SDL_UpdateRect(real_screen, 0, 0, 0, 0);
161 #else
162         if ( (g_screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF )
163                 SDL_Flip(g_screen);
164         else
165                 SDL_UpdateRects(g_screen, 1, &destRect);
166 #endif
167         SDL_FreeSurface(sprite);
168 }
169
170 static void setPalette(unsigned char *p, unsigned start, unsigned count)
171 {
172         //Set color 0 to be black
173         g_palette[0] = g_palette[1] = g_palette[2] = 0;
174
175         //Set color 255 to be our subtitle color
176         g_palette[765] = g_palette[766] = g_palette[767] = 50;
177
178         //movie libs palette into our array
179         memcpy(g_palette + start*3, p+start*3, count*3);
180 }
181
182 static int pollEvents()
183 {
184         SDL_Event event;
185
186         while (SDL_PollEvent(&event))
187         {
188                 switch(event.type)
189                 {
190                 case SDL_QUIT:
191                 case SDL_MOUSEBUTTONDOWN:
192                 case SDL_MOUSEBUTTONUP:
193                         return 1;
194                 case SDL_KEYDOWN:
195                         switch (event.key.keysym.sym)
196                         {
197                         case SDLK_ESCAPE:
198                         case SDLK_q:
199                                 return 1;
200                         case SDLK_f:
201                                 SDL_WM_ToggleFullScreen(g_screen);
202                                 break;
203                         default:
204                                 break;
205                         }
206                         break;
207                 default:
208                         break;
209                 }
210         }
211
212         return 0;
213 }
214
215 static int doPlay(const char *filename)
216 {
217         int result;
218         int done = 0;
219         int bpp = 0;
220         FILE *mve;
221         MVE_videoSpec vSpec;
222
223         mve = fopen(filename, "rb");
224         if (mve == NULL) {
225                 fprintf(stderr, "can't open MVE file\n");
226                 return 1;
227         }
228
229         memset(g_palette, 0, 768);
230
231         MVE_sndInit(1);
232         MVE_memCallbacks((mve_cb_Alloc)malloc, free);
233         MVE_ioCallbacks(fileRead);
234         MVE_sfCallbacks(showFrame);
235         MVE_palCallbacks(setPalette);
236
237         MVE_rmPrepMovie(mve, -1, -1, track);
238
239         MVE_getVideoSpec(&vSpec);
240
241 #ifndef _WIN32_WCE // doesn't like to change bpp?
242         bpp = vSpec.truecolor?16:8;
243 #endif
244
245 #ifdef LANDSCAPE
246         real_screen = SDL_SetVideoMode(vSpec.screenHeight, vSpec.screenWidth, bpp, SDL_FULLSCREEN);
247         g_screen = CreateRotatedSurface(real_screen);
248 #else
249         g_screen = SDL_SetVideoMode(vSpec.screenWidth, vSpec.screenHeight, bpp, SDL_ANYFORMAT);
250 #endif
251
252         g_truecolor = vSpec.truecolor;
253
254         while (!done && (result = MVE_rmStepMovie()) == 0)
255         {
256                 done = pollEvents();
257         }
258
259         MVE_rmEndMovie();
260
261         fclose(mve);
262
263         return 0;
264 }