1 #include "bumprace.h"
2 #include "SDL_image.h"
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #define PATHNUM 8
7 #define BPP 0
8 #define RECTS_NUM 40000
9 #ifndef DATADIR
10 #define DATADIR "BumpRace.app/Contents/Resources/data"
11 #endif
12 char DATAPATH[200]=DATADIR;
13 const char PATH[PATHNUM][200]={DATADIR,".","data","/usr/local/share/bumprace"
14 ,"/usr/lib/bumprace","../data","/usr/share/bumprace", DATADIR};
15 SDL_Surface *Screen,*BackBuffer,*fadebuffer;
16 SDL_Rect blitrect,blitrects[RECTS_NUM];
17 int blitrects_num=0;
18 #ifdef DATADIR
ComplainAndExit(void)19 void ComplainAndExit(void)
20 {
21         fprintf(stderr, "Problem: %s\n", SDL_GetError());
22         exit(1);
23 }
24 #endif
abrand(int a,int b)25 int abrand(int a,int b)  //random number between a and b (inclusive)
26 {
27   return(a+(rand() % (b-a+1)));
28 }
29 
30 int (*_PutPixel)(SDL_Surface *Surface, Sint32 X, Sint32 Y, Uint32 Color);
31 
fast_putpixel1(SDL_Surface * Surface,Sint32 X,Sint32 Y,Uint32 Color)32 int fast_putpixel1(SDL_Surface *Surface, Sint32 X, Sint32 Y, Uint32 Color)
33 {
34   if (X < 0 || X > Surface->w || Y < 0 || Y > Surface->h)
35     return -1;
36 
37   *((Uint8 *)Surface->pixels + Y * Surface->pitch + X) = Color;
38 
39   return 0;
40 }
41 
fast_putpixel2(SDL_Surface * Surface,Sint32 X,Sint32 Y,Uint32 Color)42 int fast_putpixel2(SDL_Surface *Surface, Sint32 X, Sint32 Y, Uint32 Color)
43 {
44   if (X < 0 || X > Surface->w || Y < 0 || Y > Surface->h)
45     return -1;
46 
47  *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X) = Color;
48 
49   return 0;
50 }
51 
fast_putpixel3(SDL_Surface * Surface,Sint32 X,Sint32 Y,Uint32 Color)52 int fast_putpixel3(SDL_Surface *Surface, Sint32 X, Sint32 Y, Uint32 Color)
53 {
54   Uint8 *pix;
55   int shift;
56 
57   if (X < 0 || X > Surface->w || Y < 0 || Y > Surface->h)
58     return -1;
59 
60   /* Gack - slow, but endian correct */
61   pix = (Uint8 *)Surface->pixels + Y * Surface->pitch + X*3;
62   shift = Surface->format->Rshift;
63   *(pix+shift/8) = Color>>shift;
64   shift = Surface->format->Gshift;
65   *(pix+shift/8) = Color>>shift;
66   shift = Surface->format->Bshift;
67   *(pix+shift/8) = Color>>shift;
68 
69   return 0;
70 }
71 
fast_putpixel4(SDL_Surface * Surface,Sint32 X,Sint32 Y,Uint32 Color)72 int fast_putpixel4(SDL_Surface *Surface, Sint32 X, Sint32 Y, Uint32 Color)
73 {
74   if (X < 0 || X > Surface->w || Y < 0 || Y > Surface->h)
75     return -1;
76 
77   *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X) = Color;
78 
79   return 0;
80 }
81 
init_SDL()82 void init_SDL()  // sets the video mode
83 {
84   int bpp=BPP;
85   const SDL_VideoInfo *info;
86 
87   if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) < 0 ) {ComplainAndExit();}
88   info = SDL_GetVideoInfo();
89   if (info->vfmt->BitsPerPixel==8) bpp=16;
90   atexit(SDL_Quit);
91 // Set the video mode (800x600 at 16-bit depth)
92   if (fullscreen)
93     Screen = SDL_SetVideoMode(800, 600, BPP, SDL_FULLSCREEN);
94   else
95     { Screen = SDL_SetVideoMode(800, 600, BPP, 0); }
96   if ( Screen == NULL ) {ComplainAndExit();}
97 // create BackBuffer
98   BackBuffer = SDL_AllocSurface(Screen->flags,
99                                800,
100                                600,
101                                Screen->format->BitsPerPixel,
102                                Screen->format->Rmask,
103                                Screen->format->Gmask,
104                                Screen->format->Bmask, 0);
105   if (BackBuffer == NULL)
106   printf("ERROR: Couldn't create BackBuffer: %s\n", SDL_GetError());
107   fadebuffer = SDL_AllocSurface(Screen->flags,
108                                800,
109                                600,
110                                Screen->format->BitsPerPixel,
111                                Screen->format->Rmask,
112                                Screen->format->Gmask,
113                                Screen->format->Bmask, 0);
114   if (fadebuffer == NULL)
115   printf("ERROR: Couldn't create fadebuffer: %s\n", SDL_GetError());
116 // Figure out what putpixel routine to use
117    switch (Screen->format->BytesPerPixel)
118    {
119     case 1:
120       _PutPixel = fast_putpixel1;
121       break;
122     case 2:
123       _PutPixel = fast_putpixel2;
124       break;
125     case 3:
126       _PutPixel = fast_putpixel3;
127       break;
128     case 4:
129       _PutPixel = fast_putpixel4;
130       break;
131    }
132 }
133 
lock()134 void lock()
135 {
136         if ( SDL_MUSTLOCK(Screen) ) {
137                 if ( SDL_LockSurface(Screen) < 0 )
138 		return;        }
139 }
140 
unlock()141 void unlock()
142 {
143         if ( SDL_MUSTLOCK(Screen) ) {
144 	                SDL_UnlockSurface(Screen); }
145 }
146 
147 // Performs Callback at each line point. This came straight from the
148 // asphyxia vga trainers
DoLine(SDL_Surface * Surface,Sint32 X1,Sint32 Y1,Sint32 X2,Sint32 Y2,Uint32 Color,int Callback (SDL_Surface * Surf,Sint32 X,Sint32 Y,Uint32 Color))149 int DoLine (SDL_Surface *Surface, Sint32 X1, Sint32 Y1, Sint32 X2, Sint32 Y2, Uint32 Color, int Callback (SDL_Surface *Surf, Sint32 X, Sint32 Y, Uint32 Color))
150 {
151   Sint32 dx, dy, sdx, sdy, x, y, px, py;
152 
153   dx = X2 - X1;
154   dy = Y2 - Y1;
155 
156   sdx = (dx < 0) ? -1 : 1;
157   sdy = (dy < 0) ? -1 : 1;
158 
159   dx = sdx * dx + 1;
160   dy = sdy * dy + 1;
161 
162   x = y = 0;
163 
164   px = X1;
165   py = Y1;
166 
167   if (dx >= dy)
168     {
169       for (x = 0; x < dx; x++)
170 	{
171           Callback(Surface, px, py, Color);
172 
173 	  y += dy;
174 	  if (y >= dx)
175 	    {
176 	      y -= dx;
177 	      py += sdy;
178 	    }
179 	  px += sdx;
180 	}
181     }
182   else
183     {
184       for (y = 0; y < dy; y++)
185 	{
186 
187           Callback(Surface, px, py, Color);
188 
189 	  x += dx;
190 	  if (x >= dy)
191 	    {
192 	      x -= dy;
193 	      px += sdx;
194 	    }
195 	  py += sdy;
196 	}
197     }
198    return 0;
199 }
200 
fadeout()201 void fadeout()
202 {
203 	int y;
204 	SDL_Rect rect;
205 	Uint32 time;
206 
207 	rect.x = 0;
208 	rect.w = 800;
209 	rect.h = 1;
210 	for (y=0; y<600; y+=2) {
211 		time = SDL_GetTicks();
212 		rect.y = y;
213 		SDL_FillRect(Screen, &rect, SDL_MapRGB(Screen->format, 0,0,0));
214 		SDL_UpdateRects(Screen, 1, &rect);
215 		if (time == SDL_GetTicks())
216 			SDL_Delay(1);
217 	}
218 	for (y=599; y>0; y-=2) {
219 		rect.y = y;
220 		SDL_FillRect(Screen, &rect, SDL_MapRGB(Screen->format, 0,0,0));
221 		SDL_UpdateRects(Screen, 1, &rect);
222 	}
223 
224 	/*
225   int x,y;
226 
227   if (dofadeout==0) return;
228 
229   for (x=0;x<800;x++)
230   {
231     lock();
232     for (y=0;y<300;y++)
233     {
234       PutPixel(Screen,x,y*2,SDL_MapRGB(Screen->format,0,0,0));
235     }
236     unlock();
237     Update();
238   }
239   for (x=799;x>=0;x--)
240   {
241     lock();
242     for (y=299;y>0;y--)
243     {
244       PutPixel(Screen,x,y*2+1,SDL_MapRGB(Screen->format,0,0,0));
245     }
246     unlock();
247     Update();
248   }*/
249 }
250 
Update()251 void Update()
252 {
253   SDL_UpdateRects(Screen,blitrects_num,blitrects);
254   blitrects_num=0;
255 }
256 
AddRect(int x1,int y1,int x2,int y2)257 void AddRect(int x1, int y1, int x2, int y2)
258 {
259   int temp;
260 
261    /* Make sure X1 is before X2 */
262    if (x2 < x1){
263       temp = x2;
264       x2 = x1;
265       x1 = temp;
266    }
267    /* Make sure Y1 is before Y2 */
268    if (y2 < y1){
269       temp = y2;
270       y2 = y1;
271       y1 = temp;
272    }
273   blitrect.x = x1;
274   blitrect.y = y1;
275   blitrect.w = x2-x1+1;
276   blitrect.h = y2-y1+1;
277   if (x1<0) printf("x is too small in function AddRect!  -  %d\n",x1);else
278   if (y1<0) printf("y is too small in function AddRect!  -  %d\n",y1);else
279   if (x2>=800) printf("x is too big in function AddRect!  -  %d\n",x2);else
280   if (y2>=600) printf("y is too big in function AddRect!  -  %d\n",y2);else {
281       blitrects[blitrects_num]=blitrect;
282       if (++blitrects_num>=RECTS_NUM-2)
283       {printf("Too many blits!\n");blitrects_num--;Update();}
284   }
285 }
286 
AddThisRect(SDL_Rect blitrect)287 void AddThisRect(SDL_Rect blitrect)
288 {
289     blitrects[blitrects_num]=blitrect;
290     if (++blitrects_num>=RECTS_NUM-2)
291         {printf("Too many blits!\n");blitrects_num--;Update();}
292 }
293 
Blit(int Xpos,int Ypos,SDL_Surface * image)294 void Blit(int Xpos,int Ypos,SDL_Surface *image)  //blits one GIF or BMP from the memory to the screen
295 {
296   blitrect.x = Xpos;
297   blitrect.y = Ypos;
298   blitrect.w = image->w;
299   blitrect.h = image->h;
300 
301   if (Xpos<-image->w) printf("WRONG BLIT: Xpos is too small! - %d\n",Xpos); else
302   if (Xpos>=800) printf("WRONG BLIT: Xpos is too big! - %d\n",Xpos); else
303   if (Ypos<-image->h) printf("WRONG BLIT: Ypos is too small! - %d\n",Ypos); else
304   if (Ypos>=600) printf("WRONG BLIT: Ypos is too big! - %d\n",Ypos); else
305   if ( SDL_BlitSurface(image, NULL, Screen, &blitrect) < 0 )
306   {
307     SDL_FreeSurface(image);
308     ComplainAndExit();
309   }
310   blitrects[blitrects_num]=blitrect;
311   blitrects_num++;
312 }
313 
LoadImage(char * datafile,int transparent)314 SDL_Surface *LoadImage(char *datafile, int transparent)   // reads one png into the memory
315 {
316   SDL_Surface *pic,*pic2;
317   char filename[200];
318   int i=0;
319 
320   sprintf(filename,"%s/gfx/%s",DATAPATH,datafile);
321   pic=IMG_Load(filename);
322   while ( pic == NULL ) {
323     strcpy(DATAPATH,PATH[i]);
324     sprintf(filename,"%s/gfx/%s",DATAPATH,datafile);
325     pic=IMG_Load(filename);
326     i++;
327 
328     if (i>=PATHNUM)
329     {
330       fprintf(stderr,"Couldn't load %s: %s\n", filename, SDL_GetError());
331       exit(2);
332     }
333   }
334   if (transparent==3) return(pic);
335   if (transparent==1)
336     SDL_SetColorKey(pic,SDL_SRCCOLORKEY|SDL_RLEACCEL,SDL_MapRGB(pic->format,0xFF,0xFF,0xFF));
337   if (transparent==2)
338     SDL_SetColorKey(pic,SDL_SRCCOLORKEY|SDL_RLEACCEL,SDL_MapRGB(pic->format,0x00,0x00,0x00));
339   pic2 = SDL_DisplayFormat(pic);
340   SDL_FreeSurface(pic);
341 //  blit(0,0,pic2);
342 //  SDL_UpdateRect(screen,0,0,0,0);
343   return (pic2);
344 }
345 
BlitToBB(int Xpos,int Ypos,SDL_Surface * image)346 void BlitToBB(int Xpos,int Ypos,SDL_Surface *image)  //blits one GIF or BMP from the memory to the screen
347 {
348   blitrect.x = Xpos;
349   blitrect.y = Ypos;
350   blitrect.w = image->w;
351   blitrect.h = image->h;
352   if ( SDL_BlitSurface(image, NULL, BackBuffer, &blitrect) < 0 )
353   {
354     SDL_FreeSurface(image);
355     ComplainAndExit();
356   }
357 }
358 
BlitPart(int Xpos,int Ypos,SDL_Surface * image,SDL_Rect srcrect)359 void BlitPart(int Xpos,int Ypos,SDL_Surface *image, SDL_Rect srcrect)
360 {
361   blitrect.x = srcrect.x;
362   blitrect.y = srcrect.y;
363   blitrect.w = srcrect.w;
364   blitrect.h = srcrect.h;
365   if ( SDL_BlitSurface(image, &srcrect , Screen, &blitrect) < 0 )
366   {
367     SDL_FreeSurface(image);
368     ComplainAndExit();
369   }
370   blitrects[blitrects_num]=blitrect;
371   blitrects_num++;
372 }
373 
FadeScreen(float speed)374 void FadeScreen(float speed)
375 {
376   Sint32 now,i;
377 
378   SDL_BlitSurface(Screen,NULL,fadebuffer,NULL);
379   now=SDL_GetTicks();
380   for (i=255*speed;i>=0;i-=SDL_GetTicks()-now)
381   {
382     now=SDL_GetTicks();
383     SDL_BlitSurface(fadebuffer,&blitrect,Screen,&blitrect);
384     SDL_SetAlpha(BackBuffer,SDL_SRCALPHA,255-(int)(i/speed));
385     Blit(0,0,BackBuffer);
386     Update();
387   }
388   SDL_SetAlpha(BackBuffer,SDL_SRCALPHA,255);
389   Blit(0,0,BackBuffer);
390   Update();
391 }
392 
PutPixel(SDL_Surface * Surface,Sint32 X,Sint32 Y,Uint32 Color)393 int PutPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y, Uint32 Color)
394 {
395     if (X<0) printf("X < 0 in function PutPixel! - %d\n",X); else
396     if (X>=800) printf("X >= 800 in function PutPixel! - %d\n",X); else
397     if (Y<0) printf("Y < 0 in function PutPixel! - %d\n",Y); else
398     if (Y>=600) printf("Y >= 600 in function PutPixel! - %d\n",Y); else
399     {
400         _PutPixel(Surface,X,Y,Color);
401         AddRect(X,Y,X,Y);
402     }
403     return 0;
404 }
405 
PutPixelC(SDL_Surface * Surface,Sint32 X,Sint32 Y,Uint32 Color)406 int PutPixelC(SDL_Surface *Surface, Sint32 X, Sint32 Y, Uint32 Color)
407 {
408     if (X<0) printf("X < 0 in function PutPixelC! - %d\n",X); else
409     if (X>=800) printf("X >= 800 in function PutPixelC! - %d\n",X); else
410     if (Y<0) printf("Y < 0 in function PutPixelC! - %d\n",Y); else
411     if (Y>=600) printf("Y >= 600 in function PutPixelC! - %d\n",Y); else
412     {
413         _PutPixel(Surface,X,Y,Color);
414         AddRect(X,Y,X,Y);
415     }
416     return 0;
417 }
418 
PutBackPixel(SDL_Surface * Surface,Sint32 X,Sint32 Y)419 void PutBackPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
420 {
421     SDL_Rect rect;
422 
423     rect.w=1;
424     rect.h=1;
425     rect.x=X;
426     rect.y=Y;
427     SDL_BlitSurface(BackBuffer, &rect, Surface, &rect);
428     AddThisRect(rect);
429 }
430