1 /**
2  * @file handler_resources.cc
3  * @brief Handler of the files resources
4  * @created 2004-04-20
5  * @date 2014-07-20
6  * @copyright 1991-2014 TLK Games
7  * @author Bruno Ethvignot
8  * @version $Revision: 24 $
9  */
10 /*
11  * copyright (c) 1991-2014 TLK Games all rights reserved
12  * $Id: handler_resources.cc 24 2014-09-28 15:30:04Z bruno.ethvignot@gmail.com $
13  *
14  * TecnoballZ is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * TecnoballZ is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27  * MA  02110-1301, USA.
28  */
29 #include "../include/handler_resources.h"
30 #include "../include/bitmap_data.h"
31 #include "../config.h"
32 #include <string>
33 #include <fstream>
34 
35 #ifndef DATADIR
36 #define DATADIR "/usr/share/games/tecnoballz"
37 #endif
38 
39 #ifndef SCOREFILE
40 #define SCOREFILE "/var/lib/games/tecnoballz.hi"
41 #endif
42 
43 #ifdef _WIN32
44 #ifndef _S_ISDIR
45 #define _S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
46 #endif
47 #endif
48 
49 handler_resources *
50 handler_resources::handler_resources_singleton = NULL;
51 
52 const char * handler_resources::fnamescore = SCOREFILE;
53 const char *
54   handler_resources::folder_640 = "hires/";
55 const char *
56   handler_resources::folder_320 = "lores/";
57 char
58   handler_resources::tmp_filename[512];
59 char
60   handler_resources::pathstring[512];
61 
62 const char *
63   handler_resources::standfiles[] = {
64   "cosinus128.list",            //RESCOSLIST
65   /* MAP_GUARDIANS_20 */
66   "tilemap-guardians_20.data",
67   "tilemap-guardians_40.data",
68   /* MAP_CONGRATULATIONS_20 */
69   "tilemap-congratulation_20.data",
70   "tilemap-congratulation_40.data",
71   /* MAP_MENU_20 */
72   "tilemap-menu_20.data",
73   "tilemap-menu_40.data",
74   "gard_lissa.list",            //RESGCURVES
75   /* DATA_BRICKS_LEVELS */
76   "tableau.data",
77   "min60map.png",                //RES60BACKG
78   /* DATA_LEVELS */
79   "levels-data.xml"
80 };
81 
82 const char *
83   handler_resources::musicfiles[] = {
84   "area1-game2.mod",
85   "area2-game.mod",
86   "area3-game.mod",
87   "area4-game.mod",
88   "area5-game.mod",
89   "gardien-go.mod",
90   "high-score.mod",
91   "over-theme.mod",
92   "tecnoballz.mod",
93   "tecno-winn.mod",
94   "termigator_reg-zbb.mod",
95   "in-game-music-1_reg.mod",
96   "fridge-in-space_from_reg-zbb.mod",
97   "mon-lapin_reg-zbb.mod"
98 };
99 
100 const char *
101   handler_resources::soundfiles[] = { "rlife_moins.wav",        // 01
102   "rexplo_rak.wav",
103   "rlife_plus.wav",
104   "rmoney.wav",
105   "ralarm.wav",                 //05
106   "rgadget_sound.wav",
107   "rtecno.wav",
108   "rappar.wav",
109   "rtransfo.wav",
110   "rtir_monstre.wav",           //10
111   "rtir_rak.wav",
112   "rexplo_big.wav",
113   "rdetruit_indes.wav",
114   "rexeplo_atom.wav",
115   "rmontre_touche.wav",         //15
116   "ratom.wav",
117   "rindes_1.wav",
118   "rindes_2.wav",
119   "rraquette.wav",
120   "rbricote.wav",               //20
121   "rbrique1.wav",
122   "rbrique2.wav",
123   "rbrique3.wav",
124   "rbrique4.wav",
125   "rbrique5.wav",               //25
126   "raspire.wav",
127   "reject.wav",                 //27
128 };
129 
130 const char * handler_resources::bitmap_files[] =
131 {
132   /* BITMAP_HEAD_ANIMATION */
133   "head_animation.png",
134   /* BITMAP_RIGHT_PANEL */
135   "right_panel.png",
136   /* BITMAP_PADDLES_1 */
137   "paddles_1.png",
138   /* BITMAP_PADDLES_2 */
139   "paddles_2.png",
140   /* BITMAP_GAME_FONTS */
141   "game_fonts.png",
142   /* BITMAP_MENU_FONTS */
143   "menu_fonts.png",
144   /* BITMAP_SMALL_FONTS */
145   "small_fonts.png",
146   /* BITMAP_GIGABLITZ */
147   "gigablitz.png",
148   /* BITMAP_TILESMAP */
149   "tilesmap.png",
150   /* BITMAP_SHOP */
151   "shop.png",
152   /* BITMAP_ALL_SPRITES */
153   "all_sprites.png",
154   /* BITMAP_BRICKS */
155   "bricks.png",
156   /* BITMAP_SCORES_FONTS */
157   "font_score.png"
158 };
159 
160 const char * handler_resources::texts_files[] =
161 {
162   /* TEXTS_SHOP */
163   "shop_%s.txt",
164   /* TEXTS_MESSAGES */
165   "short_info_messages_%s.txt",
166   /* TEXTS_SCROLL_MENU */
167   "scrolltext_%s.txt",
168   /* TEXTS_POPUP_MENU */
169   "popup_menu_%s.txt",
170   /* TEXTS_MAIN_MENU */
171   "main_menu_%s.txt"
172 };
173 
174 //char handler_resources::ze_mapfile[] = "map??.png";
175 
176 /**
177  * Create the resources manager object
178  */
handler_resources()179 handler_resources::handler_resources ()
180 {
181   last_filesize_loaded = 0;
182   set_filesize_loaded(0);
183 }
184 
185 /**
186  * Get the object instance
187  * handler_resources is a singleton
188  * @return the handler_resources object
189  */
190 handler_resources *
get_instance()191 handler_resources::get_instance ()
192 {
193   if (NULL == handler_resources_singleton)
194     {
195       handler_resources_singleton = new handler_resources ();
196     }
197   return handler_resources_singleton;
198 }
199 
200 /**
201  * Release the resources manager object
202  */
~handler_resources()203 handler_resources::~handler_resources ()
204 {
205   if (table_cosL != NULL)
206     {
207       delete[](char *)table_cosL;
208       table_cosL = (Sint16 *) NULL;
209     }
210   release_sprites_bitmap ();
211 }
212 
213 /**
214  * Load a resources file in memory
215  * @param resource_id resource identifier of the data
216  * @return file data buffer pointer
217  */
218 char *
load_data(Uint32 resource_id)219 handler_resources::load_data (Uint32 resource_id)
220 {
221   char *filename = get_filename (resource_id);
222   return load_file (filename);
223 }
224 
225 /**
226  * Return valid name from a resource identifier
227  * @param resource_id resource identifier
228  * @param resolution 0 default, 1 = 320 or 2 640,
229  * @return filename with a relative pathname
230  */
231 char *
get_filename(Uint32 resource_id,Uint32 res)232 handler_resources::get_filename (Uint32 resource_id, Uint32 res)
233 {
234   const char *pfile;
235   if (resource_id >= BITMAP_OFFSET)
236     {
237       if (0 == res)
238         {
239           res = resolution;
240         }
241       resource_id -= BITMAP_OFFSET;
242       pfile = bitmap_files[resource_id];
243       if (1 == res)
244         {
245           strcpy (tmp_filename, folder_320);
246         }
247       else
248         {
249           strcpy (tmp_filename, folder_640);
250         }
251       strcat (tmp_filename, pfile);
252     }
253   else
254     {
255       pfile = standfiles[resource_id];
256       strcpy (tmp_filename, pfile);
257     }
258   return tmp_filename;
259 }
260 
261 /**
262  * Return valid music filename from a resource identifier
263  * @param resource_id resource identifier of the music
264  * @return music filename with a relative pathname
265  */
266 char *
get_music_filename(Uint32 resource_id)267 handler_resources::get_music_filename (Uint32 resource_id)
268 {
269   const char *pfile;
270   strcpy (tmp_filename, "musics/");
271   pfile = musicfiles[resource_id];
272   strcat (tmp_filename, pfile);
273   return locate_data_file (tmp_filename);
274 }
275 
276 /**
277  * Return valid sound filename from a resource identifier
278  * @param resource_id resource identifier of the sound
279  * @return sound filename with a relative pathname
280  */
281 char *
get_sound_filename(Uint32 resource_id)282 handler_resources::get_sound_filename (Uint32 resource_id)
283 {
284   strcpy (tmp_filename, "sounds/");
285   strcat (tmp_filename, soundfiles[resource_id]);
286   return locate_data_file (tmp_filename);
287 }
288 
289 /**
290  * Return valid tilemaps filename from a tilemap number
291  * @param title_num filename number from 1 to 78
292  * @return tilemap filename with a relative pathname
293  */
294 char *
get_tilemaps_filename(Uint32 title_num)295 handler_resources::get_tilemaps_filename (Uint32 title_num)
296 {
297   sprintf(tmp_filename, "textures/map%02d.png", title_num);
298   return tmp_filename;
299 }
300 
301 /**
302  * Return the full pathname from a resource identifier
303  * @param resource_id a resource identifier
304  * @return a pointer to the file data buffer
305  */
306 char *
get_full_pathname(Uint32 resource_id)307 handler_resources::get_full_pathname (Uint32 resource_id)
308 {
309   return locate_data_file (get_filename (resource_id));
310 }
311 
312 /**
313  * Directory list to locate a file
314  */
315 const char * handler_resources::folderlist[] =
316 {
317   /* special value meaning "$(PREFIX)/share/games/tecnoballz/" */
318   DATADIR,
319   "/",
320   /* normally unused, except when running from the source directory */
321   "./TecnoballZ/",
322   /* also marks end of list */
323   0
324 };
325 /**
326  * Locate a file under one of the data directories
327  * @param name name of file relative to data directory
328  */
329 char *
locate_data_file(const char * const name)330 handler_resources::locate_data_file (const char *const name)
331 {
332 /*
333   if (is_verbose)
334     {
335       std::
336         cout << "(*) handler_resources::locate_data_file(" << name << ")" << std::
337         endl;
338     }
339  */
340 
341   /* clear path name string */
342   for (Sint32 i = 0; i < 256; i++)
343     pathstring[i] = 0;
344 
345   if (NULL == name)
346     {
347       std::cerr << "(!)handler_resources::locate_data_file() " <<
348         "NULL pointer was passed as an argument!" << std::endl;
349       throw std::ios_base::
350         failure ("[!] handler_resources::locate_data_file "
351                  "NULL pointer was passed as an argument!");
352     }
353 
354   /* if absolute path, return a pointer to a duplicate string */
355   char *pathname;
356   if (*name == '/')
357     {
358       pathname = &pathstring[0];
359       strcpy (pathname, name);
360       return pathname;
361     }
362 
363   /* process each folder of the list */
364   for (const char **p = folderlist;; p++)
365     {
366       if (*p != 0)
367         {
368           /* check if the file is located in current directory */
369           pathname = &pathstring[0];
370           strcpy (pathname, *p);
371           if (pathname[strlen (pathname) - 1] != '/')
372             {
373               strcat (pathname, "/");
374             }
375           strcat (pathname, name);
376 
377         }
378       else
379         {
380           /* file not found, try default folder as last chance */
381           const char *subdir = "/share/games/tecnoballz/";
382           pathname = &pathstring[0];
383           strcpy (pathname, nomprefix);
384           strcat (pathname, subdir);
385           strcat (pathname, name);
386         }
387       /*
388       if (is_verbose)
389         {
390           std::cout << "handler_resources::locate_data_file() try " << pathname << std::endl;
391         }
392       */
393 #ifdef WIN32
394       struct _stat s;
395       if (_stat (pathname, &s) == 0 && !_S_ISDIR (s.st_mode))
396         {
397           return pathname;
398         }
399 #else
400       struct stat s;
401       if (stat (pathname, &s) == 0 && !S_ISDIR (s.st_mode))
402         {
403             /*
404           if (is_verbose)
405             {
406               std::
407                 cout << "handler_resources::locate_data_file(" << pathname <<
408                 ") find!" << std::endl;
409             }
410             */
411           return pathname;
412         }
413 #endif
414       /* end of the list, error file not found! */
415       if (*p == 0)
416         {
417           break;
418         }
419     }
420   std::cerr << "(!)handler_resources::locate_data_file() file '"
421     << name << "' not found!" << std::endl;
422   throw std::ios_base::failure (std::string
423                                 ("[!]handler_resources::locate_data_file() File '")
424                                 + name + std::string ("' not found!"));
425 }
426 
427 /**
428  * Load a bitmap of sprites
429  * @param resource_id resource identifier of the bitmap
430  *                    BITMAP_ALL_SPRITES by default
431  */
432 void
load_sprites_bitmap(Uint32 resource_id)433 handler_resources::load_sprites_bitmap (Uint32 resource_id)
434 {
435   release_sprites_bitmap ();
436   sprites_bitmap = new bitmap_data ();
437   sprites_bitmap->load (resource_id);
438   sprites_bitmap->enable_palette ();
439 }
440 
441 /**
442  * Release the bitmap of sprites
443  */
444 void
release_sprites_bitmap()445 handler_resources::release_sprites_bitmap ()
446 {
447   if (sprites_bitmap != NULL)
448     {
449       delete sprites_bitmap;
450     }
451   sprites_bitmap = (bitmap_data *) NULL;
452 }
453 
454 /**
455  * Load texts data into strings list
456  * @param resource_id resource identifier of the texts data
457  * @param numof_lines number of lines
458  * @param row_length maximum number of chars by string, 0 if preserve the size of
459  *                   the original string
460  * @param modulo 0 if non concatenation, 2 concatene strings 3 by 3
461  * @param upper_case Change from 'a' to 'z' chars by 'A' to 'Z' chars
462  */
463 char **
load_texts(Uint32 resource_id,Uint32 numof_lines,Uint32 row_length,Uint32 modulo,bool upper_case)464 handler_resources::load_texts(Uint32 resource_id, Uint32 numof_lines, Uint32 row_length, Uint32 modulo, bool upper_case)
465 {
466   resource_id -=TEXTS_OFFSET;
467   const char *file = texts_files[resource_id];
468   strcpy (tmp_filename, "texts/");
469   strcat (tmp_filename, file);
470   Uint32 filesize;
471   char *filedata = loadfile_with_lang (tmp_filename, &filesize);
472 
473   /*
474    * caclulate the number of lines
475    */
476   Uint32 offset = 0;
477   bool is_first_row = true;
478   bool is_comment = false;
479   Uint32 row_count = 0;
480   Uint32 alloc_size = 0;
481   Uint32 list_count = 0;
482   Uint32 str_count = 0;
483   while (offset < filesize)
484     {
485       char c = filedata[offset++];
486       row_count++;
487       if (is_first_row && c == '#')
488         {
489           is_comment = true;
490         }
491       is_first_row = false;
492       if (c == '\n')
493         {
494           if (!is_comment)
495             {
496               if (row_length > 0)
497                 {
498                   alloc_size += row_length;
499                 }
500               else
501                 {
502                   alloc_size += row_count - 1;
503                 }
504               str_count++;
505               if (modulo == 0 || (str_count % modulo == 0))
506                 {
507                   /* null-terminated string */
508                   alloc_size++;
509                   list_count++;
510                 }
511             }
512           is_first_row = true;
513           is_comment = false;
514           row_count = 0;
515         }
516      }
517 
518   if (numof_lines > 0 && numof_lines != list_count)
519     {
520       std::cerr << "(!)handler_resources::load_texts() " <<
521         numof_lines << " exceptes lines, read " << list_count <<
522         " lines!" << std::endl;
523       throw std::runtime_error ("(!))handler_resources::load_texts() "
524           "bad number of lines!");
525     }
526 
527   /*
528    * allocate memory require to create strings list
529    */
530   alloc_size += sizeof(char *) * list_count;
531   char *buffer = NULL;
532   try
533   {
534     buffer = new char[alloc_size];
535   }
536   catch (std::bad_alloc &)
537   {
538     std::cerr << "(!)handler_resources::load_texts() " <<
539       "not enough memory to allocate " <<
540       alloc_size << " bytes!" << std::endl;
541     throw;
542   }
543   char **list = (char**) buffer;
544   char *strs = buffer + sizeof(char *) * list_count;
545 
546 
547   offset = 0;
548   is_first_row = true;
549   is_comment = false;
550   row_count = 0;
551   char* source = filedata;
552   list_count = 0;
553   str_count = 0;
554   char *str_current = strs;
555   while (offset < filesize)
556     {
557       char c = filedata[offset++];
558       row_count++;
559       if (is_first_row && c == '#')
560         {
561           is_comment = true;
562         }
563       is_first_row = false;
564       if (c == '\n')
565         {
566           if (!is_comment)
567             {
568               /* do not copy the carriage return */
569               row_count--;
570               if (row_length > 0 && row_count >= row_length)
571                 {
572                   row_count = row_length;
573                 }
574               for (Uint32 i = 0; i < row_count; i++)
575                 {
576                   char c = source[i];
577                   if (upper_case && c >= 'a' && c <= 'z')
578                     {
579                       c = c - ('a' - 'A');
580                     }
581                   if (c < ' ')
582                     {
583                       c = ' ';
584                     }
585                   *(strs++) = c;
586                 }
587               for (Uint32 i = row_count; i < row_length; i++)
588                 {
589                   *(strs++) = ' ';
590                 }
591               str_count++;
592               if (modulo == 0 || (str_count % modulo == 0))
593                 {
594                   *(strs++) = '\0';
595                   list[list_count++] = str_current;
596                   str_current = strs;
597                 }
598             }
599           is_first_row = true;
600           is_comment = false;
601           row_count = 0;
602           source = &filedata[offset];
603         }
604      }
605   delete[]filedata;
606   return list;
607 }
608 
609 /**
610  * Allocate memory and load a file (filename with a language code)
611  * @param filename specified by path
612  * @param fsize pointer on the size of file which will be loaded
613  * @return a pointer to the file data
614  */
615 char *
loadfile_with_lang(const char * const filename,Uint32 * const fsize)616 handler_resources::loadfile_with_lang (const char *const filename, Uint32 * const fsize)
617 {
618   if(filename == NULL || strlen (filename) == 0)
619     {
620       std::cerr << "(!)handler_resources::loadfile_with_lang() " <<
621         "NULL string!" << std::endl;
622       throw std::ios_base::failure ("(!)handler_resources::loadfile_with_lang() "
623                                     "can't open a file!");
624     }
625   char* fname = new char[strlen (filename) + 1];
626   strcpy (fname, filename);
627   const char* lang = config_file->get_language ();
628   sprintf (fname, filename, lang);
629   if (is_verbose)
630     {
631       std::cout << "handler_resources::loadfile_with_lang() " <<
632         "file " << fname << " was loaded in memory" << std::endl;
633     }
634   char* data = load_file (fname, fsize);
635   delete[]fname;
636   return data;
637 }
638 
639 /**
640  * Load a file in memory
641  * @param fname filename specified by path
642  */
643 char *
load_file(const char * fname)644 handler_resources::load_file (const char *fname)
645 {
646   return load_file (fname, &last_filesize_loaded);
647 }
648 
649 /**
650  * Load a file in memory
651  * @param fname filename specified by path
652  * @param fsize pointer on the size of file which will be loaded
653  * return a pointer to the file data
654 */
655 char *
load_file(const char * fname,Uint32 * fsize)656 handler_resources::load_file (const char *fname, Uint32 * fsize)
657 {
658   /* locate a file under one of the data directories */
659   char *pname = locate_data_file (fname);
660 
661   /* open the file */
662 #ifdef WIN32
663   Sint32 fhand = open (pname, O_RDONLY | O_BINARY, 0);
664 #else
665   Sint32 fhand = open (pname, O_RDONLY, 0);
666 #endif
667   if (fhand == -1)
668     {
669       std::cerr << "(!)handler_resources::load_file() " <<
670         "can't open file " << fname
671         << "; error: " << strerror (errno) << std::endl;
672       throw std::ios_base::failure ("(!)handler_resources::load_file() "
673                                     "can't open a file!");
674     }
675 
676   /* read the size of the file */
677   struct stat sb;
678   if (fstat (fhand, &sb))
679     {
680       std::cerr << "(!)handler_resources::load_file() " <<
681         "can't stat file " << fname
682         << "strerror:" << strerror (errno) << std::endl;
683       throw std::ios_base::failure ("(!)handler_resources::load_file() "
684                                     "can't stat a file!");
685     }
686   /* save filesize */
687   (*fsize) = sb.st_size;
688 
689   /* allocate memory require to load the filedata */
690   char *buffer = NULL;
691   try
692   {
693     buffer = new char[sb.st_size];
694   }
695   catch (std::bad_alloc &)
696   {
697     std::cerr << "(!)handler_resources::load_file() " <<
698       "not enough memory to allocate " <<
699       sb.st_size << " bytes!" << std::endl;
700     throw;
701   }
702 
703   /* read the file */
704   if (read (fhand, buffer, sb.st_size) != sb.st_size)
705     {
706       std::cerr << "(!)handler_resources::load_file() " <<
707         "can't read file " << fname
708         << "strerror:" << strerror (errno) << std::endl;
709       throw std::ios_base::failure ("(!)handler_resources::load_file() "
710                                     "can't read a file!");
711       return NULL;
712     }
713 
714   /* close the file */
715   close (fhand);
716   return buffer;
717 }
718 
719 /**
720  * Return size last file loaded in memory
721  * @return the size of the last filesize previously
722  */
723 Uint32
get_filesize_loaded()724 handler_resources::get_filesize_loaded ()
725 {
726   return last_filesize_loaded;
727 }
728 
729 
730 void
set_filesize_loaded(Uint32 size)731 handler_resources::set_filesize_loaded (Uint32 size)
732 {
733   Uint32 i = size;
734   i++;
735   last_filesize_loaded = size;
736 }
737 
738 char*
read_complete_file(const char * filename)739 handler_resources::read_complete_file (const char* filename )
740 {
741   std::ifstream file (filename, std::ios::ate);
742   if (! file.is_open () )
743     {
744       std::cerr << "(!)handler_ressources::read_complete_file()"
745         "can't open file '" << filename << "'" << std::endl;
746       //throw std::ios_base::failure ("(!)handler_ressources::read_complete_file() can't read a file!");
747       return NULL;
748     }
749   //Uint32 size = (Uint32) file.tellg();
750   std::ifstream::pos_type size = file.tellg();
751   //int filesize = (int)size;
752   //last_filesize_loaded = 1;
753   //last_filesize_loaded = 2;
754   //last_filesize_loaded = size;
755   char *buffer = NULL;
756   try
757   {
758     buffer = new char[size];
759   }
760   catch (std::bad_alloc &)
761   {
762     file.close();
763     std::cerr << "(!)handler_resources::read_complete_file() " <<
764       "not enough memory to allocate " <<
765       size << " bytes!" << std::endl;
766     throw;
767   }
768   file.seekg (0, std::ios::beg);
769   file.read (buffer, size);
770   file.close();
771   return buffer;
772 }
773 
774 /**
775  * Load a precalculated sinus & cosinus table (1790 bytes <=> 895 values)
776  * 0 to 511 cosinus / 383 to 894 sinus
777  */
778 void
load_sinus()779 handler_resources::load_sinus ()
780 {
781   table_cosL = (Sint16 *) load_data (handler_resources::RESCOSLIST);
782   table_sinL = table_cosL + 383;
783 
784 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
785   /* convert big endian values to little endian values */
786   Sint32 fsize = get_filesize_loaded ();
787   /* convert bytes = 16-bits words */
788   fsize = fsize / 2;
789   for (Sint32 i = 0; i < fsize; i++)
790     {
791       char *p = (char *) &table_cosL[i];
792       char a = p[0];
793       p[0] = p[1];
794       p[1] = a;
795     }
796 #endif
797 }
798 
799 /**
800  * load scores table
801  */
802 char *
load_high_score_file()803 handler_resources::load_high_score_file ()
804 {
805   char* filedata = NULL;
806   try
807     {
808       filedata = load_file (fnamescore, &last_filesize_loaded);
809     }
810   catch (...)
811     {
812        std::cerr << "(!)handler_resources::load_high_score_file() " <<
813          "can't open the scores files!" << std::endl;
814        filedata = NULL;
815     }
816   return filedata;
817 }
818 
819 /*
820  * Save scores table
821  * @param buffer
822  * @pram size
823  */
824 void
save_high_score_file(char * buffer,Uint32 size)825 handler_resources::save_high_score_file (char *buffer, Uint32 size)
826 {
827   size_t left;
828   ssize_t bytes_written;
829 #ifdef WIN32
830   /* set umask so that files are group-writable */
831   _umask (0002);
832 #else
833   umask (0002);
834 #endif
835   Sint32 fhand = open (fnamescore, O_WRONLY | O_CREAT, 00666);
836   if (fhand == -1)
837     {
838       fprintf (stderr,
839                "handler_resources::save_high_score_file(): file:%s / error:%s\n",
840                fnamescore, strerror (errno));
841     }
842   left = size;
843   while (left > 0)
844     {
845 #ifdef WIN32
846       bytes_written = _write (fhand, buffer + size - left, left);
847 #else
848       bytes_written = write (fhand, buffer + size - left, left);
849       if (bytes_written == -1)
850         {
851           std::cerr << "(!)handler_resources::save_high_score_file():" <<
852              " filename: " << fnamescore << "; error: " << strerror (errno) << std::endl;
853           close (fhand);
854           return;
855         }
856         left -= bytes_written;
857     }
858 #endif
859   if (close (fhand) == -1)
860     {
861       fprintf (stderr,
862                "handler_resources::save_high_score_file(): file:%s / error:%s\n",
863                fnamescore, strerror (errno));
864     }
865   else
866     {
867       if (is_verbose)
868         fprintf (stdout, "handler_resources::save_high_score_file(): "
869                  "file:%s size:%i\n", fnamescore, size);
870     }
871 }
872 
873 /**
874  * Precalculated cosinus and sinus table
875  */
876 const Sint16
877   handler_resources::cosinus360[720] =
878   { 0, 2, 4, 7, 9, 11, 13, 15, 18, 20, 22, 24, 26, 29, 31, 33, 35, 37, 39, 41,
879   43,
880   46, 48, 50, 52, 54, 56, 58, 60, 62, 63, 65, 67, 69, 71, 73, 75, 76, 78, 80,
881   82, 83, 85, 87, 88, 90, 91, 93, 94, 96, 97, 99, 100, 101, 103, 104, 105,
882   107,
883   108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 119, 120, 121,
884   121, 122, 123, 123, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127, 127,
885   127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 125, 125, 125, 124,
886   124, 123, 123, 122, 121, 121, 120, 119, 119, 118, 117, 116, 115, 114, 113,
887   112, 111, 110, 109, 108, 107, 105, 104, 103, 101, 100, 99, 97, 96, 94, 93,
888   91,
889   90, 88, 87, 85, 83, 82, 80, 78, 76, 75, 73, 71, 69, 67, 65, 64, 62, 60, 58,
890   56, 54, 52, 50, 48, 46, 43, 41, 39, 37, 35, 33, 31, 29, 26, 24, 22, 20, 18,
891   16, 13, 11, 9, 7, 4, 2, 0, -2, -4, -7, -9, -11, -13, -15, -18, -20, -22,
892   -24,
893   -26, -29, -31, -33, -35, -37, -39, -41, -43, -45, -48, -50, -52, -54, -56,
894   -58, -60, -62, -63, -65, -67, -69, -71, -73, -75, -76, -78, -80, -82, -83,
895   -85, -87, -88, -90, -91, -93, -94, -96, -97, -99, -100, -101, -103, -104,
896   -105, -106, -108, -109, -110, -111, -112, -113, -114, -115, -116, -117,
897   -118,
898   -119, -119, -120, -121, -121, -122, -123, -123, -124, -124, -125, -125,
899   -125,
900   -126, -126, -126, -127, -127, -127, -127, -127, -127, -127, -127, -127,
901   -127,
902   -127, -126, -126, -126, -125, -125, -125, -124, -124, -123, -123, -122,
903   -121,
904   -121, -120, -119, -119, -118, -117, -116, -115, -114, -113, -112, -111,
905   -110,
906   -109, -108, -107, -105, -104, -103, -101, -100, -99, -97, -96, -94, -93,
907   -91,
908   -90, -88, -87, -85, -83, -82, -80, -78, -76, -75, -73, -71, -69, -67, -65,
909   -64, -62, -60, -58, -56, -54, -52, -50, -48, -46, -43, -41, -39, -37, -35,
910   -33, -31, -29, -26, -24, -22, -20, -18, -16, -13, -11, -9, -7, -4, -2, 127,
911   127, 127, 127, 127, 127, 126, 126, 126, 125, 125, 125, 124, 124, 123, 123,
912   122, 121, 121, 120, 119, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110,
913   109, 108, 107, 105, 104, 103, 101, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87,
914   85, 83, 82, 80, 78, 76, 75, 73, 71, 69, 67, 65, 64, 62, 60, 58, 56, 54, 52,
915   50, 48, 46, 43, 41, 39, 37, 35, 33, 31, 29, 26, 24, 22, 20, 18, 15, 13, 11,
916   9, 7, 4, 2, 0, -2, -4, -7, -9, -11, -13, -15, -18, -20, -22, -24, -26, -29,
917   -31, -33, -35, -37, -39, -41, -43, -45, -48, -50, -52, -54, -56, -58, -60,
918   -62, -63, -65, -67, -69, -71, -73, -75, -76, -78, -80, -82, -83, -85, -87,
919   -88, -90, -91, -93, -94, -96, -97, -99, -100, -101, -103, -104, -105, -107,
920   -108, -109, -110, -111, -112, -113, -114, -115, -116, -117, -118, -119,
921   -119,
922   -120, -121, -121, -122, -123, -123, -124, -124, -125, -125, -125, -126,
923   -126,
924   -126, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
925   -126,
926   -126, -126, -125, -125, -125, -124, -124, -123, -123, -122, -121, -121,
927   -120,
928   -119, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110, -109,
929   -108,
930   -107, -105, -104, -103, -101, -100, -99, -97, -96, -94, -93, -91, -90, -88,
931   -87, -85, -83, -82, -80, -78, -76, -75, -73, -71, -69, -67, -65, -64, -62,
932   -60, -58, -56, -54, -52, -50, -48, -46, -43, -41, -39, -37, -35, -33, -31,
933   -29, -26, -24, -22, -20, -18, -16, -13, -11, -9, -7, -4, -2, 0, 2, 4, 7, 9,
934   11, 13, 15, 18, 20, 22, 24, 26, 29, 31, 33, 35, 37, 39, 41, 43, 45, 48, 50,
935   52, 54, 56, 58, 60, 62, 63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 83, 85,
936   87, 88, 90, 91, 93, 94, 96, 97, 99, 100, 101, 103, 104, 105, 106, 108, 109,
937   110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 119, 120, 121, 121, 122,
938   123, 123, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127, 127, 127, 127
939 };
940 const Sint16 *
941   handler_resources::zesinus360 = handler_resources::cosinus360 + 360;
942 
943 
944 const
945   Uint32
946   handler_resources::color_gradations[180] =
947   { 0x0400180, 0x0420290, 0x0440392, 0x0500494, 0x0600596, 0x0700698,
948   0x0800795, 0x0900893, 0x0A00990, 0x0A20A80, 0x0A40B70, 0x0A60C60,
949   0x0A80D50, 0x0AA0E40, 0x0AC0F30, 0x0AE1020, 0x0B01110, 0x0B21200,
950   0x0014080, 0x0024590, 0x0034A92, 0x0045094, 0x0056096, 0x0067097,
951   0x0078096, 0x0089093, 0x009A090, 0x00AA180, 0x00BA270, 0x00CA360,
952   0x00DA450, 0x00EA540, 0x00FA630, 0x010A720, 0x011A810, 0x012A900,
953   0x0408001, 0x0459002, 0x04A9203, 0x0509404, 0x0609605, 0x0709806,
954   0x0809507, 0x0909308, 0x0A19009, 0x0A2800A, 0x0A3700B, 0x0A4600C,
955   0x0A5500D, 0x0A6400E, 0x0A7300F, 0x0A82010, 0x0A91011, 0x0AA0012,
956   0x0002080, 0x0102190, 0x0202292, 0x0302394, 0x0402496, 0x0502598,
957   0x0602695, 0x0702793, 0x0802890, 0x0782980, 0x0702A90, 0x0602B92,
958   0x0502C94, 0x0402D96, 0x0302E98, 0x0202F95, 0x0102A93, 0x0002B92,
959   0x0104080, 0x0204590, 0x0304A92, 0x0405094, 0x0506096, 0x0607098,
960   0x0708095, 0x0809093, 0x090A090, 0x0A0A280, 0x0B0A470, 0x0C0A660,
961   0x0B0A850, 0x0A0AA40, 0x090AC30, 0x080AE20, 0x070B010, 0x060B210,
962   0x04080B0, 0x04590A0, 0x04A9290, 0x0509480, 0x0609670, 0x0709860,
963   0x0809550, 0x0909340, 0x0A09030, 0x0A18020, 0x0A27010, 0x0A36020,
964   0x0A45030, 0x0A54040, 0x0A63050, 0x0A72060, 0x0A81070, 0x0A90080,
965   0x0101080, 0x0181290, 0x0201492, 0x0281694, 0x0301896, 0x0381A98,
966   0x0401C95, 0x0451E93, 0x04A2080, 0x0502270, 0x0582460, 0x0602650,
967   0x0702840, 0x0782B30, 0x0802E20, 0x0853010, 0x08A3205, 0x0903600,
968   0x0404080, 0x0484890, 0x0504A91, 0x0605092, 0x0706093, 0x0807094,
969   0x0908093, 0x0889092, 0x080A090, 0x081A280, 0x082A670, 0x083A860,
970   0x084AA50, 0x085AC40, 0x086AE30, 0x087B020, 0x088B210, 0x089B405,
971   0x0458040, 0x04A9045, 0x040924A, 0x0509450, 0x0609655, 0x070985A,
972   0x0809562, 0x0909364, 0x0A09066, 0x0A1806A, 0x0A2706C, 0x0A36070,
973   0x0A45073, 0x0A54076, 0x0A6307A, 0x0A72080, 0x0A81085, 0x0A90590,
974   0x0407080, 0x0457890, 0x04A8091, 0x0508892, 0x0609093, 0x0709894,
975   0x080A093, 0x090A892, 0x0A0B090, 0x0A1B880, 0x0A2C070, 0x0A3B860,
976   0x0A4B050, 0x0A5A840, 0x0A6A030, 0x0A79820, 0x0A89010, 0x0A98805
977 };
978