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