diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/image.cpp | 14 | ||||
-rw-r--r-- | src/common/profile.cpp | 27 | ||||
-rw-r--r-- | src/common/profile.h | 3 | ||||
-rw-r--r-- | src/common/resources/inputstream.cpp | 53 | ||||
-rw-r--r-- | src/common/resources/inputstream.h | 33 | ||||
-rw-r--r-- | src/common/resources/inputstreambuffer.cpp | 129 | ||||
-rw-r--r-- | src/common/resources/inputstreambuffer.h | 48 | ||||
-rw-r--r-- | src/common/resources/outputstream.cpp | 47 | ||||
-rw-r--r-- | src/common/resources/outputstream.h | 32 | ||||
-rw-r--r-- | src/common/resources/outputstreambuffer.cpp | 86 | ||||
-rw-r--r-- | src/common/resources/outputstreambuffer.h | 43 | ||||
-rw-r--r-- | src/common/resources/resourcemanager.cpp | 277 | ||||
-rw-r--r-- | src/common/resources/resourcemanager.h | 60 | ||||
-rw-r--r-- | src/common/resources/sndfile.cpp | 127 | ||||
-rw-r--r-- | src/common/resources/sndfile.h | 53 |
15 files changed, 1020 insertions, 12 deletions
diff --git a/src/common/image.cpp b/src/common/image.cpp index e3d1ef7..dd905a7 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -18,6 +18,7 @@ #include "common/image.h" #include "math/func.h" +#include "common/resources/resourcemanager.h" #include <stdlib.h> #include <stdio.h> @@ -381,7 +382,16 @@ bool CImage::Load(const std::string& fileName) m_error = ""; - m_data->surface = IMG_Load(fileName.c_str()); + SDL_RWops* pointer = CResourceManager::GetSDLFileHandler(fileName.c_str()); + if (pointer == nullptr) + { + delete m_data; + m_data = nullptr; + + m_error = "Unable to open file"; + return false; + } + m_data->surface = IMG_Load_RW(pointer, 1); if (m_data->surface == nullptr) { delete m_data; @@ -458,4 +468,4 @@ void CImage::flipVertically(){ SDL_FreeSurface(m_data->surface); m_data->surface = result; -}
\ No newline at end of file +} diff --git a/src/common/profile.cpp b/src/common/profile.cpp index 79d7152..5ecb804 100644 --- a/src/common/profile.cpp +++ b/src/common/profile.cpp @@ -17,6 +17,8 @@ #include "common/profile.h" +#include "common/resources/inputstream.h" +#include "common/resources/outputstream.h" #include "app/system.h" #include "common/logger.h" @@ -48,16 +50,19 @@ void CProfile::SetUseCurrentDirectory(bool useCurrentDirectory) m_useCurrentDirectory = useCurrentDirectory; } -std::string CProfile::GetIniFileLocation() -{ - return m_useCurrentDirectory ? "colobot.ini" : GetSystemUtils()->GetProfileFileLocation(); -} - bool CProfile::Init() { try { - bp::ini_parser::read_ini(GetIniFileLocation(), m_propertyTree); + CInputStream stream; + stream.open("colobot.ini"); + if(stream.is_open()) { + bp::ini_parser::read_ini(stream, m_propertyTree); + } else { + GetLogger()->Error("Error on parsing profile: failed to open file\n"); + return false; + } + stream.close(); } catch (std::exception & e) { @@ -73,7 +78,15 @@ bool CProfile::Save() { try { - bp::ini_parser::write_ini(GetIniFileLocation(), m_propertyTree); + COutputStream stream; + stream.open("colobot.ini"); + if(stream.is_open()) { + bp::ini_parser::write_ini(stream, m_propertyTree); + } else { + GetLogger()->Error("Error on storing profile: failed to open file\n"); + return false; + } + stream.close(); } catch (std::exception & e) { diff --git a/src/common/profile.h b/src/common/profile.h index ad0458e..ee17591 100644 --- a/src/common/profile.h +++ b/src/common/profile.h @@ -133,9 +133,6 @@ public: bool CopyFileToTemp(std::string filename); private: - std::string GetIniFileLocation(); - -private: boost::property_tree::ptree m_propertyTree; bool m_profileNeedSave; std::string m_userDirectory; diff --git a/src/common/resources/inputstream.cpp b/src/common/resources/inputstream.cpp new file mode 100644 index 0000000..b5ba63f --- /dev/null +++ b/src/common/resources/inputstream.cpp @@ -0,0 +1,53 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.gnu.org/licenses/. + +#include "common/resources/inputstream.h" +#include "common/resources/inputstreambuffer.h" + + +CInputStream::CInputStream() : std::istream(new CInputStreamBuffer()) +{ +} + + +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..9573f2c --- /dev/null +++ b/src/common/resources/inputstream.h @@ -0,0 +1,33 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.gnu.org/licenses/. + +#pragma once + +#include <istream> +#include <string> + + +class CInputStream : public std::istream +{ +public: + CInputStream(); + 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..cfa06fb --- /dev/null +++ b/src/common/resources/inputstreambuffer.cpp @@ -0,0 +1,129 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.gnu.org/licenses/. + +#include "common/resources/inputstreambuffer.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(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..384ebfb --- /dev/null +++ b/src/common/resources/inputstreambuffer.h @@ -0,0 +1,48 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.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..ba43ba6 --- /dev/null +++ b/src/common/resources/outputstream.cpp @@ -0,0 +1,47 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.gnu.org/licenses/. + +#include "common/resources/outputstream.h" +#include "common/resources/outputstreambuffer.h" + + +COutputStream::COutputStream() : std::ostream(new COutputStreamBuffer()) +{ +} + + +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..bedbbbd --- /dev/null +++ b/src/common/resources/outputstream.h @@ -0,0 +1,32 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.gnu.org/licenses/. + +#pragma once + +#include <ostream> +#include <string> + + +class COutputStream : public std::ostream +{ +public: + COutputStream(); + 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..38979db --- /dev/null +++ b/src/common/resources/outputstreambuffer.cpp @@ -0,0 +1,86 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.gnu.org/licenses/. + +#include "common/resources/outputstreambuffer.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(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..1318530 --- /dev/null +++ b/src/common/resources/outputstreambuffer.h @@ -0,0 +1,43 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.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..8e7f09f --- /dev/null +++ b/src/common/resources/resourcemanager.cpp @@ -0,0 +1,277 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.gnu.org/licenses/. + + +#include "common/resources/resourcemanager.h" + +#include "common/config.h" +#include "common/logger.h" + +#include <physfs.h> + +#include <boost/filesystem.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"); + } + } +} + + +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; +} + + +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(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(filename); +} + + +bool CResourceManager::Exists(const std::string &filename) +{ + return PHYSFS_exists(filename.c_str()); +} + +bool CResourceManager::DirectoryExists(const std::string& directory) +{ + return PHYSFS_exists(directory.c_str()) && PHYSFS_isDirectory(directory.c_str()); +} + +bool CResourceManager::CreateDirectory(const std::string& directory) +{ + return PHYSFS_mkdir(directory.c_str()); +} + +bool CResourceManager::RemoveDirectory(const std::string& directory) +{ + bool success = true; + std::string writeDir = PHYSFS_getWriteDir(); + try + { + fs::remove_all(writeDir + "/" + 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(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(directory.c_str()); + + for (char **i = files; *i != nullptr; i++) + { + std::string path = 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..7f99210 --- /dev/null +++ b/src/common/resources/resourcemanager.h @@ -0,0 +1,60 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.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 bool AddLocation(const std::string &location, bool prepend = true); + static bool RemoveLocation(const std::string &location); + + static bool SetSaveLocation(const std::string &location); + + 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..b71f06a --- /dev/null +++ b/src/common/resources/sndfile.cpp @@ -0,0 +1,127 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.gnu.org/licenses/. + +#include "common/resources/sndfile.h" + +#include <cstring> + + +CSNDFile::CSNDFile(const std::string& filename) +{ + memset(&m_file_info, 0, sizeof(SF_INFO)); + + 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(&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..5fc00f4 --- /dev/null +++ b/src/common/resources/sndfile.h @@ -0,0 +1,53 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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://www.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 snd_callbacks = { + SNDLength, + SNDSeek, + SNDRead, + SNDWrite, + SNDTell + }; +}; |