AC_SUBST([ICONV_LIBS], [$LIBICONV])
dnl ===========================================================================
+dnl Check for OpenGL
+if test "$enable_opengl" = "yes"; then
+ AX_CHECK_GL
+fi
+if test "$no_gl" = "yes" -o "$enable_opengl" = "no"; then
+ GL_AVAILABLE="no"
+ AC_DEFINE([NOOPENGL],, [Define if opengl should not be used])
+else
+ GL_AVAILABLE="yes"
+fi
+AC_SUBST([GL_AVAILABLE])
+
dnl Check for SDL
SDL_VERSION=1.2.4
AM_PATH_SDL($SDL_VERSION,
[AC_MSG_ERROR([Please install SDLImage >= 1.2.1])],
[$SDL_CFLAGS], [$SDL_LIBS])
-if test "$enable_opengl" = "yes"; then
- AX_CHECK_GL
-fi
-if test "$no_gl" = "yes" -o "$enable_opengl" = "no"; then
- GL_AVAILABLE="no"
- AC_DEFINE([NOOPENGL],, [Define if opengl should not be used])
-else
- GL_AVAILABLE="yes"
-fi
-AC_SUBST([GL_AVAILABLE])
+NP_FINDLIB([PHYSFS], [physfs], [physfs >= 1.0.0],
+ NP_LANG_PROGRAM([#include <physfs.h>
+#if PHYSFS_VER_MAJOR < 1
+# error PHYSFS is too old
+#endif]),
+ [], [-lphysfs],
+ [],
+ [AC_MSG_ERROR([Please install physfs >= 1.0])])
dnl Checks for library functions.
AC_CHECK_FUNCS(mkdir strdup strstr)
(solid #f)
)
(init-script "
-function wait(time) {
- set_wakeup_time(time);
- suspend();
-}
Text.set_text(translate(\"The Crazy Nolok Dance\"));
Text.fade_in(2);
TUX.set_animation(\"jump\");
--- /dev/null
+# NP_FINDLIB(VARNAME, NAME, STRING, TESTAPP, CFLAGS, LIBS, ACTION_IF_FOUND,
+# ACTION_IF_NOT_FOUND, EXTRACFLAGS, EXTRALIBS)
+AC_DEFUN([NP_FINDLIB], [
+ AC_ARG_WITH([lib$2], [AC_HELP_STRING([--with-lib$2=dir],
+ [specify location of lib$2 if not detected automatically; uses
+ dir, dir/include and dir/lib])])
+
+ save_CFLAGS="$CFLAGS"
+ save_CPPFLAGS="$CPPFLAGS"
+ save_LIBS="$LIBS"
+
+ RESCFLAGS="$5"
+ RESLIBS="$6"
+ CFLAGS="$CFLAGS $5 $9"
+ CPPFLAGS="$CPPFLAGS $5 $9"
+ LIBS="$LIBS $6 $10"
+
+ AS_IF([test -n "$with_lib$2"], [
+ CFLAGS="-I$with_lib$2/include $CFLAGS"
+ CPPFLAGS="-I$with_lib$2/include $CPPFLAGS"
+ LIBS="-L$with_lib$2/lib $LIBS"
+ RESCFLAGS="-I$with_lib$2/include $RESCFLAGS"
+ RESLIBS="-L$with_lib$2/lib $RESLIBS"
+ ])
+
+ AC_MSG_CHECKING([for $3])
+
+ AC_LINK_IFELSE([$4], [buildok=yes], [buildok=no])
+
+ LIBS=$save_LIBS
+ CPPFLAGS=$save_CPPFLAGS
+ CFLAGS=$save_CFLAGS
+
+ AS_IF([test $buildok = yes],
+ [AC_MSG_RESULT([found])
+ $1_AVAILABLE=yes
+ $1_CFLAGS="$RESCFLAGS"
+ $1_LIBS="$RESLIBS"],
+ [AC_MSG_RESULT([not found])
+ $1_AVAILABLE=no
+ $1_CFLAGS=""
+ $1_LIBS=""])
+
+ AC_SUBST([$1_AVAILABLE])
+ AC_SUBST([$1_CFLAGS])
+ AC_SUBST([$1_LIBS])
+
+ AS_IF([test $buildok = yes],
+ [ifelse([$7], , :, [$7])],
+ [ifelse([$8], , :, [$8])])
+])
--- /dev/null
+# NP_LANG_PROGRAM, custom version of AC_LANG_PROGRAM (because SDL on win32
+# NEEDS main(int argc, char** argv)
+AC_DEFUN([NP_LANG_PROGRAM],
+[$1
+m4_ifdef([_AC_LANG_PROGRAM_C_F77_HOOKS], [_AC_LANG_PROGRAM_C_F77_HOOKS])[]dnl
+int
+main(int argc, char** argv)
+{
+$2
+ ;
+ return 0;
+}
+])
sources =
[ Wildcard *.cpp *.h ]
- [ Wildcard math : *.cpp *.h ]
- [ Wildcard video : *.cpp *.h ]
[ Wildcard audio : *.cpp *.h ]
+ [ Wildcard badguy : *.cpp *.h ]
+ [ Wildcard control : *.cpp *.h ]
[ Wildcard gui : *.cpp *.h ]
[ Wildcard lisp : *.cpp *.h ]
+ [ Wildcard math : *.cpp *.h ]
[ Wildcard object : *.cpp *.h ]
- [ Wildcard badguy : *.cpp *.h ]
+ [ Wildcard physfs : *.cpp *.h ]
[ Wildcard sprite : *.cpp *.h ]
- [ Wildcard trigger : *.cpp *.h ]
[ Wildcard tinygettext : *.cpp *.h ]
- [ Wildcard control : *.cpp *.h ]
+ [ Wildcard trigger : *.cpp *.h ]
+ [ Wildcard video : *.cpp *.h ]
;
TRANSLATABLE_SOURCES += [ SearchSource $(sources) ] ;
Application supertux : $(sources) $(wrapper_objects) ;
-C++Flags supertux : -DDATA_PREFIX='\"$(appdatadir)\"' ;
+C++Flags supertux : -DAPPDATADIR='\"$(appdatadir)\"' ;
LinkWith supertux : squirrel ;
-ExternalLibs supertux : SDL SDLMIXER SDLIMAGE GL ICONV ;
+ExternalLibs supertux : SDL SDLMIXER SDLIMAGE GL ICONV PHYSFS BINRELOC ;
Help supertux : "Build the supertux executable" ;
IncludeDir supertux : squirrel/include ;
#include <iostream>
#include <stdexcept>
#include <sstream>
+#include <physfs.h>
#include "audio/sound_manager.h"
#include "audio/musicref.h"
+#include "physfs/physfs_sdl.h"
#include "moving_object.h"
#include "resources.h"
}
bool
-SoundManager::exists_music(const std::string& file)
+SoundManager::exists_music(const std::string& filename)
{
if(!audio_device)
return true;
// song already loaded?
- std::map<std::string, MusicResource>::iterator i = musics.find(file);
+ std::map<std::string, MusicResource>::iterator i = musics.find(filename);
if(i != musics.end()) {
return true;
}
-
- Mix_Music* song = Mix_LoadMUS(file.c_str());
+
+ const char* dir = PHYSFS_getRealDir(filename.c_str());
+ if(dir == 0)
+ return false;
+ Mix_Music* song = Mix_LoadMUS( (std::string(dir) + "/" + filename).c_str() );
if(song == 0)
return false;
// insert into music list
std::pair<std::map<std::string, MusicResource>::iterator, bool> result =
musics.insert(
- std::make_pair<std::string, MusicResource> (file, MusicResource()));
+ std::make_pair<std::string, MusicResource> (filename, MusicResource()));
MusicResource& resource = result.first->second;
resource.manager = this;
resource.music = song;
std::string filename = "sounds/";
filename += name;
filename += ".wav";
- filename = get_resource_filename(filename);
- Mix_Chunk* chunk = Mix_LoadWAV(filename.c_str());
+ Mix_Chunk* chunk = Mix_LoadWAV_RW(get_physfs_SDLRWops(filename), true);
if(chunk != 0) {
sounds.insert(std::make_pair(name, chunk));
}
#include <config.h>
#include "file_system.h"
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#ifndef WIN32
-#include <libgen.h>
-#endif
-#include "resources.h"
-
-#ifdef WIN32
-#define mkdir(dir, mode) mkdir(dir)
-#endif
+#include <string>
namespace FileSystem
{
-/* Does the given file exist and is it accessible? */
-bool faccessible(const std::string& filename)
-{
- FILE* f = fopen(filename.c_str(), "r");
- if(f == 0)
- return false;
-
- fclose(f);
- return true;
-}
-
-/* Can we write to this location? */
-bool fwriteable(const std::string& filename)
-{
- FILE* f = fopen(filename.c_str(), "wa");
- if (f == 0)
- return false;
-
- fclose(f);
- return true;
-}
-
-/* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/
-bool fcreatedir(const std::string& relative_dir)
-{
- std::string path = user_dir + "/" + relative_dir + "/";
- if(mkdir(path.c_str(),0755) == 0)
- return true;
-
- path = datadir + "/" + relative_dir + "/";
- if(mkdir(path.c_str(),0755) == 0)
- return true;
-
- return false;
-}
-
-/* Get all names of sub-directories in a certain directory. */
-/* Returns the number of sub-directories found. */
-/* Note: The user has to free the allocated space. */
-std::set<std::string> dsubdirs(const std::string &rel_path,
- const std::string& expected_file)
-{
- DIR *dirStructP;
- struct dirent *direntp;
- std::set<std::string> sdirs;
- std::string filename;
- std::string path = user_dir + "/" + rel_path;
-
- if((dirStructP = opendir(path.c_str())) != NULL)
- {
- while((direntp = readdir(dirStructP)) != NULL)
- {
- std::string absolute_filename;
- struct stat buf;
-
- absolute_filename = path + "/" + direntp->d_name;
-
- if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
- {
- if(!expected_file.empty())
- {
- filename = path + "/" + direntp->d_name + "/" + expected_file;
- if(!faccessible(filename))
- continue;
- }
-
- sdirs.insert(direntp->d_name);
- }
- }
- closedir(dirStructP);
- }
-
- path = datadir + "/" + rel_path;
- if((dirStructP = opendir(path.c_str())) != NULL)
- {
- while((direntp = readdir(dirStructP)) != NULL)
- {
- std::string absolute_filename;
- struct stat buf;
-
- absolute_filename = path + "/" + direntp->d_name;
-
- if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
- {
- if(!expected_file.empty())
- {
- filename = path + "/" + direntp->d_name + "/" + expected_file;
- if(!faccessible(filename.c_str()))
- {
- continue;
- }
- else
- {
- filename = user_dir + "/" + rel_path + "/" + direntp->d_name + "/" + expected_file;
- if(faccessible(filename.c_str()))
- continue;
- }
- }
-
- sdirs.insert(direntp->d_name);
- }
- }
- closedir(dirStructP);
- }
-
- return sdirs;
-}
-
-std::set<std::string> dfiles(const std::string& rel_path,
- const std::string& glob, const std::string& exception_str)
-{
- DIR *dirStructP;
- struct dirent *direntp;
- std::set<std::string> sdirs;
- std::string path = user_dir + "/" + rel_path;
-
- if((dirStructP = opendir(path.c_str())) != NULL)
- {
- while((direntp = readdir(dirStructP)) != NULL)
- {
- std::string absolute_filename;
- struct stat buf;
-
- absolute_filename = path + "/" + direntp->d_name;
-
- if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
- {
- if(!exception_str.empty())
- {
- if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
- continue;
- }
- if(!glob.empty())
- if(strstr(direntp->d_name,glob.c_str()) == NULL)
- continue;
-
- sdirs.insert(direntp->d_name);
- }
- }
- closedir(dirStructP);
- }
-
- path = datadir + "/" + rel_path;
- if((dirStructP = opendir(path.c_str())) != NULL)
- {
- while((direntp = readdir(dirStructP)) != NULL)
- {
- std::string absolute_filename;
- struct stat buf;
-
- absolute_filename = path + "/" + direntp->d_name;
-
- if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
- {
- if(!exception_str.empty())
- {
- if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
- continue;
- }
- if(!glob.empty())
- if(strstr(direntp->d_name,glob.c_str()) == NULL)
- continue;
-
- sdirs.insert(direntp->d_name);
- }
- }
- closedir(dirStructP);
- }
-
- return sdirs;
-}
-
std::string dirname(const std::string& filename)
{
std::string::size_type p = filename.find_last_of('/');
return filename.substr(0, p+1);
}
-std::set<std::string> read_directory(const std::string& pathname)
+std::string basename(const std::string& filename)
{
- std::set<std::string> dirnames;
-
- DIR* dir = opendir(pathname.c_str());
- if (dir)
- {
- struct dirent *direntp;
-
- while((direntp = readdir(dir)))
- {
- dirnames.insert(direntp->d_name);
- }
-
- closedir(dir);
- }
+ std::string::size_type p = filename.find_last_of('/');
+ if(p == std::string::npos)
+ return filename;
- return dirnames;
+ return filename.substr(p, filename.size()-p);
}
}
namespace FileSystem
{
- bool faccessible(const std::string& filename);
- bool fcreatedir(const std::string& relative_dir);
- bool fwriteable(const std::string& filename);
- std::set<std::string> read_directory(const std::string& pathname);
- std::set<std::string> dsubdirs(const std::string& rel_path,
- const std::string& expected_file);
- std::set<std::string> dfiles(const std::string& rel_path,
- const std::string& glob, const std::string& exception_str);
std::string dirname(const std::string& filename);
+ std::string basename(const std::string& filename);
}
#endif
std::string title;
std::stringstream stream;
stream << slot;
- slotfile = user_dir + "/save/slot" + stream.str() + ".stsg";
+ slotfile = "save/slot" + stream.str() + ".stsg";
try {
lisp::Parser parser;
std::stringstream stream;
stream << slot;
- std::string slotfile = user_dir + "/save/slot" + stream.str() + ".stsg";
+ std::string slotfile = "save/slot" + stream.str() + ".stsg";
fadeout(256);
DrawingContext context;
Config::load()
{
lisp::Parser parser;
- std::auto_ptr<lisp::Lisp> root (parser.parse(user_dir + "/config"));
+ std::auto_ptr<lisp::Lisp> root (parser.parse("config"));
const lisp::Lisp* config_lisp = root->get_lisp("supertux-config");
if(!config_lisp)
void
Config::save()
{
- std::string configfile = user_dir + "/config";
- std::ofstream file( (user_dir + "/config").c_str() );
- if(!file.good()) {
- std::stringstream msg;
- msg << "Couldn't write config file '" << configfile << "'";
- throw std::runtime_error(msg.str());
- }
- lisp::Writer writer(file);
+ lisp::Writer writer("config");
writer.start_list("supertux-config");
level->get("version", version);
if(version == 1) {
load_old_format(*level);
-
-#if 0
- // test for now
- FlipLevelTransformer* transformer = new FlipLevelTransformer();
- transformer->transform(this);
-#endif
-
return;
}
void
Level::save(const std::string& filename)
{
- std::string filepath = "levels/" + filename;
- int last_slash = filepath.find_last_of('/');
- FileSystem::fcreatedir(filepath.substr(0,last_slash).c_str());
- filepath = user_dir + "/" + filepath;
- ofstream file(filepath.c_str(), ios::out);
- lisp::Writer* writer = new lisp::Writer(file);
+ lisp::Writer* writer = new lisp::Writer(filename);
writer->write_comment("Level made using SuperTux's built-in Level Editor");
writer->end_list("supertux-level");
delete writer;
- file.close();
}
Level::~Level()
#include <stdexcept>
#include <assert.h>
#include <unistd.h>
+#include <physfs.h>
#include "level.h"
#include "resources.h"
#include "file_system.h"
#include "level_subset.h"
#include "lisp/parser.h"
#include "lisp/lisp.h"
+#include "lisp/writer.h"
static bool has_suffix(const std::string& data, const std::string& suffix)
{
{
name = subset;
- // Check in which directory our subset is located (ie. ~/.supertux/
- // or SUPERTUX_DATADIR)
- std::string filename = get_resource_filename(
- std::string("levels/") + subset + "/info");
- if(filename == "") {
- std::stringstream msg;
- msg << "Couldn't find level subset '" << subset << "'.";
- throw new std::runtime_error(msg.str());
- }
-
+ std::string infofile = subset + "/info";
try {
- read_info_file(filename);
+ read_info_file(infofile);
} catch(std::exception& e) {
std::stringstream msg;
- msg << "Couldn't parse info file '" << filename << "': " << e.what();
- throw new std::runtime_error(msg.str());
+ msg << "Couldn't parse info file '" << infofile << "': " << e.what();
+ throw std::runtime_error(msg.str());
}
// test is a worldmap exists
has_worldmap = false;
- std::string worldmap = get_resource_filename(
- std::string("levels/") + subset + "/worldmap.stwm");
- if(worldmap != "") {
+ std::string worldmap = subset + "/worldmap.stwm";
+ if(PHYSFS_exists(worldmap.c_str())) {
has_worldmap = true;
}
- if (levels.empty())
- { // Level info file doesn't define any levels, so read the
- // directory to see what we can find
- std::set<std::string> files;
-
- filename = datadir + "/levels/" + subset + "/";
- files = FileSystem::read_directory(filename);
+ if (levels.empty()) {
+ // Level info file doesn't define any levels, so read the
+ // directory to see what we can find
+
+ std::string path = subset + "/";
+ char** files = PHYSFS_enumerateFiles(path.c_str());
+ if(!files) {
+ std::cerr << "Warning: Couldn't read subset dir '"
+ << path << "'.\n";
+ return;
+ }
- filename = user_dir + "/levels/" + subset + "/";
- std::set<std::string> user_files = FileSystem::read_directory(filename);
- files.insert(user_files.begin(), user_files.end());
-
- for(std::set<std::string>::iterator i = files.begin(); i != files.end(); ++i)
- {
- if (has_suffix(*i, ".stl"))
- levels.push_back(get_resource_filename(
- std::string("levels/" + subset+ "/" + *i)));
- }
+ for(const char* const* filename = files; *filename != 0; ++filename) {
+ if(has_suffix(*filename, ".stl")) {
+ levels.push_back(path + *filename);
+ }
}
+ PHYSFS_freeList(files);
+ }
}
void
LevelSubset::save()
{
- FILE* fi;
- std::string filename;
-
/* Save data file: */
- filename = "/levels/" + name + "/";
-
- FileSystem::fcreatedir(filename.c_str());
- filename = std::string(user_dir) + "/levels/" + name + "/info";
- if(!FileSystem::fwriteable(filename.c_str()))
- filename = datadir + "/levels/" + name + "/info";
- if(FileSystem::fwriteable(filename.c_str()))
- {
- fi = fopen(filename.c_str(), "w");
- if (fi == NULL)
- {
- perror(filename.c_str());
- }
-
- /* Write header: */
- fprintf(fi,";; SuperTux-Level-Subset\n");
- fprintf(fi,"(supertux-level-subset\n");
-
- /* Save title info: */
- fprintf(fi," (title \"%s\")\n", title.c_str());
-
- /* Save the description: */
- fprintf(fi," (description \"%s\")\n", description.c_str());
-
- /* Save the hide from Contrbis menu boolean: */
- fprintf(fi," (hide-from-contribs %s)\n", hide_from_contribs ? "#t" : "#f");
-
- fprintf( fi,")");
- fclose(fi);
- }
+ std::string filename = name + "/info";
+ lisp::Writer writer(filename);
+
+ writer.start_list("supertux-level-subset");
+ writer.write_string("title", title);
+ writer.write_string("description", description);
+ writer.write_bool("hide-from-contribs", hide_from_contribs);
+ writer.end_list("supertux-level-subset");
}
void
std::string
LevelSubset::get_worldmap_filename()
{
- return std::string("/levels/" + name + "/worldmap.stwm");
+ return std::string(name + "/worldmap.stwm");
}
int
const lisp::Lisp* child = cur->get_car();
if(!child)
- throw new std::runtime_error("child is 0 in list entry");
+ throw std::runtime_error("child is 0 in list entry");
if(child->get_type() != lisp::Lisp::TYPE_CONS)
- throw new std::runtime_error("Expected CONS");
+ throw std::runtime_error("Expected CONS");
const lisp::Lisp* name = child->get_car();
if(!name || name->get_type() != lisp::Lisp::TYPE_SYMBOL)
- throw new std::runtime_error("Expected symbol");
+ throw std::runtime_error("Expected symbol");
name->get(current_item);
current_lisp = child->get_cdr();
#include <iostream>
#include "tinygettext/tinygettext.h"
+#include "physfs/physfs_stream.h"
+#include "resources.h"
#include "parser.h"
#include "lisp.h"
#include "file_system.h"
Lisp*
Parser::parse(const std::string& filename)
{
- std::ifstream in(filename.c_str());
+ IFileStream in(filename);
if(!in.good()) {
std::stringstream msg;
msg << "Parser problem: Couldn't open file '" << filename << "'.";
// evaluate translation function (_ str) in place here
token = lexer->getNextToken();
if(token != Lexer::TOKEN_STRING)
- throw new std::runtime_error("Expected string after '(_'");
+ throw std::runtime_error("Expected string after '(_'");
result = new Lisp(Lisp::TYPE_STRING);
if(dictionary) {
}
token = lexer->getNextToken();
if(token != Lexer::TOKEN_CLOSE_PAREN)
- throw new std::runtime_error("Expected ')' after '(_ string'");
+ throw std::runtime_error("Expected ')' after '(_ string'");
break;
}
#include <iostream>
#include "writer.h"
+#include "physfs/physfs_stream.h"
namespace lisp
{
-Writer::Writer(std::ostream& newout)
- : out(newout), indent_depth(0)
+Writer::Writer(const std::string& filename)
{
+ out = new OFileStream(filename);
+ out_owned = true;
+ indent_depth = 0;
+}
+
+Writer::Writer(std::ostream* newout)
+{
+ out = newout;
+ out_owned = false;
+ indent_depth = 0;
}
Writer::~Writer()
if(lists.size() > 0) {
std::cerr << "Warning: Not all sections closed in lispwriter!\n";
}
+ if(out_owned)
+ delete out;
}
void
Writer::write_comment(const std::string& comment)
{
- out << "; " << comment << "\n";
+ *out << "; " << comment << "\n";
}
void
Writer::start_list(const std::string& listname)
{
indent();
- out << '(' << listname << '\n';
+ *out << '(' << listname << '\n';
indent_depth += 2;
lists.push_back(listname);
indent_depth -= 2;
indent();
- out << ")\n";
+ *out << ")\n";
}
void
Writer::write_int(const std::string& name, int value)
{
indent();
- out << '(' << name << ' ' << value << ")\n";
+ *out << '(' << name << ' ' << value << ")\n";
}
void
Writer::write_float(const std::string& name, float value)
{
indent();
- out << '(' << name << ' ' << value << ")\n";
+ *out << '(' << name << ' ' << value << ")\n";
}
void
bool translatable)
{
indent();
- out << '(' << name;
+ *out << '(' << name;
if(translatable) {
- out << " (_ \"" << value << "\"))\n";
+ *out << " (_ \"" << value << "\"))\n";
} else {
- out << " \"" << value << "\")\n";
+ *out << " \"" << value << "\")\n";
}
}
Writer::write_bool(const std::string& name, bool value)
{
indent();
- out << '(' << name << ' ' << (value ? "#t" : "#f") << ")\n";
+ *out << '(' << name << ' ' << (value ? "#t" : "#f") << ")\n";
}
void
const std::vector<int>& value)
{
indent();
- out << '(' << name;
+ *out << '(' << name;
for(std::vector<int>::const_iterator i = value.begin(); i != value.end(); ++i)
- out << " " << *i;
- out << ")\n";
+ *out << " " << *i;
+ *out << ")\n";
}
void
const std::vector<unsigned int>& value)
{
indent();
- out << '(' << name;
+ *out << '(' << name;
for(std::vector<unsigned int>::const_iterator i = value.begin(); i != value.end(); ++i)
- out << " " << *i;
- out << ")\n";
+ *out << " " << *i;
+ *out << ")\n";
}
void
Writer::indent()
{
for(int i = 0; i<indent_depth; ++i)
- out << ' ';
+ *out << ' ';
}
} // end of namespace lisp
{
class Writer
- {
- public:
- Writer(std::ostream& out);
- ~Writer();
+ {
+ public:
+ Writer(const std::string& filename);
+ Writer(std::ostream* out);
+ ~Writer();
- void write_comment(const std::string& comment);
+ void write_comment(const std::string& comment);
- void start_list(const std::string& listname);
+ void start_list(const std::string& listname);
- void write_int(const std::string& name, int value);
- void write_float(const std::string& name, float value);
- void write_string(const std::string& name, const std::string& value,
- bool translatable = false);
- void write_bool(const std::string& name, bool value);
- void write_int_vector(const std::string& name, const std::vector<int>& value);
- void write_int_vector(const std::string& name, const std::vector<unsigned int>& value);
- // add more write-functions when needed...
+ void write_int(const std::string& name, int value);
+ void write_float(const std::string& name, float value);
+ void write_string(const std::string& name, const std::string& value,
+ bool translatable = false);
+ void write_bool(const std::string& name, bool value);
+ void write_int_vector(const std::string& name, const std::vector<int>& value);
+ void write_int_vector(const std::string& name, const std::vector<unsigned int>& value);
+ // add more write-functions when needed...
- void end_list(const std::string& listname);
+ void end_list(const std::string& listname);
- private:
- void indent();
-
- std::ostream& out;
- int indent_depth;
- std::vector<std::string> lists;
- };
+ private:
+ void indent();
+ std::ostream* out;
+ bool out_owned;
+ int indent_depth;
+ std::vector<std::string> lists;
+ };
+
} //namespace lisp
#endif //SUPERTUX_LISPWRITER_H
#include <dirent.h>
#include <unistd.h>
#include <assert.h>
-#ifndef WIN32
-#include <libgen.h>
-#endif
+#include <physfs.h>
#include <SDL.h>
#include <SDL_mixer.h>
#include <SDL_image.h>
#include "title.h"
#include "game_session.h"
#include "file_system.h"
-
-#ifdef WIN32
-#define mkdir(dir, mode) mkdir(dir)
-#endif
+#include "physfs/physfs_sdl.h"
SDL_Surface* screen = 0;
JoystickKeyboardController* main_controller = 0;
}
}
-static void find_directories()
+static void init_tinygettext()
{
- const char* home = getenv("HOME");
- if(home == 0) {
-#ifdef DEBUG
- std::cerr << "Couldn't find home directory.\n";
-#endif
- home = ".";
- }
-
- user_dir = home;
- user_dir += "/.supertux";
-
- // create directories
- std::string savedir = user_dir + "/save";
- mkdir(user_dir.c_str(), 0755);
- mkdir(savedir.c_str(), 0755);
+ dictionary_manager.add_directory("locale");
+ dictionary_manager.set_charset("UTF-8");
+}
- // try current directory as datadir
- if(datadir.empty()) {
- if(FileSystem::faccessible("./data/credits.txt")) {
- datadir = "./data/";
- }
+static void init_physfs(const char* argv0)
+{
+ if(!PHYSFS_init(argv0)) {
+ std::stringstream msg;
+ msg << "Couldn't initialize physfs: " << PHYSFS_getLastError();
+ throw std::runtime_error(msg.str());
}
- // Detect datadir with some linux magic
- if(datadir.empty()) {
- std::string exedir;
-#ifdef WIN32
- exedir = ".";
-#else
- char exe_file[PATH_MAX];
- if(readlink("/proc/self/exe", exe_file, PATH_MAX) >= 0) {
- exedir = std::string(dirname(exe_file));
- } else {
-#ifdef DEBUG
- std::cerr << "Couldn't read /proc/self/exe \n";
-#endif
- exedir = ".";
- }
-#endif
- std::string testdir = exedir + "/data/";
- if(access(testdir.c_str(), F_OK) == 0) {
- datadir = testdir;
+ // Initialize physfs (this is a slightly modified version of
+ // PHYSFS_setSaneConfig
+ const char* application = PACKAGE_NAME;
+ const char* userdir = PHYSFS_getUserDir();
+ const char* dirsep = PHYSFS_getDirSeparator();
+ char* writedir = new char[strlen(userdir) + strlen(application) + 2];
+
+ // Set configuration directory
+ sprintf(writedir, "%s.%s", userdir, application);
+ if(!PHYSFS_setWriteDir(writedir)) {
+ // try to create the directory
+ char* mkdir = new char[strlen(application) + 2];
+ sprintf(mkdir, ".%s", application);
+ if(!PHYSFS_setWriteDir(userdir) || !PHYSFS_mkdir(mkdir)) {
+ std::ostringstream msg;
+ msg << "Failed creating configuration directory '"
+ << writedir << "': " << PHYSFS_getLastError();
+ delete[] writedir;
+ delete[] mkdir;
+ throw std::runtime_error(msg.str());
}
+ delete[] mkdir;
- testdir = exedir + "/../share/supertux/";
- if(datadir.empty() && access(testdir.c_str(), F_OK) == 0) {
- datadir = testdir;
+ if(!PHYSFS_setWriteDir(writedir)) {
+ std::ostringstream msg;
+ msg << "Failed to use configuration directory '"
+ << writedir << "': " << PHYSFS_getLastError();
+ delete[] writedir;
+ throw std::runtime_error(msg.str());
}
- }
+ }
+ PHYSFS_addToSearchPath(writedir, 0);
+ delete[] writedir;
+
+ // Search for archives and add them to the search path
+ const char* archiveExt = "zip";
+ char** rc = PHYSFS_enumerateFiles("/");
+ size_t extlen = strlen(archiveExt);
+
+ for(char** i = rc; *i != 0; ++i) {
+ size_t l = strlen(*i);
+ if((l > extlen) && ((*i)[l - extlen - 1] == '.')) {
+ const char* ext = (*i) + (l - extlen);
+ if(strcasecmp(ext, archiveExt) == 0) {
+ const char* d = PHYSFS_getRealDir(*i);
+ char* str = new char[strlen(d) + strlen(dirsep) + l + 1];
+ sprintf(str, "%s%s%s", d, dirsep, *i);
+ PHYSFS_addToSearchPath(str, 1);
+ delete[] str;
+ }
+ }
+ }
-#ifdef DATA_PREFIX
- // use default location
- if(datadir.empty()) {
- datadir = DATA_PREFIX;
+ PHYSFS_freeList(rc);
+
+ // when started from source dir...
+ std::string dir = PHYSFS_getBaseDir();
+ dir += "/data";
+ std::string testfname = dir;
+ testfname += "/credits.txt";
+ FILE* f = fopen(testfname.c_str(), "r");
+ if(f) {
+ fclose(f);
+ if(!PHYSFS_addToSearchPath(dir.c_str(), 1)) {
+ std::cout << "Warning: Couldn't add '" << dir
+ << "' to physfs searchpath: " << PHYSFS_getLastError() << "\n";
+ }
+ }
+
+#if defined(APPDATADIR) || defined(ENABLE_BINRELOC)
+ std::string datadir;
+#ifdef ENABLE_BINRELOC
+ char* brdatadir = br_strcat(DATADIR, "/" PACKAGE_NAME);
+ datadir = brdatadir;
+ free(brdatadir);
+#else
+ datadir = APPDATADIR;
+#endif
+ if(!PHYSFS_addToSearchPath(datadir.c_str(), 1)) {
+ std::cout << "Couldn't add '" << datadir
+ << "' to physfs searchpath: " << PHYSFS_getLastError() << "\n";
}
#endif
- if(datadir.empty())
- throw std::runtime_error("Couldn't find datadir");
-}
+ // allow symbolic links
+ PHYSFS_permitSymbolicLinks(1);
-static void init_tinygettext()
-{
- dictionary_manager.add_directory(datadir + "/locale");
- dictionary_manager.set_charset("UTF-8");
+ //show search Path
+ for(char** i = PHYSFS_getSearchPath(); *i != NULL; i++)
+ printf("[%s] is in the search path.\n", *i);
}
static void print_usage(const char* argv0)
SDL_WM_SetCaption(PACKAGE_NAME " " PACKAGE_VERSION, 0);
// set icon
- SDL_Surface* icon = IMG_Load(
- get_resource_filename("images/engine/icons/supertux.xpm").c_str());
+ SDL_Surface* icon = IMG_Load_RW(
+ get_physfs_SDLRWops("images/engine/icons/supertux.xpm"), true);
if(icon != 0) {
SDL_WM_SetIcon(icon, 0);
SDL_FreeSurface(icon);
try {
#endif
srand(time(0));
+ init_physfs(argv[0]);
init_sdl();
main_controller = new JoystickKeyboardController();
- find_directories();
init_config();
init_tinygettext();
parse_commandline(argc, argv);
setup_menu();
load_shared();
if(config->start_level != "") {
- GameSession session(config->start_level, ST_GL_LOAD_LEVEL_FILE);
+ // we have a normal path specified at commandline not physfs paths.
+ // So we simply mount that path here...
+ std::string dir = FileSystem::dirname(config->start_level);
+ PHYSFS_addToSearchPath(dir.c_str(), true);
+ GameSession session(
+ FileSystem::basename(config->start_level), ST_GL_LOAD_LEVEL_FILE);
if(config->start_demo != "")
session.play_demo(config->start_demo);
if(config->record_demo != "")
delete config;
delete main_controller;
SDL_Quit();
+ PHYSFS_deinit();
return 0;
}
this->speed = speed;
delete image;
- image = new Surface(datadir + "/images/background/" + name, false);
+ image = new Surface("images/background/" + name, false);
}
void
SnowParticleSystem::SnowParticleSystem()
{
- snowimages[0] = new Surface(datadir+"/images/objects/particles/snow0.png", true);
- snowimages[1] = new Surface(datadir+"/images/objects/particles/snow1.png", true);
- snowimages[2] = new Surface(datadir+"/images/objects/particles/snow2.png", true);
+ snowimages[0] = new Surface("images/objects/particles/snow0.png", true);
+ snowimages[1] = new Surface("images/objects/particles/snow1.png", true);
+ snowimages[2] = new Surface("images/objects/particles/snow2.png", true);
virtual_width = SCREEN_WIDTH * 2;
// Ghosts don't change their movement pattern - not random
GhostParticleSystem::GhostParticleSystem()
{
- ghosts[0] = new Surface(datadir+"/images/objects/particles/ghost0.png", true);
- ghosts[1] = new Surface(datadir+"/images/objects/particles/ghost1.png", true);
+ ghosts[0] = new Surface("images/objects/particles/ghost0.png", true);
+ ghosts[1] = new Surface("images/objects/particles/ghost1.png", true);
virtual_width = SCREEN_WIDTH * 2;
CloudParticleSystem::CloudParticleSystem()
{
- cloudimage = new Surface(datadir + "/images/objects/particles/cloud.png", true);
+ cloudimage = new Surface("images/objects/particles/cloud.png", true);
virtual_width = 2000.0;
RainParticleSystem::RainParticleSystem()
{
- rainimages[0] = new Surface(datadir+"/images/objects/particles/rain0.png", true);
- rainimages[1] = new Surface(datadir+"/images/objects/particles/rain1.png", true);
+ rainimages[0] = new Surface("images/objects/particles/rain0.png", true);
+ rainimages[1] = new Surface("images/objects/particles/rain1.png", true);
virtual_width = SCREEN_WIDTH * 2;
CometParticleSystem::CometParticleSystem()
{
- cometimages[0] = new Surface(datadir+"/images/creatures/mr_bomb/exploding-left-0.png", true);
- cometimages[1] = new Surface(datadir+"/images/creatures/mr_bomb/exploding-left-0.png", true);
+ cometimages[0] = new Surface("images/creatures/mr_bomb/exploding-left-0.png", true);
+ cometimages[1] = new Surface("images/creatures/mr_bomb/exploding-left-0.png", true);
virtual_width = SCREEN_WIDTH * 2;
#include "object/gameobjs.h"
#include "object/player.h"
-std::string datadir;
-std::string user_dir;
-
MusicRef herring_song;
MusicRef level_end_song;
MusicRef credits_song;
void load_shared()
{
/* Load GUI/menu images: */
- checkbox = new Surface(datadir + "/images/engine/menu/checkbox-unchecked.png", true);
- checkbox_checked = new Surface(datadir + "/images/engine/menu/checkbox-checked.png", true);
- back = new Surface(datadir + "/images/engine/menu/arrow-back.png", true);
- arrow_left = new Surface(datadir + "/images/engine/menu/arrow-left.png", true);
- arrow_right = new Surface(datadir + "/images/engine/menu/arrow-right.png", true);
+ checkbox = new Surface("images/engine/menu/checkbox-unchecked.png", true);
+ checkbox_checked = new Surface("images/engine/menu/checkbox-checked.png", true);
+ back = new Surface("images/engine/menu/arrow-back.png", true);
+ arrow_left = new Surface("images/engine/menu/arrow-left.png", true);
+ arrow_right = new Surface("images/engine/menu/arrow-right.png", true);
/* Load the mouse-cursor */
- mouse_cursor = new MouseCursor(datadir + "/images/engine/menu/mousecursor.png");
+ mouse_cursor = new MouseCursor("images/engine/menu/mousecursor.png");
MouseCursor::set_current(mouse_cursor);
/* Load global images: */
- gold_text = new Font(datadir + "/images/engine/fonts/gold.png", Font::TEXT, 16,18);
- blue_text = new Font(datadir + "/images/engine/fonts/blue.png", Font::TEXT, 16,18,3);
- white_text = new Font(datadir + "/images/engine/fonts/white.png",
- Font::TEXT, 16,18);
- gray_text = new Font(datadir + "/images/engine/fonts/gray.png",
- Font::TEXT, 16,18);
- white_small_text = new Font(datadir + "/images/engine/fonts/white-small.png",
+ gold_text = new Font("images/engine/fonts/gold.png", Font::TEXT, 16,18);
+ blue_text = new Font("images/engine/fonts/blue.png", Font::TEXT, 16,18,3);
+ white_text = new Font("images/engine/fonts/white.png", Font::TEXT, 16,18);
+ gray_text = new Font("images/engine/fonts/gray.png", Font::TEXT, 16,18);
+ white_small_text = new Font("images/engine/fonts/white-small.png",
Font::TEXT, 8,9, 1);
- white_big_text = new Font(datadir + "/images/engine/fonts/white-big.png",
+ white_big_text = new Font("images/engine/fonts/white-big.png",
Font::TEXT, 20,22, 3);
- yellow_nums = new Font(datadir + "/images/engine/fonts/numbers.png",
- Font::NUM, 32,32);
+ yellow_nums = new Font("images/engine/fonts/numbers.png", Font::NUM, 32,32);
Menu::default_font = white_text;
Menu::active_font = blue_text;
Button::info_font = white_small_text;
- sprite_manager = new SpriteManager(
- get_resource_filename("/images/sprites.strf"));
- tile_manager = new TileManager("/images/tiles.strf");
+ sprite_manager = new SpriteManager("images/sprites.strf");
+ tile_manager = new TileManager("images/tiles.strf");
/* Tuxes: */
char img_name[1024];
for (int i = 0; i < GROWING_FRAMES; i++)
{
- sprintf(img_name, "%s/images/creatures/tux_grow/left-%i.png", datadir.c_str(), i+1);
+ sprintf(img_name, "images/creatures/tux_grow/left-%i.png", i+1);
growingtux_left[i] = new Surface(img_name, true);
- sprintf(img_name, "%s/images/creatures/tux_grow/right-%i.png", datadir.c_str(), i+1);
+ sprintf(img_name, "images/creatures/tux_grow/right-%i.png", i+1);
growingtux_right[i] = new Surface(img_name, true);
}
load_object_gfx();
/* Tux life: */
- tux_life = new Surface(datadir + "/images/creatures/tux_small/tux-life.png",
- true);
+ tux_life = new Surface("images/creatures/tux_small/tux-life.png", true);
/* Sound effects: */
sound_manager->preload_sound("jump");
sound_manager->preload_sound("fireworks");
/* Herring song */
- herring_song = sound_manager->load_music(datadir + "/music/salcon.mod");
- level_end_song = sound_manager->load_music(datadir + "/music/leveldone.mod");
+ herring_song = sound_manager->load_music("music/salcon.mod");
+ level_end_song = sound_manager->load_music("music/leveldone.mod");
}
/* Free shared data: */
delete mouse_cursor;
}
-std::string get_resource_filename(const std::string& resource)
-{
- std::string filepath = user_dir + "/" + resource;
- if(FileSystem::faccessible(filepath))
- return filepath;
-
- filepath = datadir + resource;
- if(FileSystem::faccessible(filepath))
- return filepath;
-
- std::cerr << "Couldn't find resource: '" << resource << "'." << std::endl;
- return "";
-}
extern Font* white_big_text;
extern Font* yellow_nums;
-extern std::string datadir;
-extern std::string user_dir;
-
-/** maps a virtual resource path to a real path (ie. levels/bla is mapped to
- * $DATADIR/levels/bla or $HOME/.supertux/levels/bla)
- * All paths inside the game should be handled in as virtual paths and then
- * expanded with this function just before the call to fopen or std::ifstream.
- */
-std::string get_resource_filename(const std::string& resource);
-
void load_shared();
void unload_shared();
#include <stdio.h>
#include <string>
#include <squirrel.h>
+#include <sqstdio.h>
#include "textscroller.h"
#include "functions.h"
#include "script_interpreter.h"
::display_text_file(file);
}
+void import(HSQUIRRELVM v, const std::string& filename)
+{
+ std::string file
+ = ScriptInterpreter::current()->get_working_directory() + filename;
+ if(sqstd_loadfile(v, file.c_str(), true) < 0) {
+ std::cerr << "Warning couldn't load script '" << filename << "' ("
+ << file << ").\n";
+ return;
+ }
+
+ sq_push(v, -2);
+ if(sq_call(v, 1, false) < 0) {
+ std::cerr << "Couldn't execute script '" << filename << "' ("
+ << file << ").\n";
+ return;
+ }
+}
+
}
* files)
*/
std::string translate(const std::string& text);
+/** load a script file and executes it
+ * This is typically used to import functions from external files.
+ * */
+void import(HSQUIRRELVM v, const std::string& filename);
}
#include <stdarg.h>
#include <stdexcept>
#include <sstream>
+#include <fstream>
#include <sqstdio.h>
#include <sqstdaux.h>
#include <sqstdblob.h>
#include "sector.h"
#include "file_system.h"
#include "game_session.h"
+#include "resources.h"
+#include "physfs/physfs_stream.h"
#include "object/text_object.h"
#include "object/scripted_object.h"
#include "object/display_effect.h"
return c;
}
-
void
-ScriptInterpreter::load_script(std::istream& in, const std::string& sourcename)
+ScriptInterpreter::run_script(std::istream& in, const std::string& sourcename)
{
if(sq_compile(v, squirrel_read_char, &in, sourcename.c_str(), true) < 0)
throw SquirrelError(v, "Couldn't parse script");
-}
-
-void
-ScriptInterpreter::start_script()
-{
+
_current = this;
sq_push(v, -2);
if(sq_call(v, 1, false) < 0)
const std::string& script)
{
try {
- std::auto_ptr<ScriptInterpreter> interpreter
- (new ScriptInterpreter(GameSession::current()->get_working_directory()));
+ std::string workdir = GameSession::current()->get_working_directory();
+ std::auto_ptr<ScriptInterpreter> interpreter(
+ new ScriptInterpreter(workdir));
interpreter->register_sector(sector);
+
+ // load default.nut file if it exists
+ try {
+ std::string filename = workdir + "/default.nut";
+ IFileStream in(filename);
+ interpreter->run_script(in, filename);
+ } catch(std::exception& e) {
+ // nothing
+ }
+
std::istringstream in(script);
- interpreter->load_script(in, name);
- interpreter->start_script();
+ interpreter->run_script(in, name);
sector->add_object(interpreter.release());
} catch(std::exception& e) {
std::cerr << "Couldn't start '" << name << "' script: " << e.what() << "\n";
void draw(DrawingContext& );
void update(float );
- void load_script(std::istream& in, const std::string& sourcename = "");
- void start_script();
+ void run_script(std::istream& in, const std::string& sourcename = "");
void expose_object(void* object, const std::string& name,
const std::string& type);
return 1;
}
+static int import_wrapper(HSQUIRRELVM v)
+{
+ HSQUIRRELVM arg0 = v;
+ const char* arg1;
+ sq_getstring(v, 4, &arg1);
+
+ Scripting::import(arg0, arg1);
+
+ return 0;
+}
+
WrappedFunction supertux_global_functions[] = {
{ "display_text_file", &display_text_file_wrapper },
{ "set_wakeup_time", &set_wakeup_time_wrapper },
{ "translate", &translate_wrapper },
+ { "import", &import_wrapper },
{ 0, 0 }
};
void
Sector::load_music()
{
- level_song = sound_manager->load_music(
- get_resource_filename("/music/" + song_title));
+ level_song = sound_manager->load_music("/music/" + song_title);
}
void
}
for(std::vector<std::string>::size_type i = 0; i < images.size(); i++) {
- action->surfaces.push_back(
- new Surface(datadir + "/images/" + images[i], true));
+ action->surfaces.push_back(new Surface("images/" + images[i], true));
}
}
actions[action->name] = action;
}
}
-void display_text_file(const std::string& file)
+void display_text_file(const std::string& filename)
{
const Font* heading_font = white_big_text;
const Font* normal_font = white_text;
std::string background_file;
std::vector<std::string> lines;
- std::string filename = datadir + "/" + file;
lisp::Parser parser;
try {
std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
split_text(text, lines);
// load background image
- Surface* background = new Surface(
- get_resource_filename("images/background/" + background_file), false);
+ Surface* background
+ = new Surface("images/background/" + background_file, false);
bool done = false;
float scroll = 0;
imagespecs.end(); ++i) {
const ImageSpec& spec = *i;
Surface* surface;
- std::string file
- = get_resource_filename(tilesetpath + spec.file);
+ std::string file = tilesetpath + spec.file;
if(spec.rect.get_width() <= 0) {
surface = new Surface(file, true);
} else {
images.push_back(surface);
}
if(editor_imagefile != "") {
- editor_image = new Surface(
- get_resource_filename(tilesetpath + editor_imagefile), true);
+ editor_image = new Surface(tilesetpath + editor_imagefile, true);
}
}
}
lisp::Parser parser;
- std::auto_ptr<lisp::Lisp> root (parser.parse(
- get_resource_filename(filename)));
+ std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
const lisp::Lisp* tiles_lisp = root->get_lisp("supertux-tiles");
if(!tiles_lisp)
#include <sys/types.h>
#include <iconv.h>
-#include <dirent.h>
#include <fstream>
#include <iostream>
#include <ctype.h>
#include <errno.h>
+
#include "tinygettext.h"
+#include "physfs/physfs_stream.h"
//#define TRANSLATION_DEBUG
/** Convert \a which is in \a from_charset to \a to_charset and return it */
std::string convert(const std::string& text,
const std::string& from_charset,
- const std::string& to_charset)
+ const std::string& to_charset)
{
if (from_charset == to_charset)
return text;
iconv_t cd = iconv_open(to_charset.c_str(), from_charset.c_str());
size_t in_len = text.length();
- size_t out_len = text.length()*3; // FIXME: cross fingers that this is enough
+ size_t out_len = text.length()*3; // FIXME: cross fingers that this is enough
char* out_orig = new char[out_len];
char* in_orig = new char[in_len+1];
for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
{
- DIR* dir = opendir(p->c_str());
- if (!dir)
+ char** files = PHYSFS_enumerateFiles(p->c_str());
+ if(!files)
{
- std::cerr << "Error: opendir() failed on " << *p << std::endl;
+ std::cerr << "Error: enumerateFiles() failed on " << *p << std::endl;
}
else
{
- struct dirent* ent;
- while((ent = readdir(dir)))
- {
- if (std::string(ent->d_name) == lang + ".po")
- {
- std::string pofile = *p + "/" + ent->d_name;
- std::ifstream in(pofile.c_str());
- if (!in)
- {
- std::cerr << "Error: Failure file opening: " << pofile << std::endl;
- }
- else
- {
- read_po_file(dict, in);
- }
- }
+ for(const char* const* filename = files;
+ *filename != 0; filename++) {
+ if(std::string(*filename) == lang + ".po") {
+ std::string pofile = *p + "/" + *filename;
+ try {
+ IFileStream in(pofile);
+ read_po_file(dict, in);
+ } catch(std::exception& e) {
+ std::cerr << "Error: Failure file opening: " << pofile << std::endl;
+ std::cerr << e.what() << "\n";
+ }
}
- closedir(dir);
+ }
+ PHYSFS_freeList(files);
}
}
for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
{
- DIR* dir = opendir(p->c_str());
- if (!dir)
+ char** files = PHYSFS_enumerateFiles(p->c_str());
+ if (!files)
{
std::cerr << "Error: opendir() failed on " << *p << std::endl;
}
else
{
- struct dirent* ent;
- while((ent = readdir(dir)))
- {
- if (has_suffix(ent->d_name, ".po"))
- {
- std::string filename = ent->d_name;
+ for(const char* const* file = files; *file != 0; file++) {
+ if(has_suffix(*file, ".po")) {
+ std::string filename = *file;
languages.insert(filename.substr(0, filename.length()-3));
- }
- }
- closedir(dir);
+ }
+ }
+ PHYSFS_freeList(files);
}
}
return languages;
current_dict = & (get_dictionary(language));
}
+const std::string&
+DictionaryManager::get_language() const
+{
+ return language;
+}
+
void
DictionaryManager::set_charset(const std::string& charset)
{
}
}
-std::string
-Dictionary::translate(const std::string& msgid)
+const char*
+Dictionary::translate(const char* msgid)
{
Entries::iterator i = entries.find(msgid);
if (i != entries.end() && !i->second.empty())
{
- return i->second;
+ return i->second.c_str();
}
else
{
}
}
-const char*
-Dictionary::translate(const char* msgid)
+std::string
+Dictionary::translate(const std::string& msgid)
{
Entries::iterator i = entries.find(msgid);
- if(i == entries.end() || i->second.empty()) {
+ if (i != entries.end() && !i->second.empty())
+ {
+ return i->second;
+ }
+ else
+ {
#ifdef TRANSLATION_DBEUG
- std::cout << "Error: Couldn't translate: " << msgid << std::endl;
-#endif
- return msgid;
- }
-
- return i->second.c_str();
+ std::cout << "Error: Couldn't translate: " << msgid << std::endl;
+#endif
+ return msgid;
+ }
}
void
line_num = 0;
char c = in.get();
if(c == (char) 0xef) { // skip UTF-8 intro that some texteditors produce
- in.get();
- in.get();
+ in.get();
+ in.get();
} else {
- in.unget();
+ in.unget();
}
tokenize_po(in);
}
to_charset = dict.get_charset();
if (to_charset.empty())
- { // No charset requested from the dict, so we use the one from the .po
- to_charset = from_charset;
+ { // No charset requested from the dict, use utf-8
+ to_charset = "utf-8";
dict.set_charset(from_charset);
}
}
/** Translate the string \a msgid. */
std::string translate(const std::string& msgid);
-
+ /** Translate the string \a msgid. */
const char* translate(const char* msgid);
/** Add a translation from \a msgid to \a msgstr to the dictionary,
/** Set a language based on a four? letter country code */
void set_language(const std::string& langspec);
+ /** returns the (normalized) country code of the currently used language */
+ const std::string& get_language() const;
+
/** Set a charset that will be set on the returned dictionaries */
void set_charset(const std::string& charset);
#include <cmath>
#include <SDL.h>
#include <SDL_image.h>
+#include <physfs.h>
#ifndef WIN32
#include <sys/types.h>
void generate_contrib_menu()
{
/** Generating contrib levels list by making use of Level Subset */
- std::set<std::string> level_subsets = FileSystem::dsubdirs("/levels", "info");
+ std::vector<std::string> level_subsets;
+ char** files = PHYSFS_enumerateFiles("levels/");
+ for(const char* const* filename = files; *filename != 0; ++filename) {
+ std::string filepath = std::string("levels/") + *filename;
+ if(PHYSFS_isDirectory(filepath.c_str()))
+ level_subsets.push_back(filepath);
+ }
+ PHYSFS_freeList(files);
free_contrib_menu();
contrib_menu->add_hl();
int i = 0;
- for (std::set<std::string>::iterator it = level_subsets.begin();
- it != level_subsets.end(); ++it)
- {
- LevelSubset* subset = new LevelSubset();
+ for (std::vector<std::string>::iterator it = level_subsets.begin();
+ it != level_subsets.end(); ++it) {
+ try {
+ std::auto_ptr<LevelSubset> subset (new LevelSubset());
subset->load(*it);
if(subset->hide_from_contribs) {
- delete subset;
continue;
}
- contrib_menu->add_submenu(subset->title, contrib_subset_menu, i);
- contrib_subsets.push_back(subset);
- ++i;
+ contrib_menu->add_submenu(subset->title, contrib_subset_menu, i++);
+ contrib_subsets.push_back(subset.release());
+ } catch(std::exception& e) {
+#ifdef DEBUG
+ std::cerr << "Couldn't parse levelset info for '"
+ << *it << "': " << e.what() << "\n";
+#endif
}
+ }
contrib_menu->add_hl();
contrib_menu->add_back(_("Back"));
-
- level_subsets.clear();
}
std::string get_level_name(const std::string& filename)
context.do_drawing();
// TODO: slots should be available for contrib maps
- worldmap.loadgame(user_dir + "/save/" + subset.name + "-slot1.stsg");
+ worldmap.loadgame("save/" + subset.name + "-slot1.stsg");
worldmap.display(); // run the map
Menu::set_current(main_menu);
MusicRef credits_music;
controller = new CodeController();
- titlesession = new GameSession(get_resource_filename("levels/misc/menu.stl"),
- ST_GL_DEMO_GAME);
+ titlesession = new GameSession("levels/misc/menu.stl", ST_GL_DEMO_GAME);
/* Load images: */
- bkg_title = new Surface(datadir + "/images/background/arctis.jpg", false);
- logo = new Surface(datadir + "/images/engine/menu/logo.png", true);
- //img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", true);
+ bkg_title = new Surface("images/background/arctis.jpg", false);
+ logo = new Surface("images/engine/menu/logo.png", true);
+ //img_choose_subset = new Surface("images/status/choose-level-subset.png", true);
titlesession->get_current_sector()->activate("main");
titlesession->set_current();
case MNID_CREDITS:
fadeout(500);
credits_music = sound_manager->load_music(
- get_resource_filename("/music/credits.ogg"));
+ "/music/credits.ogg");
sound_manager->play_music(credits_music);
display_text_file("credits.txt");
fadeout(500);
stream << slot;
std::string str = _("Are you sure you want to delete slot") + stream.str() + "?";
- if(confirm_dialog(bkg_title, str.c_str()))
- {
- str = user_dir + "/save/slot" + stream.str() + ".stsg";
+ if(confirm_dialog(bkg_title, str.c_str())) {
+ str = "save/slot" + stream.str() + ".stsg";
printf("Removing: %s\n",str.c_str());
- remove(str.c_str());
- }
+ PHYSFS_delete(str.c_str());
+ }
update_load_save_game_menu(load_game_menu);
Menu::set_current(main_menu);
#include <SDL_image.h>
#include "gameconfig.h"
+#include "physfs/physfs_sdl.h"
#include "video/surface.h"
#include "video/screen.h"
SDL_Surface * temp;
SDL_Surface * conv;
- temp = IMG_Load(file.c_str());
+ temp = IMG_Load_RW(get_physfs_SDLRWops(file), true);
if (temp == 0) {
std::stringstream msg;
msg << "Couldn't load '" << file << "': " << SDL_GetError();
SDL_Surface* sdl_surface;
SDL_Surface* temp;
- temp = IMG_Load(file.c_str());
+ temp = IMG_Load_RW(get_physfs_SDLRWops(file), true);
if (temp == 0) {
std::stringstream msg;
msg << "Couldn't load file '" << file << "': " << SDL_GetError();
tux = new Tux(this);
add_object(tux);
- leveldot_green
- = new Surface(datadir + "/images/tiles/worldmap/leveldot_green.png", true);
- leveldot_red
- = new Surface(datadir + "/images/tiles/worldmap/leveldot_red.png", true);
- messagedot
- = new Surface(datadir + "/images/tiles/worldmap/messagedot.png", true);
- teleporterdot
- = new Surface(datadir + "/images/tiles/worldmap/teleporterdot.png", true);
+ leveldot_green= new Surface("images/tiles/worldmap/leveldot_green.png", true);
+ leveldot_red = new Surface("images/tiles/worldmap/leveldot_red.png", true);
+ messagedot = new Surface("images/tiles/worldmap/messagedot.png", true);
+ teleporterdot = new Surface("images/tiles/worldmap/teleporterdot.png", true);
name = "<no title>";
music = "salcon.mod";
try {
lisp::Parser parser;
- std::string filename = get_resource_filename(map_filename);
- std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
+ std::auto_ptr<lisp::Lisp> root (parser.parse(map_filename));
const lisp::Lisp* lisp = root->get_lisp("supertux-worldmap");
if(!lisp)
- throw new std::runtime_error("file isn't a supertux-worldmap file.");
+ throw std::runtime_error("file isn't a supertux-worldmap file.");
clear_objects();
lisp::ListIterator iter(lisp);
try {
lisp::Parser parser;
- std::auto_ptr<lisp::Lisp> root (
- parser.parse(get_resource_filename(levels_path + level.name)));
+ std::auto_ptr<lisp::Lisp> root (parser.parse(levels_path + level.name));
const lisp::Lisp* level_lisp = root->get_lisp("supertux-level");
if(!level_lisp)
// do a shriking fade to the level
shrink_fade(Vector((level->pos.x*32 + 16 + offset.x),
(level->pos.y*32 + 16 + offset.y)), 500);
- GameSession session(get_resource_filename(levels_path + level->name),
+ GameSession session(levels_path + level->name,
ST_GL_LOAD_LEVEL_FILE, &level->statistics);
switch (session.run())
std::auto_ptr<ScriptInterpreter> interpreter
(new ScriptInterpreter(levels_path));
std::istringstream in(level->extro_script);
- interpreter->load_script(in, "level-extro-script");
- interpreter->start_script();
+ interpreter->run_script(in, "level-extro-script");
add_object(interpreter.release());
} catch(std::exception& e) {
std::cerr << "Couldn't run level-extro-script:" << e.what() << "\n";
quit = false;
- song = sound_manager->load_music(datadir + "/music/" + music);
+ song = sound_manager->load_music("music/" + music);
sound_manager->play_music(song);
if(!intro_displayed && intro_script != "") {
std::auto_ptr<ScriptInterpreter> interpreter
(new ScriptInterpreter(levels_path));
std::istringstream in(intro_script);
- interpreter->load_script(in, "worldmap-intro-script");
- interpreter->start_script();
+ interpreter->run_script(in, "worldmap-intro-script");
add_object(interpreter.release());
} catch(std::exception& e) {
std::cerr << "Couldn't execute worldmap-intro-script: "
if(filename == "")
return;
- std::ofstream file(filename.c_str(), std::ios::out);
- lisp::Writer writer(file);
+ lisp::Writer writer(filename);
int nb_solved_levels = 0, total_levels = 0;
for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {