Launcher, based on PickleLauncher
[mupen64plus-pandora.git] / source / mupen64launcher / src / cbase.cpp
1 /**
2  *  @section LICENSE
3  *
4  *  PickleLauncher
5  *  Copyright (C) 2010-2011 Scott Smith
6  *
7  *  This program is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  *  @section LOCATION
21  */
22
23 #include "cbase.h"
24
25 CBase::CBase()
26 {
27 }
28
29 CBase::~CBase()
30 {
31 }
32
33 void CBase::Log( const char* output, ... )
34 {
35     va_list fmtargs;
36     char buffer[1024];
37
38     va_start( fmtargs, output );
39     vsnprintf( buffer, sizeof(buffer)-1, output, fmtargs );
40     va_end( fmtargs );
41
42     fprintf( stdout, "%s", buffer );
43
44 #if defined(DEBUG)
45     FILE* fout = fopen( "log.txt", "a" );
46     if (!fout)
47     {
48         printf( "Failed to open logfile\n" );
49         return;
50     }
51     fputs(buffer, fout);
52     fclose(fout);
53 #endif
54 }
55
56 uint32_t CBase::CheckRange( int32_t value, int32_t size )
57 {
58     if (value >= 0 && value < size)
59     {
60         return 1;
61     }
62     else
63     {
64         return 0;
65     }
66 }
67
68 uint32_t CBase::rgb_to_int( SDL_Color color )
69 {
70     return SDL_MapRGB(SDL_GetVideoSurface()->format, color.r, color.g, color.b);
71 }
72
73 int32_t CBase::a_to_i( const string& line )
74 {
75     int32_t number;
76
77     stringstream ss( line.c_str() );
78     ss >> number;       // Convert string to integer
79     return number;
80 }
81
82 string CBase::i_to_a( const int16_t num )
83 {
84     string str;
85     stringstream ss;
86
87     ss << num;
88     ss >> str;          // Convert string to integer
89     return str;
90 }
91
92 string CBase::lowercase( string text )
93 {
94     transform( text.begin(), text.end(), text.begin(), (int (*)(int))tolower );
95     return text;
96 }
97
98 SDL_Surface* CBase::LoadImage( const string& filename )
99 {
100     SDL_Surface* loaded_image    = NULL; // The mpImage that's loaded
101     SDL_Surface* optimized_image = NULL; // The optimized surface that will be used
102
103     loaded_image = IMG_Load( filename.c_str() ); //Load the mpImage
104
105     // If the mpImage loaded
106     if (NULL != loaded_image)
107     {
108         optimized_image = SDL_DisplayFormatAlpha( loaded_image ); // Create an optimized surface
109         SDL_FreeSurface(loaded_image);                            // Free the old surface
110         loaded_image = NULL;
111
112         // If the surface was optimized
113         if (NULL != optimized_image)
114         {
115             // Color key surface
116             SDL_SetColorKey( optimized_image, SDL_RLEACCEL | SDL_SRCCOLORKEY, SDL_MapRGB( optimized_image->format, 0xFF, 0, 0xFF ) );
117         }
118     }
119     else
120     {
121                 //Log( "LoadImage -> Could not load image: %s at path='%s'\n", IMG_GetError(), filename.c_str() );
122                 return NULL;
123     }
124
125     //Return the optimized surface
126     return optimized_image;
127 }
128
129 void CBase::ApplyImage( int16_t x, int16_t y, SDL_Surface* src, SDL_Surface* dst, SDL_Rect* clip )
130 {
131     // Holds offsets
132     SDL_Rect offset;
133
134     // Get offsets
135     offset.x = x;
136     offset.y = y;
137
138     // Blit
139     SDL_BlitSurface( src, clip, dst, &offset );
140 }
141
142 bool CBase::CheckRectCollision( SDL_Rect* boxA, SDL_Rect* boxB )
143 {
144     // The sides of the SDL_Rects
145     int16_t leftA, leftB;
146     int16_t rightA, rightB;
147     int16_t topA, topB;
148     int16_t bottomA, bottomB;
149
150     // Calculate the sides of rec mCollisionbox
151     leftA   = boxB->x;
152     rightA  = boxB->x + boxB->w;
153     topA    = boxB->y;
154     bottomA = boxB->y + boxB->h;
155
156     // Calculate the sides of rec box
157     leftB   = boxA->x;
158     rightB  = boxA->x + boxA->w;
159     topB    = boxA->y;
160     bottomB = boxA->y + boxA->h;
161
162     // If any of the sides from mCollisionbox are outside of box
163     if (bottomA <= topB) return false;
164     if (topA >= bottomB) return false;
165     if (rightA <= leftB) return false;
166     if (leftA >= rightB) return false;
167     // If none of the sides from mCollisionbox are outside box
168     return true;    // Collision has occured
169 }
170
171 void CBase::SplitString( const std::string& delimiter, const std::string& text, vector<string>& array )
172 {
173     string::size_type pos1, pos2;
174     string value;
175
176     array.clear();
177
178     pos1 = text.find( delimiter, 0 );
179     if (pos1 == string::npos)
180     {
181         pos1 = text.length();
182     }
183     value = text.substr( 0, pos1 );
184     array.push_back(value);
185
186     pos2 = pos1;
187
188     do {
189         pos1 = text.find( delimiter, pos2 );
190
191         if (pos1 != string::npos)
192         {
193             pos2 = text.find( delimiter, pos1+1 );
194             if (pos2 == string::npos)
195             {
196                 pos2 = text.length();
197             }
198
199             value = text.substr( pos1+1, pos2-pos1-1 );
200             array.push_back(value);
201         }
202     } while (pos1 != string::npos);
203 }
204
205 bool CBase::UnprefixString( string& result, const string& line, const string& prefix )
206 {
207     string::size_type pos;
208
209     pos = line.find(prefix, 0);
210     if (pos == 0)
211     {
212         // Remove the prefix
213         pos = line.find("=", 0) + 1;
214         result = line.substr(pos, line.length()-pos);
215         // Remove any comments
216         pos = result.find("#", 0);
217         result = result.substr(0, pos);
218         // Trim left and right white spaces
219         result.erase( result.begin(), std::find_if(result.begin(), result.end(), std::not1(std::ptr_fun<int, int>(std::isspace))) );
220         result.erase( std::find_if(result.rbegin(), result.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), result.end() );
221
222         return true;
223     }
224     return false;
225 }
226
227 int16_t CBase::CheckExtension( const string& filename, const string& ext )
228 {
229     int16_t result;
230     string::size_type pos;
231
232     pos = filename.length() - ext.length();
233     result = lowercase(filename).find( lowercase(ext), pos);
234
235     return result;
236 }
237
238 void CBase::CheckPath( string& path )
239 {
240     if (path.length()>1)
241     {
242         if (path.at(path.length()-1) != '/')
243         {
244             path += '/';
245         }
246     }
247     else
248     {
249         Log( "Warning: CheckPath path too short\n" );
250     }
251 }
252
253 string CBase::cmdclean( string& cmdline )
254 {
255     string spchars = "\\`$();|{}&'\"*?<>[]!^~-#\n\r ";
256     for (uint i=0; i<spchars.length(); i++)
257     {
258         string curchar = spchars.substr(i,1);
259         cmdline = strreplace(cmdline, curchar, "\\"+curchar);
260     }
261     return cmdline;
262 }
263
264 string CBase::strreplace( string& orig, const string& search, const string& replace )
265 {
266     string::size_type pos = orig.find( search, 0 );
267     while (pos != string::npos)
268     {
269         orig.replace(pos,search.length(),replace);
270         pos = orig.find( search, pos+replace.length() );
271     }
272     return orig;
273 }
274
275 SDL_Surface* CBase::ScaleSurface( SDL_Surface *surface, uint16_t width, uint16_t height )
276 {
277     if(!surface || !width || !height)
278         return 0;
279
280     SDL_Surface *_ret = SDL_CreateRGBSurface(surface->flags, width, height, surface->format->BitsPerPixel,
281         surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask);
282
283     double  _stretch_factor_x = ( static_cast<double>(width) / static_cast<double>(surface->w) ),
284         _stretch_factor_y = ( static_cast<double>(height) / static_cast<double>(surface->h) );
285
286     for (int32_t y = 0; y < surface->h; y++)
287         for (int32_t x = 0; x < surface->w; x++)
288             for (int32_t o_y = 0; o_y < _stretch_factor_y; ++o_y)
289                 for (int32_t o_x = 0; o_x < _stretch_factor_x; ++o_x)
290                     putpixel( _ret, static_cast<int32_t>(_stretch_factor_x * x) + o_x,
291                         static_cast<int32_t>(_stretch_factor_y * y) + o_y, getpixel(surface, x, y) );
292
293     return _ret;
294 }
295
296 uint32_t CBase::getpixel( SDL_Surface *surface, int16_t x, int16_t y )
297 {
298     int16_t bpp = surface->format->BytesPerPixel;
299     /* Here p is the address to the pixel we want to retrieve */
300     uint8_t *p = (uint8_t *)surface->pixels + y * surface->pitch + x * bpp;
301
302     switch (bpp) {
303         case 1:
304             return *p;
305             break;
306
307         case 2:
308             return *(uint16_t *)p;
309             break;
310
311         case 3:
312             if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
313                 return p[0] << 16 | p[1] << 8 | p[2];
314             else
315                 return p[0] | p[1] << 8 | p[2] << 16;
316             break;
317
318         case 4:
319             return *(uint32_t *)p;
320             break;
321
322         default:
323             return 0;       /* shouldn't happen, but avoids warnings */
324     }
325 }
326
327 void CBase::putpixel( SDL_Surface *surface, int16_t x, int16_t y, uint32_t pixel )
328 {
329     int16_t bpp = surface->format->BytesPerPixel;
330     /* Here p is the address to the pixel we want to set */
331     uint8_t *p = (uint8_t *)surface->pixels + y * surface->pitch + x * bpp;
332
333     switch (bpp) {
334         case 1:
335             *p = pixel;
336             break;
337
338         case 2:
339             *(uint16_t *)p = pixel;
340             break;
341
342         case 3:
343             if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
344                 p[0] = (pixel >> 16) & 0xff;
345                 p[1] = (pixel >> 8) & 0xff;
346                 p[2] = pixel & 0xff;
347             } else {
348                 p[0] = pixel & 0xff;
349                 p[1] = (pixel >> 8) & 0xff;
350                 p[2] = (pixel >> 16) & 0xff;
351             }
352             break;
353
354         case 4:
355         default:
356             *(uint32_t *)p = pixel;
357             break;
358     }
359 }