summaryrefslogtreecommitdiffstats
path: root/src/common/resources
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/resources')
-rw-r--r--src/common/resources/inputstream.cpp61
-rw-r--r--src/common/resources/inputstream.h37
-rw-r--r--src/common/resources/inputstreambuffer.cpp134
-rw-r--r--src/common/resources/inputstreambuffer.h51
-rw-r--r--src/common/resources/outputstream.cpp55
-rw-r--r--src/common/resources/outputstream.h36
-rw-r--r--src/common/resources/outputstreambuffer.cpp91
-rw-r--r--src/common/resources/outputstreambuffer.h46
-rw-r--r--src/common/resources/resourcemanager.cpp295
-rw-r--r--src/common/resources/resourcemanager.h66
-rw-r--r--src/common/resources/sndfile.cpp133
-rw-r--r--src/common/resources/sndfile.h49
12 files changed, 1054 insertions, 0 deletions
diff --git a/src/common/resources/inputstream.cpp b/src/common/resources/inputstream.cpp
new file mode 100644
index 0000000..57d1305
--- /dev/null
+++ b/src/common/resources/inputstream.cpp
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#include "common/resources/inputstream.h"
+#include "common/resources/inputstreambuffer.h"
+
+
+CInputStream::CInputStream() : std::istream(new CInputStreamBuffer())
+{
+}
+
+CInputStream::CInputStream(const std::string& filename) : std::istream(new CInputStreamBuffer())
+{
+ open(filename);
+}
+
+
+CInputStream::~CInputStream()
+{
+ delete rdbuf();
+}
+
+
+void CInputStream::open(const std::string& filename)
+{
+ static_cast<CInputStreamBuffer *>(rdbuf())->open(filename);
+}
+
+
+void CInputStream::close()
+{
+ static_cast<CInputStreamBuffer *>(rdbuf())->close();
+}
+
+
+bool CInputStream::is_open()
+{
+ return static_cast<CInputStreamBuffer *>(rdbuf())->is_open();
+}
+
+
+size_t CInputStream::size()
+{
+ return static_cast<CInputStreamBuffer *>(rdbuf())->size();
+}
diff --git a/src/common/resources/inputstream.h b/src/common/resources/inputstream.h
new file mode 100644
index 0000000..74e17b2
--- /dev/null
+++ b/src/common/resources/inputstream.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#pragma once
+
+#include <istream>
+#include <string>
+
+
+class CInputStream : public std::istream
+{
+public:
+ CInputStream();
+ CInputStream(const std::string& filename);
+ virtual ~CInputStream();
+
+ void open(const std::string& filename);
+ void close();
+ bool is_open();
+ size_t size();
+};
diff --git a/src/common/resources/inputstreambuffer.cpp b/src/common/resources/inputstreambuffer.cpp
new file mode 100644
index 0000000..9ac1fec
--- /dev/null
+++ b/src/common/resources/inputstreambuffer.cpp
@@ -0,0 +1,134 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#include "common/resources/inputstreambuffer.h"
+
+#include "common/resources/resourcemanager.h"
+
+#include <stdexcept>
+#include <sstream>
+
+CInputStreamBuffer::CInputStreamBuffer(size_t buffer_size) : m_buffer_size(buffer_size)
+{
+ if (buffer_size <= 0)
+ {
+ throw std::runtime_error("File buffer must be larger then 0 bytes");
+ }
+
+ m_buffer = new char[buffer_size];
+ m_file = nullptr;
+}
+
+
+CInputStreamBuffer::~CInputStreamBuffer()
+{
+ close();
+ delete m_buffer;
+}
+
+
+void CInputStreamBuffer::open(const std::string &filename)
+{
+ if (PHYSFS_isInit())
+ m_file = PHYSFS_openRead(CResourceManager::CleanPath(filename).c_str());
+}
+
+
+void CInputStreamBuffer::close()
+{
+ if (is_open())
+ PHYSFS_close(m_file);
+}
+
+
+bool CInputStreamBuffer::is_open()
+{
+ return m_file;
+}
+
+
+size_t CInputStreamBuffer::size()
+{
+ return PHYSFS_fileLength(m_file);
+}
+
+
+std::streambuf::int_type CInputStreamBuffer::underflow()
+{
+ if (gptr() < egptr())
+ return traits_type::to_int_type(*gptr());
+
+ if (PHYSFS_eof(m_file))
+ return traits_type::eof();
+
+ PHYSFS_sint64 read_count = PHYSFS_read(m_file, m_buffer, sizeof(char), m_buffer_size);
+ if (read_count <= 0)
+ return traits_type::eof();
+
+ setg(m_buffer, m_buffer, m_buffer + read_count);
+
+ return traits_type::to_int_type(*gptr());
+}
+
+
+std::streampos CInputStreamBuffer::seekpos(std::streampos sp, std::ios_base::openmode which)
+{
+ return seekoff(off_type(sp), std::ios_base::beg, which);
+}
+
+
+std::streampos CInputStreamBuffer::seekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which)
+{
+ /* A bit of explanation:
+ We are reading file by m_buffer_size parts so our 3 internal pointers will be
+ * eback (not used here) - start of block
+ * gptr - position of read cursor in block
+ * egtpr - end of block
+ off argument is relative to way */
+
+ std::streamoff new_position;
+
+ switch (way)
+ {
+ case std::ios_base::beg:
+ new_position = off;
+ break;
+
+ case std::ios_base::cur:
+ // tell will give cursor at begining of block so we have to add where in block we currently are
+ new_position = off + static_cast<off_type>(PHYSFS_tell(m_file)) - static_cast<off_type> (egptr() - gptr());
+ break;
+
+ case std::ios_base::end:
+ new_position = off + static_cast<off_type>(PHYSFS_fileLength(m_file));
+ break;
+
+ default:
+ break;
+ }
+
+ if (PHYSFS_seek(m_file, new_position))
+ {
+ setg(m_buffer, m_buffer, m_buffer); // reset buffer
+
+ return pos_type(new_position);
+ }
+
+ return pos_type(off_type(-1));
+}
diff --git a/src/common/resources/inputstreambuffer.h b/src/common/resources/inputstreambuffer.h
new file mode 100644
index 0000000..8c45c22
--- /dev/null
+++ b/src/common/resources/inputstreambuffer.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#pragma once
+
+#include <streambuf>
+#include <string>
+#include <physfs.h>
+
+class CInputStreamBuffer : public std::streambuf
+{
+public:
+ CInputStreamBuffer(size_t buffer_size = 512);
+ virtual ~CInputStreamBuffer();
+
+ void open(const std::string &filename);
+ void close();
+ bool is_open();
+ size_t size();
+
+private:
+ int_type underflow();
+
+ std::streampos seekpos(std::streampos sp, std::ios_base::openmode which);
+ std::streampos seekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which);
+
+ // copy ctor and assignment not implemented;
+ // copying not allowed
+ CInputStreamBuffer(const CInputStreamBuffer &);
+ CInputStreamBuffer &operator= (const CInputStreamBuffer &);
+
+ PHYSFS_File *m_file;
+ char *m_buffer;
+ size_t m_buffer_size;
+};
diff --git a/src/common/resources/outputstream.cpp b/src/common/resources/outputstream.cpp
new file mode 100644
index 0000000..e88520e
--- /dev/null
+++ b/src/common/resources/outputstream.cpp
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#include "common/resources/outputstream.h"
+#include "common/resources/outputstreambuffer.h"
+
+
+COutputStream::COutputStream() : std::ostream(new COutputStreamBuffer())
+{
+}
+
+COutputStream::COutputStream(const std::string& filename) : std::ostream(new COutputStreamBuffer())
+{
+ open(filename);
+}
+
+
+COutputStream::~COutputStream()
+{
+ delete rdbuf();
+}
+
+
+void COutputStream::open(const std::string& filename)
+{
+ static_cast<COutputStreamBuffer *>(rdbuf())->open(filename);
+}
+
+
+void COutputStream::close()
+{
+ static_cast<COutputStreamBuffer *>(rdbuf())->close();
+}
+
+
+bool COutputStream::is_open()
+{
+ return static_cast<COutputStreamBuffer *>(rdbuf())->is_open();
+}
diff --git a/src/common/resources/outputstream.h b/src/common/resources/outputstream.h
new file mode 100644
index 0000000..30b9429
--- /dev/null
+++ b/src/common/resources/outputstream.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#pragma once
+
+#include <ostream>
+#include <string>
+
+
+class COutputStream : public std::ostream
+{
+public:
+ COutputStream();
+ COutputStream(const std::string& filename);
+ virtual ~COutputStream();
+
+ void open(const std::string& filename);
+ void close();
+ bool is_open();
+};
diff --git a/src/common/resources/outputstreambuffer.cpp b/src/common/resources/outputstreambuffer.cpp
new file mode 100644
index 0000000..157e17d
--- /dev/null
+++ b/src/common/resources/outputstreambuffer.cpp
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#include "common/resources/outputstreambuffer.h"
+
+#include "common/resources/resourcemanager.h"
+
+#include <stdexcept>
+#include <sstream>
+
+COutputStreamBuffer::COutputStreamBuffer(size_t buffer_size) : m_buffer_size(buffer_size)
+{
+ m_file = nullptr;
+ m_buffer = new char[buffer_size];
+ setp(m_buffer, m_buffer + buffer_size);
+}
+
+
+COutputStreamBuffer::~COutputStreamBuffer()
+{
+ close();
+ delete m_buffer;
+}
+
+
+void COutputStreamBuffer::open(const std::string &filename)
+{
+ if (PHYSFS_isInit())
+ m_file = PHYSFS_openWrite(CResourceManager::CleanPath(filename).c_str());
+}
+
+
+void COutputStreamBuffer::close()
+{
+ sync();
+ if (is_open())
+ PHYSFS_close(m_file);
+}
+
+
+bool COutputStreamBuffer::is_open()
+{
+ return m_file;
+}
+
+
+std::streambuf::int_type COutputStreamBuffer::overflow(std::streambuf::int_type ch)
+{
+ /* This function should be called when pptr() == epptr(). We use it also in sync()
+ so we also have to write data if buffer is not full. */
+
+ if (pbase() == pptr()) // no data to write, sync() called with empty buffer
+ return 0;
+
+ // save buffer
+ PHYSFS_sint64 bytes_written = PHYSFS_write(m_file, pbase(), 1, pptr() - pbase());
+ if (bytes_written <= 0)
+ return traits_type::eof();
+
+ pbump(-bytes_written);
+ // write final char
+ if (ch != traits_type::eof()) {
+ bytes_written = PHYSFS_write(m_file, &ch, 1, 1);
+ if (bytes_written <= 0)
+ return traits_type::eof();
+ }
+
+ return ch;
+}
+
+
+int COutputStreamBuffer::sync()
+{
+ return overflow(traits_type::eof());
+}
diff --git a/src/common/resources/outputstreambuffer.h b/src/common/resources/outputstreambuffer.h
new file mode 100644
index 0000000..758c4df
--- /dev/null
+++ b/src/common/resources/outputstreambuffer.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#pragma once
+
+#include <streambuf>
+#include <string>
+#include <physfs.h>
+
+class COutputStreamBuffer : public std::streambuf
+{
+public:
+ COutputStreamBuffer(size_t buffer_size = 512);
+ virtual ~COutputStreamBuffer();
+ void open(const std::string &filename);
+ void close();
+ bool is_open();
+
+private:
+ int_type overflow(int_type ch);
+ int sync();
+
+ // copy ctor and assignment not implemented;
+ // copying not allowed
+ COutputStreamBuffer(const COutputStreamBuffer &);
+ COutputStreamBuffer &operator= (const COutputStreamBuffer &);
+ PHYSFS_File *m_file;
+ char *m_buffer;
+ size_t m_buffer_size;
+};
diff --git a/src/common/resources/resourcemanager.cpp b/src/common/resources/resourcemanager.cpp
new file mode 100644
index 0000000..475d71e
--- /dev/null
+++ b/src/common/resources/resourcemanager.cpp
@@ -0,0 +1,295 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+
+#include "common/resources/resourcemanager.h"
+
+#include "common/config.h"
+#include "common/logger.h"
+
+#include <physfs.h>
+
+#include <boost/filesystem.hpp>
+#include <boost/regex.hpp>
+
+namespace fs = boost::filesystem;
+
+namespace
+{
+ const Uint32 PHYSFS_RWOPS_TYPE = 0xc010b04f;
+}
+
+
+CResourceManager::CResourceManager(const char *argv0)
+{
+ if (!PHYSFS_init(argv0))
+ {
+ CLogger::GetInstancePointer()->Error("Error while initializing physfs\n");
+ }
+}
+
+
+CResourceManager::~CResourceManager()
+{
+ if (PHYSFS_isInit())
+ {
+ if (!PHYSFS_deinit())
+ {
+ CLogger::GetInstancePointer()->Error("Error while deinitializing physfs\n");
+ }
+ }
+}
+
+std::string CResourceManager::CleanPath(const std::string& path)
+{
+ return boost::regex_replace(path, boost::regex("(.*)/\\.\\./"), "");
+}
+
+
+bool CResourceManager::AddLocation(const std::string &location, bool prepend)
+{
+ if (PHYSFS_isInit())
+ {
+ if (!PHYSFS_mount(location.c_str(), nullptr, prepend ? 0 : 1))
+ {
+ CLogger::GetInstancePointer()->Error("Error while mounting \"%s\"\n", location.c_str());
+ }
+ }
+
+ return false;
+}
+
+
+bool CResourceManager::RemoveLocation(const std::string &location)
+{
+ if (PHYSFS_isInit())
+ {
+ if (!PHYSFS_removeFromSearchPath(location.c_str()))
+ {
+ CLogger::GetInstancePointer()->Error("Error while unmounting \"%s\"\n", location.c_str());
+ }
+ }
+
+ return false;
+}
+
+
+bool CResourceManager::SetSaveLocation(const std::string &location)
+{
+ if (PHYSFS_isInit())
+ {
+ if (!PHYSFS_setWriteDir(location.c_str()))
+ {
+ CLogger::GetInstancePointer()->Error("Error while setting save location to \"%s\"\n", location.c_str());
+ }
+ }
+
+ return false;
+}
+
+std::string CResourceManager::GetSaveLocation()
+{
+ if(PHYSFS_isInit()) {
+ return PHYSFS_getWriteDir();
+ }
+ return "";
+}
+
+
+SDL_RWops* CResourceManager::GetSDLFileHandler(const std::string &filename)
+{
+ SDL_RWops *handler = SDL_AllocRW();
+ if (!handler)
+ {
+ CLogger::GetInstancePointer()->Error("Unable to allocate SDL_RWops for \"%s\"\n", filename.c_str());
+ return nullptr;
+ }
+
+ if (!PHYSFS_isInit())
+ {
+ SDL_FreeRW(handler);
+ return nullptr;
+ }
+
+ PHYSFS_File *file = PHYSFS_openRead(CleanPath(filename).c_str());
+ if (!file)
+ {
+ SDL_FreeRW(handler);
+ return nullptr;
+ }
+
+ handler->seek = SDLSeek;
+ handler->read = SDLRead;
+ handler->write = SDLWrite;
+ handler->close = SDLClose;
+ handler->type = PHYSFS_RWOPS_TYPE;
+ handler->hidden.unknown.data1 = file;
+
+ return handler;
+}
+
+
+CSNDFile* CResourceManager::GetSNDFileHandler(const std::string &filename)
+{
+ return new CSNDFile(CleanPath(filename));
+}
+
+
+bool CResourceManager::Exists(const std::string &filename)
+{
+ return PHYSFS_exists(CleanPath(filename).c_str());
+}
+
+bool CResourceManager::DirectoryExists(const std::string& directory)
+{
+ return PHYSFS_exists(CleanPath(directory).c_str()) && PHYSFS_isDirectory(CleanPath(directory).c_str());
+}
+
+bool CResourceManager::CreateDirectory(const std::string& directory)
+{
+ return PHYSFS_mkdir(CleanPath(directory).c_str());
+}
+
+//TODO: Don't use boost filesystem here
+bool CResourceManager::RemoveDirectory(const std::string& directory)
+{
+ bool success = true;
+ std::string writeDir = PHYSFS_getWriteDir();
+ try
+ {
+ fs::remove_all(writeDir + "/" + CleanPath(directory));
+ }
+ catch (std::exception & e)
+ {
+ success = false;
+ }
+ return success;
+}
+
+std::vector<std::string> CResourceManager::ListFiles(const std::string &directory)
+{
+ std::vector<std::string> result;
+
+ char **files = PHYSFS_enumerateFiles(CleanPath(directory).c_str());
+
+ for (char **i = files; *i != nullptr; i++)
+ {
+ result.push_back(*i);
+ }
+
+ PHYSFS_freeList(files);
+
+ return result;
+}
+
+std::vector<std::string> CResourceManager::ListDirectories(const std::string &directory)
+{
+ std::vector<std::string> result;
+
+ char **files = PHYSFS_enumerateFiles(CleanPath(directory).c_str());
+
+ for (char **i = files; *i != nullptr; i++)
+ {
+ std::string path = CleanPath(directory) + "/" + (*i);
+ if (PHYSFS_isDirectory(path.c_str()))
+ {
+ result.push_back(*i);
+ }
+ }
+
+ PHYSFS_freeList(files);
+
+ return result;
+}
+
+
+int CResourceManager::SDLClose(SDL_RWops *context)
+{
+ if (CheckSDLContext(context))
+ {
+ PHYSFS_close(static_cast<PHYSFS_File *>(context->hidden.unknown.data1));
+ SDL_FreeRW(context);
+
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int CResourceManager::SDLRead(SDL_RWops *context, void *ptr, int size, int maxnum)
+{
+ if (CheckSDLContext(context))
+ {
+ PHYSFS_File *file = static_cast<PHYSFS_File *>(context->hidden.unknown.data1);
+ SDL_memset(ptr, 0, size * maxnum);
+
+ return PHYSFS_read(file, ptr, size, maxnum);
+ }
+
+ return 0;
+}
+
+
+int CResourceManager::SDLWrite(SDL_RWops *context, const void *ptr, int size, int num)
+{
+ return 0;
+}
+
+
+int CResourceManager::SDLSeek(SDL_RWops *context, int offset, int whence)
+{
+ if (CheckSDLContext(context))
+ {
+ PHYSFS_File *file = static_cast<PHYSFS_File *>(context->hidden.unknown.data1);
+ int position, result;
+
+ switch (whence)
+ {
+ default:
+ case RW_SEEK_SET:
+ result = PHYSFS_seek(file, offset);
+ return result > 0 ? offset : -1;
+
+ case RW_SEEK_CUR:
+ position = offset + PHYSFS_tell(file);
+ result = PHYSFS_seek(file, position);
+ return result > 0 ? position : -1;
+
+ case RW_SEEK_END:
+ position = PHYSFS_fileLength(file) - offset;
+ result = PHYSFS_seek(file, position);
+ return result > 0 ? position : -1;
+ }
+ }
+
+ return -1;
+}
+
+
+bool CResourceManager::CheckSDLContext(SDL_RWops *context)
+{
+ if (context->type != PHYSFS_RWOPS_TYPE)
+ {
+ SDL_SetError("Wrong kind of RWops");
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/common/resources/resourcemanager.h b/src/common/resources/resourcemanager.h
new file mode 100644
index 0000000..4d79e9b
--- /dev/null
+++ b/src/common/resources/resourcemanager.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#pragma once
+
+#include <vector>
+#include <string>
+#include <SDL.h>
+
+#include "common/resources/sndfile.h"
+
+class CResourceManager
+{
+public:
+ CResourceManager(const char *argv0);
+ ~CResourceManager();
+
+ static std::string CleanPath(const std::string &path);
+
+ static bool AddLocation(const std::string &location, bool prepend = true);
+ static bool RemoveLocation(const std::string &location);
+
+ static bool SetSaveLocation(const std::string &location);
+ static std::string GetSaveLocation();
+
+ static SDL_RWops* GetSDLFileHandler(const std::string &filename);
+ static CSNDFile* GetSNDFileHandler(const std::string &filename);
+
+ //! Check if file exists
+ static bool Exists(const std::string &filename);
+ //! Check if file exists and is a directory
+ static bool DirectoryExists(const std::string& directory);
+
+ //! Create directory in write directory
+ static bool CreateDirectory(const std::string& directory);
+ //! Remove directory in write directory, recursively
+ static bool RemoveDirectory(const std::string& directory);
+
+ //! List files contained in directory
+ static std::vector<std::string> ListFiles(const std::string &directory);
+ //! List directories contained in directory
+ static std::vector<std::string> ListDirectories(const std::string &directory);
+
+private:
+ static int SDLSeek(SDL_RWops *context, int offset, int whence);
+ static int SDLRead(SDL_RWops *context, void *ptr, int size, int maxnum);
+ static int SDLWrite(SDL_RWops *context, const void *ptr, int size, int num);
+ static int SDLClose(SDL_RWops *context);
+ static bool CheckSDLContext(SDL_RWops *context);
+};
diff --git a/src/common/resources/sndfile.cpp b/src/common/resources/sndfile.cpp
new file mode 100644
index 0000000..d2330e1
--- /dev/null
+++ b/src/common/resources/sndfile.cpp
@@ -0,0 +1,133 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#include "common/resources/sndfile.h"
+
+#include <cstring>
+
+
+CSNDFile::CSNDFile(const std::string& filename)
+ : m_file_info{}
+ , m_snd_file{nullptr}
+ , m_file{nullptr}
+ , m_last_error{}
+ , m_snd_callbacks{SNDLength, SNDSeek, SNDRead, SNDWrite, SNDTell}
+{
+ if (PHYSFS_isInit())
+ {
+ m_file = PHYSFS_openRead(filename.c_str());
+ }
+ else
+ {
+ m_last_error = "Resource system not started!";
+ }
+ if (m_file)
+ {
+ m_snd_file = sf_open_virtual(&m_snd_callbacks, SFM_READ, &m_file_info, m_file);
+ if (!m_snd_file)
+ {
+ m_last_error = "Could not load file";
+ }
+ }
+ else
+ {
+ m_last_error = std::string(PHYSFS_getLastError());
+ }
+}
+
+
+CSNDFile::~CSNDFile()
+{
+ if (m_file)
+ {
+ PHYSFS_close(m_file);
+ if (m_snd_file)
+ {
+ sf_close(m_snd_file);
+ }
+ }
+}
+
+
+bool CSNDFile::IsOpen()
+{
+ return m_file && m_snd_file;
+}
+
+
+SF_INFO &CSNDFile::GetFileInfo()
+{
+ return m_file_info;
+}
+
+
+std::string& CSNDFile::GetLastError()
+{
+ return m_last_error;
+}
+
+
+sf_count_t CSNDFile::Read(short int *ptr, sf_count_t items)
+{
+ return sf_read_short(m_snd_file, ptr, items);
+}
+
+
+sf_count_t CSNDFile::SNDLength(void *data)
+{
+ return PHYSFS_fileLength(static_cast<PHYSFS_File *>(data));
+}
+
+
+sf_count_t CSNDFile::SNDRead(void *ptr, sf_count_t count, void *data)
+{
+ return PHYSFS_read(static_cast<PHYSFS_File *>(data), ptr, 1, count);
+}
+
+
+sf_count_t CSNDFile::SNDSeek(sf_count_t offset, int whence, void *data)
+{
+ PHYSFS_File *file = static_cast<PHYSFS_File *>(data);
+ switch(whence)
+ {
+ case SEEK_CUR:
+ PHYSFS_seek(file, PHYSFS_tell(file) + offset);
+ break;
+ case SEEK_SET:
+ PHYSFS_seek(file, offset);
+ break;
+ case SEEK_END:
+ PHYSFS_seek(file, PHYSFS_fileLength(file) + offset);
+ break;
+ }
+
+ return PHYSFS_tell(file);
+}
+
+
+sf_count_t CSNDFile::SNDTell(void *data)
+{
+ return PHYSFS_tell(static_cast<PHYSFS_File *>(data));
+}
+
+
+sf_count_t CSNDFile::SNDWrite(const void *ptr, sf_count_t count, void *data)
+{
+ return PHYSFS_write(static_cast<PHYSFS_File *>(data), ptr, 1, count);
+}
diff --git a/src/common/resources/sndfile.h b/src/common/resources/sndfile.h
new file mode 100644
index 0000000..f083666
--- /dev/null
+++ b/src/common/resources/sndfile.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the Colobot: Gold Edition source code
+ * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
+ * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://gnu.org/licenses
+ */
+
+#pragma once
+
+#include <string>
+#include <physfs.h>
+#include <sndfile.h>
+
+
+class CSNDFile
+{
+public:
+ CSNDFile(const std::string &filename);
+ virtual ~CSNDFile();
+
+ SF_INFO &GetFileInfo();
+ bool IsOpen();
+ std::string &GetLastError();
+ sf_count_t Read(short int *ptr, sf_count_t items);
+
+private:
+ static sf_count_t SNDLength(void *data);
+ static sf_count_t SNDSeek(sf_count_t offset, int whence, void *data);
+ static sf_count_t SNDRead(void *ptr, sf_count_t count, void *data);
+ static sf_count_t SNDWrite(const void *ptr, sf_count_t count, void *data);
+ static sf_count_t SNDTell(void *data);
+ SF_INFO m_file_info;
+ SNDFILE *m_snd_file;
+ PHYSFS_File *m_file;
+ std::string m_last_error;
+ SF_VIRTUAL_IO m_snd_callbacks;
+};