1 /*
2  *
3  *   Copyright (c) 1994, 2002, 2003  Johannes Prix
4  *   Copyright (c) 1994, 2002, 2003  Reinhard Prix
5  *
6  *
7  *  This file is part of Freedroid
8  *
9  *  Freedroid is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  Freedroid is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with Freedroid; see the file COPYING. If not, write to the
21  *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  *  MA  02111-1307  USA
23  *
24  */
25 
26 /*----------------------------------------------------------------------
27  *
28  * Desc: Graphics primitived, such as functions to load LBM or PCX images,
29  * 	 to change the vga color table, to activate or deachtivate monitor
30  *	 signal, to set video modes etc.
31  *
32  *----------------------------------------------------------------------*/
33 
34 #define _graphics_c
35 
36 #include "system.h"
37 
38 #include "defs.h"
39 #include "struct.h"
40 #include "global.h"
41 #include "proto.h"
42 #include "map.h"
43 #include "text.h"
44 #include "SDL_rotozoom.h"
45 #include "takeover.h"
46 
47 const SDL_VideoInfo *vid_info;/* info about current video mode */
48 
49 void PutPixel (SDL_Surface * surface, int x, int y, Uint32 pixel);
50 int Load_Fonts (void);
51 SDL_Surface *Load_Block (char *fpath, int line, int col, SDL_Rect * block, int flags);
52 SDL_RWops *load_raw_pic (char *fpath);
53 
54 /* XPM */
55 static const char *crosshair_xpm[] = {
56   /* width height num_colors chars_per_pixel */
57   "    32    32        3            1",
58   /* colors */
59   "X c #000000",
60   ". c #ffffff",
61   "  c None",
62   /* pixels */
63   "                                ",
64   "                                ",
65   "               XXXX             ",
66   "               X..X             ",
67   "               X..X             ",
68   "               X..X             ",
69   "               X..X             ",
70   "               X..X             ",
71   "               X..X             ",
72   "               X..X             ",
73   "               X..X             ",
74   "               XXXX             ",
75   "                                ",
76   "   XXXXXXXXXXX      XXXXXXXXXX  ",
77   "   X.........X      X........X  ",
78   "   X.........X      X........X  ",
79   "   XXXXXXXXXXX      XXXXXXXXXX  ",
80   "                                ",
81   "               XXXX             ",
82   "               X..X             ",
83   "               X..X             ",
84   "               X..X             ",
85   "               X..X             ",
86   "               X..X             ",
87   "               X..X             ",
88   "               X..X             ",
89   "               X..X             ",
90   "               X..X             ",
91   "               X..X             ",
92   "               XXXX             ",
93   "                                ",
94   "                                ",
95   "0,0"
96 };
97 
98 
99 /* XPM */
100 static const char *arrow_xpm[] = {
101   /* width height num_colors chars_per_pixel */
102   "    32    32        3            1",
103   /* colors */
104   "X c #000000",
105   ". c #ffffff",
106   "  c None",
107   /* pixels */
108   "X                               ",
109   "XX                              ",
110   "X.X                             ",
111   "X..X                            ",
112   "X...X                           ",
113   "X....X                          ",
114   "X.....X                         ",
115   "X......X                        ",
116   "X.......X                       ",
117   "X........X                      ",
118   "X.....XXXXX                     ",
119   "X..X..X                         ",
120   "X.X X..X                        ",
121   "XX  X..X                        ",
122   "X    X..X                       ",
123   "     X..X                       ",
124   "      X..X                      ",
125   "      X..X                      ",
126   "       XX                       ",
127   "                                ",
128   "                                ",
129   "                                ",
130   "                                ",
131   "                                ",
132   "                                ",
133   "                                ",
134   "                                ",
135   "                                ",
136   "                                ",
137   "                                ",
138   "                                ",
139   "                                ",
140   "0,0"
141 };
142 
143 
144 /* ----------------------------------------------------------------------
145  * This function applies a color filter to a given surface
146  * ---------------------------------------------------------------------- */
147 int
ApplyFilter(SDL_Surface * surf,float fred,float fgreen,float fblue)148 ApplyFilter (SDL_Surface *surf, float fred, float fgreen, float fblue)
149 {
150   int x , y ; // for processing through the surface...
151   Uint8 red, green, blue, alpha;
152 
153   //--------------------
154   // First we check for null surfaces given...
155   //
156   if ( surf == NULL )
157     {
158       DebugPrintf (0 , "\nERROR: ApplyFilter called with NULL pointer\n" );
159       return (ERR);
160     }
161 
162   //--------------------
163   // Now we start to process through the whole surface and examine each
164   // pixel.
165   //
166   for ( y = 0 ; y < surf -> h ; y ++ )
167     {
168       for ( x = 0 ; x < surf -> w ; x ++ )
169 	{
170 	  GetRGBA (surf, x, y, &red, &green, &blue, &alpha);
171 
172 	  if (alpha == SDL_ALPHA_TRANSPARENT)
173 	    continue;
174 
175 	  red *= fred;
176 	  green *= fgreen;
177 	  blue *= fblue;
178 
179 	  putpixel (surf, x, y, SDL_MapRGBA (surf->format, red, green, blue, alpha) ) ;
180 	}
181     }
182 
183   return (OK);
184 
185 } // Apply_Filter
186 
187 /* ----------------------------------------------------------------------
188  * This function gives the green component of a pixel, using a value of
189  * 255 for the most green pixel and 0 for the least green pixel.
190  * ---------------------------------------------------------------------- */
191 void
GetRGBA(SDL_Surface * surface,int x,int y,Uint8 * r,Uint8 * g,Uint8 * b,Uint8 * a)192 GetRGBA ( SDL_Surface* surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
193 {
194   SDL_PixelFormat *fmt;
195   Uint32 pixel;
196 
197   //--------------------
198   // First we extract the pixel itself and the
199   // format information we need.
200   //
201   fmt = surface -> format ;
202   pixel = * ( ( ( Uint32* ) surface -> pixels ) + x + y * surface->w )  ;
203 
204   SDL_GetRGBA (pixel, fmt, r, g, b, a);
205 
206 }; // int GetRGBA
207 
208 
209 /*----------------------------------------------------------------------
210 This function was taken directly from the example in the SDL docu.
211 Even there they say they have stolen if from the mailing list.
212 Anyway it should create a new mouse cursor from an XPM.
213 The XPM is defined above and not read in from disk or something.
214 ----------------------------------------------------------------------*/
init_system_cursor(const char * image[])215 static SDL_Cursor *init_system_cursor(const char *image[])
216 {
217   int i, row, col;
218   Uint8 data[4*32];
219   Uint8 mask[4*32];
220   int hot_x, hot_y;
221 
222   i = -1;
223   for ( row=0; row<32; ++row ) {
224     for ( col=0; col<32; ++col ) {
225       if ( col % 8 ) {
226         data[i] <<= 1;
227         mask[i] <<= 1;
228       } else {
229         ++i;
230         data[i] = mask[i] = 0;
231       }
232       switch (image[4+row][col]) {
233         case 'X':
234           data[i] |= 0x01;
235           mask[i] |= 0x01;
236           break;
237         case '.':
238           mask[i] |= 0x01;
239           break;
240         case ' ':
241           break;
242       }
243     }
244   }
245   sscanf(image[4+row], "%d,%d", &hot_x, &hot_y);
246   return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
247 };
248 
249 /*
250 ----------------------------------------------------------------------
251 ----------------------------------------------------------------------
252 */
253 
254 void
DrawLineBetweenTiles(float x1,float y1,float x2,float y2,int Color)255 DrawLineBetweenTiles( float x1 , float y1 , float x2 , float y2 , int Color )
256 {
257   int i;
258   int pixx;
259   int pixy;
260   float tmp;
261   float slope;
262 
263   if ( (x1 == x2) && (y1 == y2) ) return; // nothing is to be done here
264 
265 
266   if (x1 == x2) // infinite slope!! special case, that must be caught!
267     {
268 
269       if (y1 > y2) // in this case, just interchange 1 and 2
270 	{
271 	  tmp = y1;
272 	  y1=y2;
273 	  y2=tmp;
274 	}
275 
276       for ( i=0 ; i < (y2 - y1) * Block_Rect.w ; i++ )
277 	{
278 	  pixx = User_Rect.x + User_Rect.w/2 - Block_Rect.w * (Me.pos.x - x1 );
279 	  pixy = UserCenter_y - Block_Rect.h * (Me.pos.y - y1 ) + i ;
280 	  if ( (pixx <= User_Rect.x) ||
281 	       (pixx >= User_Rect.x + User_Rect.w -1) ||
282 	       (pixy <= User_Rect.y ) ||
283 	       (pixy >= User_Rect.y + User_Rect.h -1) ) continue;
284 	  putpixel( ne_screen , pixx , pixy , Color );
285 	  putpixel( ne_screen , pixx-1 , pixy , Color );
286 	}
287       return;
288     }
289 
290   if (x1 > x2) // in this case, just interchange 1 and 2
291     {
292       tmp = x1;
293       x1=x2;
294       x2=tmp;
295       tmp = y1;
296       y1=y2;
297       y2=tmp;
298     }
299 
300   //--------------------
301   // Now we start the drawing process
302   //
303   // SDL_LockSurface( ne_screen );
304 
305   slope = ( y2 - y1 ) / (x2 - x1) ;
306   for ( i=0 ; i<(x2-x1)*Block_Rect.w ; i++ )
307     {
308       pixx=User_Rect.x + User_Rect.w/2 - Block_Rect.w * (Me.pos.x - x1 ) + i;
309       pixy= UserCenter_y - Block_Rect.h * (Me.pos.y - y1 ) + i * slope ;
310       if ( (pixx <= User_Rect.x) ||
311 	   (pixx >= User_Rect.x + User_Rect.w -1) ||
312 	   (pixy <= User_Rect.y ) ||
313 	   (pixy >= User_Rect.y + User_Rect.h -1) ) continue;
314       putpixel( ne_screen , pixx , pixy , Color );
315       putpixel( ne_screen , pixx , pixy -1 , Color );
316     }
317 
318   // SDL_UnlockSurface( ne_screen );
319 
320 } // void DrawLineBetweenTiles
321 
322 
323 /*-----------------------------------------------------------------
324  * This function saves a screenshot to disk.
325  * The screenshots are names "Screenshot_XX.bmp" where XX is a
326  * running number.
327  *
328  * NOTE:  This function does NOT check for existing screenshots,
329  *        but will silently overwrite them.  No problem in most
330  *        cases I think.
331  *
332  *-----------------------------------------------------------------*/
333 void
TakeScreenshot(void)334 TakeScreenshot(void)
335 {
336   static int Number_Of_Screenshot=0;
337   char *Screenshoot_Filename;
338 
339   Screenshoot_Filename=MyMalloc(100);
340   DebugPrintf (1, "\n\nScreenshoot function called.\n\n");
341   sprintf( Screenshoot_Filename , "Screenshot_%d.bmp", Number_Of_Screenshot );
342   DebugPrintf(1, "\n\nScreenshoot function: The Filename is: %s.\n\n" , Screenshoot_Filename );
343   SDL_SaveBMP( ne_screen , Screenshoot_Filename );
344   Number_Of_Screenshot++;
345   free(Screenshoot_Filename);
346 
347 } // void TakeScreenshot(void)
348 
349 /*
350 ----------------------------------------------------------------------
351 @Desc: This function draws a "grid" on the screen, that means every
352        "second" pixel is blacked out, thereby generation a fading
353        effect.  This function was created to fade the background of the
354        Escape menu and its submenus.
355 
356 @Ret: none
357 ----------------------------------------------------------------------
358 */
359 void
MakeGridOnScreen(SDL_Rect * Grid_Rectangle)360 MakeGridOnScreen( SDL_Rect* Grid_Rectangle )
361 {
362   int x,y;
363 
364   if ( Grid_Rectangle == NULL ) Grid_Rectangle = & User_Rect ;
365 
366   DebugPrintf (2, "\nvoid MakeGridOnScreen(...): real function call confirmed.");
367   SDL_LockSurface( ne_screen );
368   for ( y = Grid_Rectangle->y ; y < (Grid_Rectangle->h + Grid_Rectangle->y) ; y++)
369     {
370       for ( x = Grid_Rectangle->x ; x < (Grid_Rectangle->x + Grid_Rectangle->w) ; x++ )
371 	{
372 	  if ((x+y)%2 == 0)
373 	    {
374 	      putpixel( ne_screen, x, y, 0 );
375 	    }
376 	}
377     }
378 
379   SDL_UnlockSurface( ne_screen );
380   DebugPrintf (2, "\nvoid MakeGridOnScreen(...): end of function reached.");
381 } // void MakeGridOnSchreen(void)
382 
383 
384 /*----------------------------------------------------------------------
385  * This function load an image and displays it directly to the ne_screen
386  * but without updating it.
387  * This might be very handy, especially in the Title() function to
388  * display the title image and perhaps also for displaying the ship
389  * and that.
390  *
391  ----------------------------------------------------------------------*/
392 void
DisplayImage(char * datafile)393 DisplayImage(char *datafile)
394 {
395   SDL_Surface *image;
396 
397   image = IMG_Load(datafile);
398   if ( image == NULL ) {
399     DebugPrintf(0, "ERROR: Couldn't load image %s: %s\n", datafile, IMG_GetError());
400     Terminate(ERR);
401   }
402 
403   if (GameConfig.scale != 1.0)
404     ScalePic (&image, GameConfig.scale);
405 
406   SDL_BlitSurface(image, NULL, ne_screen, NULL);
407 
408   SDL_FreeSurface(image);
409 
410   return;
411 
412 } // DisplayImage()
413 
414 /*----------------------------------------------------------------------
415  * This function resizes all blocks and structures involved in assembling
416  * the combat picture to a new scale.  The new scale is relative to the
417  * standard scale with means scale=1 is 64x64 tile size.
418  *
419  * in the first call we assume the Block_Rect to be the original game-size
420  * and store this value for future rescalings
421  ----------------------------------------------------------------------*/
422 void
SetCombatScaleTo(float scale)423 SetCombatScaleTo(float scale)
424 {
425   int i, j;
426   static SDL_Rect origBlock;
427   static bool firstcall = TRUE;
428   SDL_Surface *tmp;
429 
430   if (firstcall) Copy_Rect (Block_Rect, origBlock);   // keep that as a backup
431   firstcall = FALSE;
432 
433   for ( j=0 ; j < NUM_COLORS ; j++ )
434     for ( i = 0 ; i < NUM_MAP_BLOCKS ; i++ )
435       {
436 	// if there's already a rescaled version, free it
437 	if (MapBlockSurfacePointer[j][i] != OrigMapBlockSurfacePointer[j][i])
438 	  SDL_FreeSurface (MapBlockSurfacePointer[j][i]);
439 	// then zoom..
440 	tmp = zoomSurface(OrigMapBlockSurfacePointer[j][i], scale, scale, 0);
441 	// and optimize
442 	MapBlockSurfacePointer[j][i]=SDL_DisplayFormat (tmp);
443 	SDL_FreeSurface(tmp); // free the old surface
444       }
445 
446   Copy_Rect (origBlock, Block_Rect);   // always scale with respect to original size!
447   ScaleRect(Block_Rect, scale);
448 
449   return;
450 
451 } // void SetCombatScaleTo(float new_scale);
452 
453 /*
454 ----------------------------------------------------------------------
455 ----------------------------------------------------------------------
456 */
457 void
LoadThemeConfigurationFile(void)458 LoadThemeConfigurationFile(void)
459 {
460   char *Data;
461   char *ReadPointer;
462   char *fpath;
463   char *EndOfThemesBulletData;
464   char *EndOfThemesBlastData;
465   char *EndOfThemesDigitData;
466   int BulletIndex;
467 
468 #define END_OF_THEME_DATA_STRING "**** End of theme data section ****"
469 #define END_OF_THEME_BLAST_DATA_STRING "*** End of themes blast data section ***"
470 #define END_OF_THEME_BULLET_DATA_STRING "*** End of themes bullet data section ***"
471 #define END_OF_THEME_DIGIT_DATA_STRING "*** End of themes digit data section ***"
472 
473   fpath = find_file ("config.theme", GRAPHICS_DIR, USE_THEME, CRITICAL);
474 
475   Data = ReadAndMallocAndTerminateFile( fpath , END_OF_THEME_DATA_STRING ) ;
476 
477   EndOfThemesBulletData = LocateStringInData ( Data , END_OF_THEME_BULLET_DATA_STRING );
478   EndOfThemesBlastData  = LocateStringInData ( Data , END_OF_THEME_BLAST_DATA_STRING  );
479   EndOfThemesDigitData  = LocateStringInData ( Data , END_OF_THEME_DIGIT_DATA_STRING  );
480 
481   //--------------------
482   // Now the file is read in entirely and
483   // we can start to analyze its content,
484   //
485 #define BLAST_ONE_NUMBER_OF_PHASES_STRING "How many phases in Blast one :"
486 #define BLAST_TWO_NUMBER_OF_PHASES_STRING "How many phases in Blast two :"
487 
488   ReadValueFromString (Data, BLAST_ONE_NUMBER_OF_PHASES_STRING, "%d", &Blastmap[0].phases);
489 
490   ReadValueFromString (Data, BLAST_TWO_NUMBER_OF_PHASES_STRING, "%d", &Blastmap[1].phases);
491 
492   //--------------------
493   // Next we read in the number of phases that are to be used for each bullet type
494   ReadPointer = Data ;
495   while ( ( ReadPointer = strstr ( ReadPointer , "For Bullettype Nr.=" ) ) != NULL )
496     {
497       ReadValueFromString (ReadPointer, "For Bullettype Nr.=", "%d", &BulletIndex);
498       if ( BulletIndex >= Number_Of_Bullet_Types )
499 	{
500 	  DebugPrintf (0, "\n\n\
501 ----------------------------------------------------------------------\n\
502 Freedroid has encountered a problem:\n\
503 In function 'char* LoadThemeConfigurationFile ( ... ):\n\
504 \n\
505 There was a specification for the number of phases in a bullet type\n\
506 that does not at all exist in the ruleset.\n\
507 \n\
508 This might indicate that either the ruleset file is corrupt or the \n\
509 theme.config configuration file is corrupt or (less likely) that there\n\
510 is a severe bug in the reading function.\n\
511 \n\
512 Please check that your theme and ruleset files are properly set up.\n\
513 \n\
514 Please also don't forget, that you might have to run 'make install'\n\
515 again after you've made modifications to the data files in the source tree.\n\
516 \n\
517 Freedroid will terminate now to draw attention to the data problem it could\n\
518 not resolve.... Sorry, if that interrupts a major game of yours.....\n\
519 ----------------------------------------------------------------------\n\
520 \n" );
521 	  Terminate(ERR);
522 	}
523       ReadValueFromString (ReadPointer, "we will use number of phases=", "%d", &Bulletmap[BulletIndex].phases);
524       ReadValueFromString (ReadPointer, "and number of phase changes per second=", "%f",
525 			   &Bulletmap[BulletIndex].phase_changes_per_second);
526       ReadPointer++;
527     }
528 
529   // --------------------
530   // Also decidable from the theme is where in the robot to
531   // display the digits.  This must also be read from the configuration
532   // file of the theme
533   //
534 #define DIGIT_ONE_POSITION_X_STRING "First digit x :"
535 #define DIGIT_ONE_POSITION_Y_STRING "First digit y :"
536 #define DIGIT_TWO_POSITION_X_STRING "Second digit x :"
537 #define DIGIT_TWO_POSITION_Y_STRING "Second digit y :"
538 #define DIGIT_THREE_POSITION_X_STRING "Third digit x :"
539 #define DIGIT_THREE_POSITION_Y_STRING "Third digit y :"
540 
541   ReadValueFromString (Data, DIGIT_ONE_POSITION_X_STRING, "%hd", &FirstDigit_Rect.x);
542   ReadValueFromString (Data, DIGIT_ONE_POSITION_Y_STRING, "%hd", &FirstDigit_Rect.y);
543 
544   ReadValueFromString (Data, DIGIT_TWO_POSITION_X_STRING, "%hd", &SecondDigit_Rect.x);
545   ReadValueFromString (Data, DIGIT_TWO_POSITION_Y_STRING, "%hd", &SecondDigit_Rect.y);
546 
547   ReadValueFromString (Data, DIGIT_THREE_POSITION_X_STRING, "%hd", &ThirdDigit_Rect.x);
548   ReadValueFromString (Data, DIGIT_THREE_POSITION_Y_STRING, "%hd", &ThirdDigit_Rect.y);
549 
550   free (Data);
551 
552   return;
553 
554 }; // void LoadThemeConfigurationFile ( void )
555 
556 
557 /*-----------------------------------------------------------------
558  * @Desc: get the pics for: druids, bullets, blasts
559  *
560  * 	reads all blocks and puts the right pointers into
561  * 	the various structs
562  *
563  * @Ret: TRUE/FALSE
564  *
565  *-----------------------------------------------------------------*/
566 int
InitPictures(void)567 InitPictures (void)
568 {
569   static bool first_call= TRUE;
570   char *fpath;
571   int line, col, i;
572   BFont_Info *oldfont;
573   SDL_Surface *tmp;
574   char fname[500];
575 
576   // Loading all these pictures might take a while...
577   // and we do not want do deal with huge frametimes, which
578   // could box the influencer out of the ship....
579   Activate_Conservative_Frame_Computation();
580 
581   oldfont = GetCurrentFont ();
582 
583   if (first_call)
584     Load_Fonts ();
585 
586   SetCurrentFont (FPS_Display_BFont);
587   printf_SDL (ne_screen, User_Rect.x + 50, Screen_Rect.h - 100, "Loading Theme config ...");
588 
589   LoadThemeConfigurationFile();
590 
591   printf_SDL (ne_screen, -1, -1, " ok\n");
592 
593   printf_SDL (ne_screen, User_Rect.x + 50, -1, "Loading image data ");
594   //---------- get Map blocks
595   fpath = find_file (MAP_BLOCK_FILE, GRAPHICS_DIR, USE_THEME, CRITICAL);
596   Load_Block (fpath, 0, 0, NULL, INIT_ONLY);	/* init function */
597   for (line = 0; line < NUM_COLORS; line ++)
598     for (col = 0; col < NUM_MAP_BLOCKS; col ++)
599       {
600 	FreeIfUsed (OrigMapBlockSurfacePointer[line][col]);
601 	OrigMapBlockSurfacePointer[line][col] = Load_Block (NULL, line, col, &OrigBlock_Rect,0);
602 	MapBlockSurfacePointer[line][col] = OrigMapBlockSurfacePointer[line][col];
603       }
604   printf_SDL (ne_screen, -1, -1, ".");
605   //---------- get Droid-model  blocks
606   fpath = find_file (DROID_BLOCK_FILE, GRAPHICS_DIR, USE_THEME, CRITICAL);
607   Load_Block (fpath, 0, 0, NULL, INIT_ONLY);
608   for (col = 0; col < DROID_PHASES; col ++)
609     {
610       FreeIfUsed (InfluencerSurfacePointer[col]);
611       FreeIfUsed (EnemySurfacePointer[col]);
612       InfluencerSurfacePointer[col] = Load_Block (NULL, 0, col, &OrigBlock_Rect, 0);
613       EnemySurfacePointer[col] = Load_Block (NULL, 1, col, &OrigBlock_Rect, 0);
614       /* Droid pics are only used in _internal_ blits ==> clear per-surf alpha */
615       SDL_SetAlpha (InfluencerSurfacePointer[col], 0, 0);
616       SDL_SetAlpha (EnemySurfacePointer[col], 0, 0);
617     }
618 
619   //  SDL_SetAlpha( Me.pic, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
620 
621   printf_SDL (ne_screen, -1, -1, ".");
622   //---------- get Bullet blocks
623   fpath = find_file (BULLET_BLOCK_FILE, GRAPHICS_DIR, USE_THEME, CRITICAL);
624   Load_Block (fpath, 0, 0, NULL, INIT_ONLY);
625   for (line = 0; line < Number_Of_Bullet_Types; line ++)
626     for (col = 0; col < Bulletmap[line].phases; col ++)
627       {
628 	FreeIfUsed (Bulletmap[line].SurfacePointer[col]);
629 	Bulletmap[line].SurfacePointer[col] = Load_Block (NULL, line, col, &OrigBlock_Rect, 0);
630       }
631   printf_SDL (ne_screen, -1, -1, ".");
632 
633   //---------- get Blast blocks
634   fpath = find_file (BLAST_BLOCK_FILE, GRAPHICS_DIR, USE_THEME, CRITICAL);
635   Load_Block (fpath, 0, 0, NULL, INIT_ONLY);
636   for (line = 0; line <  ALLBLASTTYPES; line ++)
637     for (col = 0; col < Blastmap[line].phases; col ++)
638       {
639 	FreeIfUsed (Blastmap[line].SurfacePointer[col]);
640 	Blastmap[line].SurfacePointer[col] = Load_Block (NULL, line, col, &OrigBlock_Rect, 0);
641       }
642   printf_SDL (ne_screen, -1, -1, ".");
643   //---------- get Digit blocks
644   fpath = find_file (DIGIT_BLOCK_FILE, GRAPHICS_DIR, USE_THEME, CRITICAL);
645   Load_Block (fpath, 0, 0, NULL, INIT_ONLY);
646   for (col = 0; col < 10; col++)
647     {
648       FreeIfUsed (InfluDigitSurfacePointer[col]);
649       InfluDigitSurfacePointer[col] = Load_Block (NULL, 0, col, &OrigDigit_Rect, 0);
650       FreeIfUsed (EnemyDigitSurfacePointer[col]);
651       EnemyDigitSurfacePointer[col] = Load_Block (NULL, 0, col + 10, &OrigDigit_Rect, 0);
652     }
653   printf_SDL (ne_screen, -1, -1, ".");
654 
655   //---------- get Takeover pics
656   GetTakeoverGraphics ();
657   printf_SDL (ne_screen, -1, -1, ".");
658 
659   FreeIfUsed(ship_on_pic);
660   ship_on_pic = IMG_Load (find_file (SHIP_ON_PIC_FILE, GRAPHICS_DIR, USE_THEME, CRITICAL));
661   FreeIfUsed(ship_off_pic);
662   ship_off_pic= IMG_Load (find_file (SHIP_OFF_PIC_FILE, GRAPHICS_DIR, USE_THEME, CRITICAL));
663 
664   // the following are not theme-specific and are therefore only loaded once!
665   if (first_call)
666     {
667       //  create the tmp block-build storage
668       tmp = SDL_CreateRGBSurface( 0 , Block_Rect.w, Block_Rect.h, screen_bpp, 0, 0, 0, 0);
669       BuildBlock = SDL_DisplayFormatAlpha (tmp);
670       SDL_FreeSurface (tmp);
671 
672       // takeover pics
673       fpath = find_file (TAKEOVER_BG_PIC_FILE, GRAPHICS_DIR, NO_THEME, CRITICAL);
674       takeover_bg_pic = Load_Block (fpath, 0, 0, NULL, 0);
675       // cursor shapes
676       arrow_cursor = init_system_cursor (arrow_xpm);
677       crosshair_cursor = init_system_cursor (crosshair_xpm);
678       //---------- get Console pictures
679       fpath = find_file (CONSOLE_PIC_FILE, GRAPHICS_DIR, NO_THEME, CRITICAL);
680       console_pic = Load_Block (fpath, 0, 0, NULL, 0);
681       fpath = find_file (CONSOLE_BG_PIC1_FILE, GRAPHICS_DIR, NO_THEME, CRITICAL);
682       console_bg_pic1 = Load_Block (fpath, 0, 0, NULL, 0);
683       fpath = find_file (CONSOLE_BG_PIC2_FILE, GRAPHICS_DIR, NO_THEME, CRITICAL);
684       console_bg_pic2 = Load_Block (fpath, 0, 0, NULL, 0);
685       printf_SDL (ne_screen, -1, -1, ".");
686       arrow_up = IMG_Load (find_file ("arrow_up.png", GRAPHICS_DIR, NO_THEME, CRITICAL) );
687       arrow_down = IMG_Load (find_file ("arrow_down.png", GRAPHICS_DIR, NO_THEME, CRITICAL) );
688       arrow_right = IMG_Load (find_file ("arrow_right.png", GRAPHICS_DIR, NO_THEME, CRITICAL) );
689       arrow_left = IMG_Load (find_file ("arrow_left.png", GRAPHICS_DIR, NO_THEME, CRITICAL) );
690       //---------- get Banner
691       fpath = find_file (BANNER_BLOCK_FILE, GRAPHICS_DIR, NO_THEME, CRITICAL);
692       banner_pic = Load_Block (fpath, 0, 0, NULL, 0);
693       printf_SDL (ne_screen, -1, -1, ".");
694       //---------- get Droid images ----------
695       for (i=0; i<NUM_DROIDS; i++)
696 	{
697 	  // first check if we find a file with rotation-frames: first try .jpg
698 	  strcpy( fname, Druidmap[i].druidname );
699 	  strcat( fname , ".jpg" );
700 	  fpath = find_file (fname, GRAPHICS_DIR, NO_THEME, IGNORE);
701 	  // then try with .png
702 	  if (!fpath)
703 	    {
704 	      strcpy( fname, Druidmap[i].druidname );
705 	      strcat( fname , ".png" );
706 	      fpath = find_file (fname, GRAPHICS_DIR, NO_THEME, CRITICAL);
707 	    }
708 
709 	  packed_portraits[i] = load_raw_pic (fpath);
710 	}
711 
712       // we need the 999.png in any case for transparency!
713       strcpy( fname, Druidmap[DRUID999].druidname );
714       strcat( fname , ".png" );
715       fpath = find_file (fname, GRAPHICS_DIR, NO_THEME, CRITICAL);
716       pic999 = Load_Block (fpath, 0, 0, NULL, 0);
717 
718       // get the Ashes pics
719       strcpy (fname, "Ashes.png");
720       fpath = find_file (fname, GRAPHICS_DIR, NO_THEME, WARNONLY);
721       if (!fpath)
722 	{
723 	  DebugPrintf (0, "WARNING: deactivated display of droid-decals\n");
724 	  GameConfig.ShowDecals = FALSE;
725       }
726       else
727 	{
728 	  Load_Block (fpath, 0, 0, NULL, INIT_ONLY);
729 	  Decal_pics[0] = Load_Block (NULL, 0, 0, &OrigBlock_Rect, 0);
730 	  Decal_pics[1] = Load_Block (NULL, 0, 1, &OrigBlock_Rect, 0);
731 	}
732 
733     } // if first_call
734 
735   printf_SDL (ne_screen, -1, -1, " ok\n");
736 
737   // if scale != 1 then we need to rescale everything now
738   ScaleGraphics (GameConfig.scale);
739 
740   // make sure bullet-surfaces get re-generated!
741   for ( i = 0 ; i < MAXBULLETS ; i++ )
742     AllBullets[i].Surfaces_were_generated = FALSE ;
743 
744   SetCurrentFont (oldfont);
745 
746   first_call = FALSE;
747 
748   return (TRUE);
749 
750 }  // InitPictures
751 
752 
753 /*----------------------------------------------------------------------
754  * load a pic into memory and return the SDL_RWops pointer to it
755  *----------------------------------------------------------------------*/
756 SDL_RWops *
load_raw_pic(char * fpath)757 load_raw_pic (char *fpath)
758 {
759     struct stat statbuf;
760     FILE *fp;
761     off_t size;
762     void *mem;
763 
764     // sanity check
765     if (!fpath)
766       {
767 	DebugPrintf (0, "ERROR: load_raw_pic() called with NULL argument!\n");
768 	Terminate (ERR);
769       }
770 
771     fp = fopen (fpath, "rb");
772     if (!fp)
773       {
774 	DebugPrintf (0, "ERROR: could not open file %s. Giving up\n", fpath);
775 	Terminate (ERR);
776       }
777 
778     size = FS_filelength (fp);
779     mem = MyMalloc (size);
780     if (fread (mem, 1, size, fp) != size)
781       {
782 	DebugPrintf (0, "ERROR reading file %s. Giving up...\n", fpath);
783 	Terminate (ERR);
784       }
785     fclose (fp);
786 
787 
788     return (SDL_RWFromMem(mem, size) );
789 
790 }
791 
792 
793 /*------------------------------------------------------------
794  * General block-reading routine: get block from pic-file
795  *
796  * fpath: full pathname of picture-file; if NULL: use previous SDL-surf
797  * line, col: block-position in pic-file to read block from
798  * block: dimension of blocks to consider: if NULL: copy whole pic
799  * 	  NOTE: only w and h of block are used!!
800  *
801  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
802  * NOTE: to avoid memory-leaks, use (flags | INIT_ONLY) if you only
803  *       call this function to set up a new pic-file to be read.
804  *       This will avoid copying & mallocing a new pic, NULL will be returned
805  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
806  *------------------------------------------------------------*/
807 SDL_Surface *
Load_Block(char * fpath,int line,int col,SDL_Rect * block,int flags)808 Load_Block (char *fpath, int line, int col, SDL_Rect * block, int flags)
809 {
810   static SDL_Surface *pic = NULL;
811   SDL_Surface *tmp;
812   SDL_Rect src, dim;
813   SDL_Surface *ret;
814   int usealpha;
815 
816   if (!fpath && !pic)		/* we need some info.. */
817     return (NULL);
818 
819   if (fpath) // initialize: read & malloc new pic, dont' return a copy!!
820     {
821       if (pic)  // previous pic?
822 	SDL_FreeSurface (pic);
823       pic = IMG_Load (fpath);
824 
825     }
826 
827   if ( (flags & INIT_ONLY) != FALSE )
828     return (NULL); // that's it guys, only initialzing...
829 
830   if (!block)
831     {
832       Set_Rect (dim, 0, 0, pic->w, pic->h);
833     }
834   else
835     {
836       Set_Rect (dim, 0, 0, block->w, block->h);
837     }
838 
839   if (pic->format->Amask != 0)
840     usealpha = TRUE;
841   else
842     usealpha = FALSE;
843 
844   if (usealpha)
845     SDL_SetAlpha (pic, 0, 0);	/* clear per-surf alpha for internal blit */
846   tmp = SDL_CreateRGBSurface (0, dim.w, dim.h, screen_bpp, 0, 0, 0, 0);
847   if (usealpha)
848     ret = SDL_DisplayFormatAlpha (tmp);
849   else
850     ret = SDL_DisplayFormat (tmp);
851   SDL_FreeSurface (tmp);
852 
853   Set_Rect (src, col * (dim.w + 2), line * (dim.h + 2), dim.w, dim.h);
854   SDL_BlitSurface (pic, &src, ret, NULL);
855   if (usealpha)
856     SDL_SetAlpha (ret, SDL_SRCALPHA | SDL_RLEACCEL, SDL_ALPHA_OPAQUE);
857 
858   return (ret);
859 
860 } // Load_Block()
861 
862 
863 /*-----------------------------------------------------------------
864  * Initialise the Video display and graphics engine
865  *
866  *
867  *-----------------------------------------------------------------*/
868 void
Init_Video(void)869 Init_Video (void)
870 {
871   char vid_driver[81];
872   Uint32 flags;  /* flags for SDL video mode */
873   char *fpath;
874 
875   /* Initialize the SDL library */
876   // if ( SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1 )
877 
878   if ( SDL_Init (SDL_INIT_VIDEO) == -1 )
879     {
880       fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
881       Terminate(ERR);
882     } else
883       DebugPrintf(1, "\nSDL Video initialisation successful.\n");
884 
885   // Now SDL_TIMER is initialized here:
886 
887   if ( SDL_InitSubSystem ( SDL_INIT_TIMER ) == -1 )
888     {
889       fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
890       Terminate(ERR);
891     } else
892       DebugPrintf(1, "\nSDL Timer initialisation successful.\n");
893 
894   /* clean up on exit */
895   atexit (SDL_Quit);
896 
897 
898   vid_info = SDL_GetVideoInfo (); /* just curious */
899   SDL_VideoDriverName (vid_driver, 80);
900 
901   //  flags = SDL_HWSURFACE | SDL_DOUBLEBUF;
902   flags = 0;
903   if (GameConfig.UseFullscreen) flags |= SDL_FULLSCREEN;
904 
905   if (vid_info->wm_available)  /* if there's a window-manager */
906     {
907       SDL_WM_SetCaption ("Freedroid", "");
908       fpath = find_file (ICON_FILE, GRAPHICS_DIR, NO_THEME, WARNONLY);
909       if (fpath) SDL_WM_SetIcon( IMG_Load (fpath), NULL);
910     }
911 
912   screen_bpp = 16; /* start with the simplest */
913 
914   if( !(ne_screen = SDL_SetVideoMode ( Screen_Rect.w, Screen_Rect.h , 0 , flags)) )
915     {
916       DebugPrintf (0, "ERORR: Couldn't set %d x %d video mode. SDL: %s\n",
917 		   Screen_Rect.w, Screen_Rect.h, SDL_GetError());
918       exit(-1);
919     }
920 
921   vid_info = SDL_GetVideoInfo (); /* info about current video mode */
922 
923   DebugPrintf(1, "Got video mode: ");
924 
925   SDL_SetGamma( 1 , 1 , 1 );
926   GameConfig.Current_Gamma_Correction=1;
927 
928   return;
929 
930 } /* InitVideo () */
931 
932 /*@Function============================================================
933 @Desc:
934 
935 @Ret:
936 @Int:
937 * $Function----------------------------------------------------------*/
938 void
ClearGraphMem(void)939 ClearGraphMem ( void )
940 {
941   // One this function is done, the rahmen at the
942   // top of the screen surely is destroyed.  We inform the
943   // DisplayBanner function of the matter...
944   BannerIsDestroyed=TRUE;
945 
946   //
947   SDL_SetClipRect( ne_screen, NULL );
948 
949   // Now we fill the screen with black color...
950   SDL_FillRect( ne_screen , NULL , 0 );
951   SDL_Flip (ne_screen);
952 
953   return;
954 } // ClearGraphMem( void )
955 
956 
957 /*----------------------------------------------------------------------
958  * Return the pixel value at (x, y)
959  * NOTE: The surface must be locked before calling this!
960  *----------------------------------------------------------------------*/
961 Uint32
getpixel(SDL_Surface * surface,int x,int y)962 getpixel(SDL_Surface *surface, int x, int y)
963 {
964   int bpp = surface->format->BytesPerPixel;
965   /* Here p is the address to the pixel we want to retrieve */
966   Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
967 
968   switch(bpp)
969     {
970     case 1:
971       return *p;
972 
973     case 2:
974       return *(Uint16 *)p;
975 
976     case 3:
977       if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
978 	return p[0] << 16 | p[1] << 8 | p[2];
979       else
980 	return p[0] | p[1] << 8 | p[2] << 16;
981 
982     case 4:
983       return *(Uint32 *)p;
984 
985     default:
986       return 0;       /* shouldn't happen, but avoids warnings */
987     }
988 
989 } // Uint32 getpixel(...)
990 
991 
992 /*
993  * Set the pixel at (x, y) to the given value
994  * NOTE: The surface must be locked before calling this!
995  */
putpixel(SDL_Surface * surface,int x,int y,Uint32 pixel)996 void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
997 {
998     int bpp = surface->format->BytesPerPixel;
999     /* Here p is the address to the pixel we want to set */
1000     Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
1001 
1002     switch(bpp) {
1003     case 1:
1004         *p = pixel;
1005         break;
1006 
1007     case 2:
1008         *(Uint16 *)p = pixel;
1009         break;
1010 
1011     case 3:
1012         if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1013             p[0] = (pixel >> 16) & 0xff;
1014             p[1] = (pixel >> 8) & 0xff;
1015             p[2] = pixel & 0xff;
1016         } else {
1017             p[0] = pixel & 0xff;
1018             p[1] = (pixel >> 8) & 0xff;
1019             p[2] = (pixel >> 16) & 0xff;
1020         }
1021         break;
1022 
1023     case 4:
1024         *(Uint32 *)p = pixel;
1025         break;
1026     }
1027 } // void putpixel(...)
1028 
1029 /*----------------------------------------------------------------------
1030  *
1031  *----------------------------------------------------------------------*/
1032 int
Load_Fonts(void)1033 Load_Fonts (void)
1034 {
1035   char *fpath;
1036 
1037   fpath = find_file (PARA_FONT_FILE, GRAPHICS_DIR, NO_THEME, CRITICAL);
1038   if ( ( Para_BFont = LoadFont (fpath, GameConfig.scale) ) == NULL )
1039     {
1040       DebugPrintf (0, "ERROR: font file named %s was not found.\n", PARA_FONT_FILE );
1041       Terminate(ERR);
1042     } else
1043       DebugPrintf(1, "\nSDL Para Font initialisation successful.\n");
1044 
1045   Menu_BFont = Para_BFont;
1046 
1047   fpath = find_file (FPS_FONT_FILE, GRAPHICS_DIR, NO_THEME, CRITICAL);
1048   if ( ( FPS_Display_BFont = LoadFont (fpath, GameConfig.scale) ) == NULL )
1049     {
1050       DebugPrintf (0, "ERROR: font file named %s was not found.\n", FPS_FONT_FILE);
1051       Terminate(ERR);
1052     } else
1053       DebugPrintf(1, "\nSDL FPS Display Font initialisation successful.\n");
1054 
1055   /* choose a font for highscore displaying... */
1056   Highscore_BFont = Para_BFont;
1057 
1058   return (OK);
1059 } // Load_Fonts ()
1060 
1061 //------------------------------------------------------------
1062 // display "white noise" effect in Rect.
1063 // algorith basically stolen from
1064 // Greg Knauss's "xteevee" hack in xscreensavers.
1065 //
1066 // timeout is in ms
1067 //------------------------------------------------------------
1068 #define NOISE_COLORS 6
1069 #define NOISE_TILES 8
1070 
1071 void
white_noise(SDL_Surface * bitmap,SDL_Rect * rect,int timeout)1072 white_noise (SDL_Surface *bitmap, SDL_Rect *rect, int timeout)
1073 {
1074   int i;
1075   int x, y;
1076   int signal_strengh = 60;
1077   Uint32 grey[NOISE_COLORS];
1078   Uint8 color;
1079   SDL_Surface *tmp, *tmp2;
1080   SDL_Surface *noise_tiles[NOISE_TILES];
1081   SDL_Rect clip_rect;
1082   char used_tiles[NOISE_TILES/2+1];
1083   int next_tile;
1084   int now;
1085 
1086   for (i=0; i< NOISE_COLORS; i++)
1087     {
1088       color = (Uint8)(((double)(i+1.0)/NOISE_COLORS)*255.0);
1089       grey[i] = SDL_MapRGB(ne_screen->format, color, color, color);
1090     }
1091 
1092   // produce the tiles
1093   tmp = SDL_CreateRGBSurface(0, rect->w, rect->h, screen_bpp, 0, 0, 0, 0);
1094   tmp2 = SDL_DisplayFormat (tmp);
1095   SDL_FreeSurface (tmp);
1096   SDL_BlitSurface (bitmap, rect, tmp2, NULL);
1097   //  printf_SDL (ne_screen, rect->x + 10, rect->y + rect->h/2, "Preparing noise-tiles ");
1098   for (i=0; i< NOISE_TILES; i++)
1099     {
1100       noise_tiles[i] = SDL_DisplayFormat(tmp2);
1101 
1102       for (x = 0; x < rect->w; x++)
1103 	for (y = 0; y < rect->h; y++)
1104 	  if (rand()%100 > signal_strengh)
1105 	    PutPixel (noise_tiles[i], x, y, grey[rand()%NOISE_COLORS]);
1106 
1107       //      printf_SDL (ne_screen, -1, -1, " %d", i+1);
1108       //      SDL_BlitSurface (noise_tiles[i], NULL, ne_screen, rect);
1109       //      SDL_UpdateRect (ne_screen, rect->x, rect->y, rect->w, rect->h);
1110     }
1111   SDL_FreeSurface (tmp2);
1112 
1113   memset(used_tiles,-1, sizeof(used_tiles));
1114   // let's go
1115   Play_Sound (WHITE_NOISE);
1116 
1117   now = SDL_GetTicks();
1118 
1119   while (1)
1120     {
1121       // pick an old enough tile
1122       do
1123 	{
1124 	  next_tile = rand()%NOISE_TILES;
1125 	  for (i = 0; i < sizeof(used_tiles); i++)
1126 	    {
1127 	      if (next_tile == used_tiles[i])
1128 		{
1129 		  next_tile = -1;
1130 		  break;
1131 		}
1132 	    }
1133 	} while (next_tile == -1);
1134       memmove(used_tiles,used_tiles+1,sizeof(used_tiles)-1);
1135       used_tiles[sizeof(used_tiles)-1] = next_tile;
1136 
1137       // make sure we can blit the full rect without clipping! (would change *rect!)
1138       SDL_GetClipRect (ne_screen, &clip_rect);
1139       SDL_SetClipRect (ne_screen, NULL);
1140       // set it
1141       SDL_BlitSurface (noise_tiles[next_tile], NULL, ne_screen, rect);
1142       SDL_UpdateRect (ne_screen, rect->x, rect->y, rect->w, rect->h);
1143       SDL_Delay(25);
1144 
1145       if ( (timeout && (SDL_GetTicks()-now > timeout)))
1146 	break;
1147 
1148     } // while (! finished)
1149 
1150   //restore previous clip-rectange
1151   SDL_SetClipRect (ne_screen, &clip_rect);
1152 
1153   for (i=0; i<NOISE_TILES; i++)
1154     SDL_FreeSurface (noise_tiles[i]);
1155 
1156   return;
1157 }
1158 
1159 /*----------------------------------------------------------------------
1160  * ScaleGraphics ()
1161  *----------------------------------------------------------------------*/
1162 void
ScaleGraphics(float scale)1163 ScaleGraphics (float scale)
1164 {
1165   static bool first_call = TRUE;
1166   SDL_Surface *tmp;
1167   int line, col, i, j;
1168 
1169   if (scale == 1.0)
1170     return;
1171 
1172   // these are reset in a theme-change by the theme-config-file
1173   // therefore we need to rescale them each time again
1174   ScaleRect (FirstDigit_Rect, scale);
1175   ScaleRect (SecondDigit_Rect, scale);
1176   ScaleRect (ThirdDigit_Rect, scale);
1177 
1178 
1179   // note: only rescale these rects the first time!!
1180   if (first_call)
1181     ScaleStatRects (scale);
1182 
1183   printf_SDL (ne_screen, User_Rect.x + 50, -1, "Rescaling graphics ...");
1184 
1185   //---------- rescale Map blocks
1186   for (line = 0; line < NUM_COLORS; line ++)
1187     for (col = 0; col < NUM_MAP_BLOCKS; col ++)
1188       {
1189 	ScalePic( &OrigMapBlockSurfacePointer[line][col], scale);
1190 	MapBlockSurfacePointer[line][col] = OrigMapBlockSurfacePointer[line][col];
1191       }
1192   printf_SDL (ne_screen, -1, -1, ".");
1193   //---------- rescale Droid-model  blocks
1194   for (col = 0; col < DROID_PHASES; col ++)
1195     {
1196       ScalePic (&InfluencerSurfacePointer[col], scale);
1197       ScalePic (&EnemySurfacePointer[col], scale);
1198       /* Droid pics are only used in _internal_ blits ==> clear per-surf alpha */
1199       SDL_SetAlpha (InfluencerSurfacePointer[col], 0, 0);
1200       SDL_SetAlpha (EnemySurfacePointer[col], 0, 0);
1201     }
1202 
1203   printf_SDL (ne_screen, -1, -1, ".");
1204   //---------- rescale Bullet blocks
1205   for (line = 0; line < Number_Of_Bullet_Types; line ++)
1206     for (col = 0; col < Bulletmap[line].phases; col ++)
1207       ScalePic( &Bulletmap[line].SurfacePointer[col], scale);
1208 
1209   printf_SDL (ne_screen, -1, -1, ".");
1210 
1211   //---------- rescale Blast blocks
1212   for (line = 0; line <  ALLBLASTTYPES; line ++)
1213     for (col = 0; col < Blastmap[line].phases; col ++)
1214       ScalePic (&Blastmap[line].SurfacePointer[col], scale);
1215 
1216   printf_SDL (ne_screen, -1, -1, ".");
1217   //---------- rescale Digit blocks
1218   for (col = 0; col < 10; col++)
1219     {
1220       ScalePic (&InfluDigitSurfacePointer[col], scale);
1221       ScalePic (&EnemyDigitSurfacePointer[col], scale);
1222       /* Digits are only used in _internal_ blits ==> clear per-surf alpha */
1223       SDL_SetAlpha (InfluDigitSurfacePointer[col], 0, 0);
1224       SDL_SetAlpha (EnemyDigitSurfacePointer[col], 0, 0);
1225     }
1226   printf_SDL (ne_screen, -1, -1, ".");
1227 
1228   //---------- rescale Takeover pics
1229   ScalePic (&to_blocks, scale);
1230   printf_SDL (ne_screen, -1, -1, ".");
1231 
1232   ScalePic (&ship_on_pic, scale);
1233   ScalePic (&ship_off_pic, scale);
1234 
1235   // the following are not theme-specific and are therefore only loaded once!
1236   if (first_call)
1237     {
1238       //  create a new tmp block-build storage
1239       FreeIfUsed (BuildBlock);
1240       tmp = SDL_CreateRGBSurface( 0 , Block_Rect.w, Block_Rect.h, screen_bpp, 0, 0, 0, 0);
1241       BuildBlock = SDL_DisplayFormatAlpha (tmp);
1242       SDL_FreeSurface (tmp);
1243 
1244       // takeover pics
1245       ScalePic (&takeover_bg_pic, scale);
1246 
1247       //---------- Console pictures
1248       ScalePic (&console_pic, scale);
1249       ScalePic (&console_bg_pic1, scale);
1250       ScalePic (&console_bg_pic2, scale);
1251       ScalePic (&arrow_up, scale);
1252       ScalePic (&arrow_down, scale);
1253       ScalePic (&arrow_right, scale);
1254       ScalePic (&arrow_left, scale);
1255       //---------- Banner
1256       ScalePic (&banner_pic, scale);
1257 
1258       //---------- Droid images ----------
1259       // FIXME: this still needs to be done!!!!
1260       for (i=0; i<NUM_DROIDS; i++)
1261 	{
1262 	  //	  packed_portraits[i] = load_raw_pic (fpath);
1263 	}
1264 
1265       // we need the 999.png in any case for transparency!
1266       ScalePic (&pic999, scale);
1267 
1268       // get the Ashes pics
1269       if (Decal_pics[0]) ScalePic (&Decal_pics[0], scale);
1270       if (Decal_pics[1]) ScalePic (&Decal_pics[1], scale);
1271 
1272     } // if first_call
1273 
1274   printf_SDL (ne_screen, -1, -1, " ok\n");
1275 
1276   first_call = FALSE;
1277 
1278   return;
1279 
1280 } // ScaleGraphics()
1281 
1282 /*----------------------------------------------------------------------
1283  *
1284  *----------------------------------------------------------------------*/
1285 void
ScalePic(SDL_Surface ** pic,float scale)1286 ScalePic (SDL_Surface **pic, float scale)
1287 {
1288   SDL_Surface *tmp;
1289 
1290   if (scale == 1.0)
1291     return;
1292 
1293   tmp = *pic;
1294   *pic = zoomSurface (tmp, scale, scale, 0);
1295   SDL_FreeSurface (tmp);
1296 
1297   return;
1298 
1299 } // ScalePic ()
1300 
1301 /*----------------------------------------------------------------------
1302  * scale all "static" rectangle
1303  *----------------------------------------------------------------------*/
1304 void
ScaleStatRects(float scale)1305 ScaleStatRects (float scale)
1306 {
1307   int i, j;
1308 
1309   ScaleRect (Block_Rect, scale);
1310   ScaleRect (User_Rect, scale);
1311   ScaleRect (Classic_User_Rect, scale);
1312   ScaleRect (Full_User_Rect, scale);
1313   ScaleRect (Banner_Rect, scale);
1314   ScaleRect (Portrait_Rect, scale);
1315   ScaleRect (Cons_Droid_Rect, scale);
1316   ScaleRect (Menu_Rect, scale);
1317   ScaleRect (OptionsMenu_Rect, scale);
1318   ScaleRect (Digit_Rect, scale);
1319   ScaleRect (Cons_Header_Rect, scale);
1320   ScaleRect (Cons_Menu_Rect, scale);
1321   ScaleRect (Cons_Text_Rect, scale);
1322 
1323   ScaleRect (Cons_Menu_Rects[0], scale);
1324   ScaleRect (Cons_Menu_Rects[1], scale);
1325   ScaleRect (Cons_Menu_Rects[2], scale);
1326   ScaleRect (Cons_Menu_Rects[3], scale);
1327 
1328   ScaleRect (ConsMenuItem_Rect, scale);
1329 
1330   ScaleRect (LeftInfo_Rect, scale);
1331   ScaleRect (RightInfo_Rect, scale);
1332 
1333   for (i=0; i<NUM_FILL_BLOCKS; i++)
1334     ScaleRect (FillBlocks[i], scale);
1335 
1336   for (i = 0; i < NUM_CAPS_BLOCKS; i++)
1337     ScaleRect (CapsuleBlocks[i], scale);
1338 
1339   for (j = 0; j < 2*NUM_PHASES; j++)
1340     for (i = 0; i < TO_BLOCKS; i++)
1341       ScaleRect (ToGameBlocks[j*TO_BLOCKS+i], scale);
1342 
1343   for (i = 0; i < NUM_GROUND_BLOCKS; i++)
1344     ScaleRect (ToGroundBlocks[i], scale);
1345 
1346   ScaleRect (ToColumnBlock, scale);
1347   ScaleRect (ToLeaderBlock, scale);
1348 
1349 
1350   for (i=0; i < TO_COLORS; i++)
1351     {
1352       ScalePoint (LeftCapsulesStart[i],scale);
1353       ScalePoint (CurCapsuleStart[i],scale);
1354       ScalePoint (PlaygroundStart[i],scale);
1355       ScalePoint (DruidStart[i],scale);
1356     }
1357   ScalePoint (TO_LeftGroundStart, scale);
1358   ScalePoint (TO_ColumnStart, scale);
1359   ScalePoint (TO_RightGroundStart, scale);
1360   ScalePoint( TO_LeaderBlockStart, scale);
1361 
1362   ScaleRect (TO_FillBlock, scale);
1363   ScaleRect (TO_ElementRect, scale);
1364   ScaleRect (TO_CapsuleRect, scale);
1365   ScaleRect (TO_LeaderLed, scale);
1366   ScaleRect (TO_GroundRect, scale);
1367   ScaleRect (TO_ColumnRect, scale);
1368 
1369   return;
1370 
1371 } // ScaleStatRects()
1372 
1373 
1374 
1375 #undef _graphics_c
1376