1 #include "main.h"
2 #include <SDL_image.h>
3 #include <string.h>
4 
5 #define PATHNUM 6
6 #define BPP 0
7 #define RECTS_NUM 80000
8 
9 #ifndef DATADIR
10 #define DATADIR "."
11 #endif
12 char DATAPATH[200]=DATADIR;
13 const char PATH[PATHNUM][200]={DATADIR,".","data","../data","Penguin-Command.app/Contents/Resources/data",DATADIR};
14 SDL_Surface *Screen,*BackBuffer,*FadeBuffer;
15 SDL_Rect blitrect,blitrects[RECTS_NUM];
16 int blitrects_num=0;
17 
18 
ComplainAndExit(void)19 void ComplainAndExit(void)
20 {
21         fprintf(stderr, "Problem: %s\n", SDL_GetError());
22         exit(1);
23 }
24 
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,flags=0;
85   const SDL_VideoInfo *info;
86 
87 //  if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0 ) {ComplainAndExit();}
88   puts("** Init video **");
89   if ( SDL_Init(SDL_INIT_VIDEO ) < 0 ) ComplainAndExit();
90 //  puts("** Init timer **");
91 //  if ( SDL_Init(SDL_INIT_TIMER ) < 0 ) ComplainAndExit();
92   info = SDL_GetVideoInfo();
93   if (info->vfmt->BitsPerPixel==8) bpp=16;
94   atexit(SDL_Quit);
95 // Set the video mode (800x600 at 16-bit depth)
96   puts("** Set video mode **");
97   if (fullscreen)
98     Screen = SDL_SetVideoMode(800, 600, bpp, SDL_FULLSCREEN | flags);
99   else
100     { Screen = SDL_SetVideoMode(800, 600, bpp, flags); }
101   if ( Screen == NULL ) {ComplainAndExit();}
102 // create BackBuffer
103   puts("** Create buffers **");
104   BackBuffer = SDL_AllocSurface(Screen->flags,
105                                800,
106                                600,
107                                Screen->format->BitsPerPixel,
108                                Screen->format->Rmask,
109                                Screen->format->Gmask,
110                                Screen->format->Bmask, 0);
111   if (BackBuffer == NULL)
112   printf("ERROR: Couldn't create BackBuffer: %s\n", SDL_GetError());
113   FadeBuffer = SDL_AllocSurface(Screen->flags,
114                                800,
115                                600,
116                                Screen->format->BitsPerPixel,
117                                Screen->format->Rmask,
118                                Screen->format->Gmask,
119                                Screen->format->Bmask, 0);
120   if (FadeBuffer == NULL)
121   printf("ERROR: Couldn't create FadeBuffer: %s\n", SDL_GetError());
122 // Figure out what putpixel routine to use
123    switch (Screen->format->BytesPerPixel)
124    {
125     case 1:
126       _PutPixel = fast_putpixel1;
127       break;
128     case 2:
129       _PutPixel = fast_putpixel2;
130       break;
131     case 3:
132       _PutPixel = fast_putpixel3;
133       break;
134     case 4:
135       _PutPixel = fast_putpixel4;
136       break;
137    }
138 }
139 
lock()140 void lock()
141 {
142         if ( SDL_MUSTLOCK(Screen) ) {
143                 if ( SDL_LockSurface(Screen) < 0 )
144 		return;        }
145 }
146 
unlock()147 void unlock()
148 {
149         if ( SDL_MUSTLOCK(Screen) ) {
150                 SDL_UnlockSurface(Screen); }
151 }
152 
153 // Performs Callback at each line point. This came straight from the
154 // 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))155 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))
156 {
157   Sint32 dx, dy, sdx, sdy, x, y, px, py;
158 
159   dx = X2 - X1;
160   dy = Y2 - Y1;
161 
162   sdx = (dx < 0) ? -1 : 1;
163   sdy = (dy < 0) ? -1 : 1;
164 
165   dx = sdx * dx + 1;
166   dy = sdy * dy + 1;
167 
168   x = y = 0;
169 
170   px = X1;
171   py = Y1;
172 
173   if (dx >= dy)
174     {
175       for (x = 0; x < dx; x++)
176 	{
177           Callback(Surface, px, py, Color);
178 
179 	  y += dy;
180 	  if (y >= dx)
181 	    {
182 	      y -= dx;
183 	      py += sdy;
184 	    }
185 	  px += sdx;
186 	}
187     }
188   else
189     {
190       for (y = 0; y < dy; y++)
191 	{
192 
193           Callback(Surface, px, py, Color);
194 
195 	  x += dx;
196 	  if (x >= dy)
197 	    {
198 	      x -= dy;
199 	      px += sdx;
200 	    }
201 	  py += sdy;
202 	}
203     }
204    return 0;
205 }
206 
DoLinePart(SDL_Surface * Surface,Sint32 X1,Sint32 Y1,Sint32 X2,Sint32 Y2,Sint32 lower,Sint32 upper,Uint32 Color,int Callback (SDL_Surface * Surf,Sint32 X,Sint32 Y,Uint32 Color))207 int DoLinePart (SDL_Surface *Surface, Sint32 X1, Sint32 Y1, Sint32 X2, Sint32 Y2, Sint32 lower, Sint32 upper, Uint32 Color, int Callback (SDL_Surface *Surf, Sint32 X, Sint32 Y, Uint32 Color))
208 {
209   Sint32 dx, dy, sdx, sdy, x, y, px, py;
210 
211   dx = X2 - X1;
212   dy = Y2 - Y1;
213 
214   sdx = (dx < 0) ? -1 : 1;
215   sdy = (dy < 0) ? -1 : 1;
216 
217   dx = sdx * dx + 1;
218   dy = sdy * dy + 1;
219 
220   x = y = 0;
221 
222   px = X1;
223   py = Y1;
224 
225   if (dx >= dy)
226     {
227       for (x = 0; x < dx; x++)
228 	{
229 	  if ( (py<=upper)&&(py>=lower) )
230           Callback(Surface, px, py, Color);
231 
232 	  y += dy;
233 	  if (y >= dx)
234 	    {
235 	      y -= dx;
236 	      py += sdy;
237 	    }
238 	  px += sdx;
239 	}
240     }
241   else
242     {
243       for (y = 0; y < dy; y++)
244 	{
245 
246 	  if ( (py<=upper)&&(py>=lower) )
247           Callback(Surface, px, py, Color);
248 
249 	  x += dx;
250 	  if (x >= dy)
251 	    {
252 	      x -= dy;
253 	      px += sdx;
254 	    }
255 	  py += sdy;
256 	}
257     }
258    return 0;
259 }
260 
LinePart(Sint32 X1,Sint32 Y1,Sint32 X2,Sint32 Y2,Sint32 lower,Sint32 upper,Uint32 Color)261 void LinePart(Sint32 X1, Sint32 Y1, Sint32 X2, Sint32 Y2, Sint32 lower, Sint32 upper, Uint32 Color)
262 {
263    lock(Screen);
264 
265    /* Draw the line */
266    DoLinePart(Screen, X1, Y1, X2, Y2, lower, upper, Color, &PutPixel);
267    unlock(Screen);
268 }
269 
Update()270 void Update()
271 {
272   SDL_UpdateRects(Screen,blitrects_num,blitrects);
273   blitrects_num=0;
274 //  SDL_UpdateRect(Screen,0,0,0,0);
275 }
276 
FullUpdate()277 void FullUpdate()
278 {
279   blitrects_num=0;
280   SDL_UpdateRect(Screen,0,0,0,0);
281 }
282 
AddRect(int x1,int y1,int x2,int y2)283 void AddRect(int x1, int y1, int x2, int y2)
284 {
285   int temp;
286    /* Make sure X1 is before X2 */
287    if (x2 < x1){
288       temp = x2;
289       x2 = x1;
290       x1 = temp;
291    }
292    /* Make sure Y1 is before Y2 */
293    if (y2 < y1){
294       temp = y2;
295       y2 = y1;
296       y1 = temp;
297    }
298   blitrect.x = x1;
299   blitrect.y = y1;
300   blitrect.w = x2-x1+1;
301   blitrect.h = y2-y1+1;
302   if (x1<0) printf("x is too small in function AddRect!\n");else
303   if (y1<0) printf("y is too small in function AddRect!\n");else
304   if (x2>=800) printf("x is too big in function AddRect!\n");else
305   if (y2>=600) printf("y is too big in function AddRect!\n");else {
306       blitrects[blitrects_num]=blitrect;
307       if (++blitrects_num>=RECTS_NUM-2)
308       {printf("Too many blits!\n");blitrects_num--;Update();}
309   }
310 }
311 
AddThisRect(SDL_Rect blitrect)312 void AddThisRect(SDL_Rect blitrect)
313 {
314     blitrects[blitrects_num]=blitrect;
315     if (++blitrects_num>=RECTS_NUM-2)
316         {printf("Too many blits!\n");blitrects_num--;Update();}
317 }
318 
Blit(int Xpos,int Ypos,SDL_Surface * image)319 void Blit(int Xpos,int Ypos,SDL_Surface *image)  //blits one GIF or BMP from the memory to the screen
320 {
321   blitrect.x = Xpos;
322   blitrect.y = Ypos;
323   blitrect.w = image->w;
324   blitrect.h = image->h;
325 
326   if (image==NULL) printf("WRONG BLIT: surface pointer is NULL!\n");
327   if (Xpos<-image->w) printf("WRONG BLIT: Xpos is too small! - %d\n",Xpos); else
328   if (Xpos>=800) printf("WRONG BLIT: Xpos is too big! - %d\n",Xpos); else
329   if (Ypos<-image->h) printf("WRONG BLIT: Ypos is too small!\n - %d",Ypos); else
330   if (Ypos>=600) printf("WRONG BLIT: Ypos is too big! - %d\n",Ypos); else
331   if ( SDL_BlitSurface(image, NULL, Screen, &blitrect) < 0 )
332   {
333     SDL_FreeSurface(image);
334     ComplainAndExit();
335   }
336   blitrects[blitrects_num]=blitrect;
337   blitrects_num++;
338 }
339 
LoadImage(char * datafile,int transparent)340 SDL_Surface *LoadImage(char *datafile, int transparent)   // reads one png into the memory
341 {
342   SDL_Surface *pic=NULL,*pic2=NULL;
343   char filename[200];
344   int i=0;
345 
346   sprintf(filename,"%s/gfx/%s",DATAPATH,datafile);
347   pic=IMG_Load(filename);
348   while ( pic == NULL ) {
349     strcpy(DATAPATH,PATH[i]);
350     sprintf(filename,"%s/gfx/%s",DATAPATH,datafile);
351     pic=IMG_Load(filename);
352     i++;
353 
354     if (i>=PATHNUM)
355     {
356       fprintf(stderr,"Couldn't load %s: %s\n", filename, SDL_GetError());
357       exit(2);
358     }
359   }
360   if (transparent>=3) {
361       if ((NoAlpha)&&(transparent!=4)) {
362 //	  SDL_SetColorKey(pic,SDL_SRCCOLORKEY|SDL_RLEACCEL, GetPixel(pic,0,0));
363 	  SDL_SetColorKey(pic,SDL_SRCCOLORKEY, GetPixel(pic,0,0));
364           pic2 = SDL_DisplayFormat(pic);
365           SDL_FreeSurface(pic);
366           return (pic2);
367       }
368       else {
369 //	  SDL_SetColorKey(pic,SDL_RLEACCEL, 0);
370           pic2 = SDL_DisplayFormatAlpha(pic);
371           SDL_FreeSurface(pic);
372           return (pic2);
373       }
374   }
375   if (transparent==1)
376     SDL_SetColorKey(pic,SDL_SRCCOLORKEY|SDL_RLEACCEL,SDL_MapRGB(pic2->format,0xFF,0xFF,0xFF));
377   if (transparent==2)
378     SDL_SetColorKey(pic,SDL_SRCCOLORKEY|SDL_RLEACCEL,0);
379   if (transparent>-1) {
380       pic2 = SDL_DisplayFormat(pic);
381       return (pic2);
382   } else
383       return pic;
384 }
385 
BlitToBB(int Xpos,int Ypos,SDL_Surface * image)386 void BlitToBB(int Xpos,int Ypos,SDL_Surface *image)  //blits one GIF or BMP from the memory to the screen
387 {
388   blitrect.x = Xpos;
389   blitrect.y = Ypos;
390   blitrect.w = image->w;
391   blitrect.h = image->h;
392   printf("rect %d,%d,%d,%d: %d\n", blitrect.x, blitrect.y, blitrect.w, blitrect.h, image);
393   if ( SDL_BlitSurface(image, NULL, BackBuffer, &blitrect) < 0 )
394   {
395     SDL_FreeSurface(image);
396     ComplainAndExit();
397   }
398 }
399 
BlitPart(int Xpos,int Ypos,SDL_Surface * image,SDL_Rect srcrect)400 void BlitPart(int Xpos,int Ypos,SDL_Surface *image, SDL_Rect srcrect)
401 {
402   blitrect.x = srcrect.x;
403   blitrect.y = srcrect.y;
404   blitrect.w = srcrect.w;
405   blitrect.h = srcrect.h;
406   if ( SDL_BlitSurface(image, &srcrect , Screen, &blitrect) < 0 )
407   {
408     SDL_FreeSurface(image);
409     ComplainAndExit();
410   }
411   blitrects[blitrects_num]=blitrect;
412   blitrects_num++;
413 }
414 
FadeScreen(float speed)415 void FadeScreen(float speed)
416 {
417   Sint32 now,i;
418 
419   SDL_BlitSurface(Screen,NULL,FadeBuffer,NULL);
420   now=SDL_GetTicks();
421   for (i=255*speed;i>=0;i-=SDL_GetTicks()-now)
422   {
423     now=SDL_GetTicks();
424     SDL_BlitSurface(FadeBuffer,&blitrect,Screen,&blitrect);
425     SDL_SetAlpha(BackBuffer,SDL_SRCALPHA,255-(int)(i/speed));
426     Blit(0,0,BackBuffer);
427     SDL_UpdateRects(Screen,1,&blitrect);
428   }
429   SDL_SetAlpha(BackBuffer,0,0);
430   Blit(0,0,BackBuffer);
431   SDL_UpdateRects(Screen,1,&blitrect);
432 }
433 
PutPixel(SDL_Surface * Surface,Sint32 X,Sint32 Y,Uint32 Color)434 int PutPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y, Uint32 Color)
435 {
436     if (X<0) printf("X < 0 in function PutPixel! - %d\n",X); else
437     if (X>=800) printf("X >= 800 in function PutPixel! - %d\n",X); else
438     if (Y<0) printf("Y < 0 in function PutPixel! - %d\n",Y); else
439     if (Y>=600) printf("Y >= 600 in function PutPixel! - %d\n",Y); else
440     {
441         _PutPixel(Surface,X,Y,Color);
442         AddRect(X,Y,X,Y);
443     }
444     return 0;
445 }
446 
447 /* This is a Callback for DoLine, so return type and arguments must match */
PutBackPixel(SDL_Surface * Surface,Sint32 X,Sint32 Y,Uint32 Color)448 int PutBackPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y, Uint32 Color)
449 {
450     SDL_Rect rect;
451 
452     if ( (X<0) || (X>=800) || (Y<0) || (Y>=600) ) return -1;
453 
454     rect.w=1;
455     rect.h=1;
456     rect.x=X;
457     rect.y=Y;
458     SDL_BlitSurface(BackBuffer, &rect, Surface, &rect);
459     AddThisRect(rect);
460 
461     return 0;
462 }
463 
UndrawLine(Sint32 X1,Sint32 Y1,Sint32 X2,Sint32 Y2,Uint32 Color)464 void UndrawLine(Sint32 X1, Sint32 Y1, Sint32 X2, Sint32 Y2, Uint32 Color)
465 {
466    /* Draw the line */
467    DoLine(Screen, X1, Y1, X2, Y2, Color, &PutBackPixel);
468 }
469