summaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
authorKrzysztof Dermont <erihel@gmail.com>2014-06-20 23:41:38 +0200
committerKrzysztof Dermont <erihel@gmail.com>2014-06-20 23:51:28 +0200
commit2260f6bf4feb62929e32a1bea9cd3f403aa034b1 (patch)
treea9f830fe8ddfa57598a0802ced6540befb8c8c75 /src/common
parentba62e6f8be5f7008939677ce70799ecc26adf420 (diff)
downloadcolobot-2260f6bf4feb62929e32a1bea9cd3f403aa034b1.tar.gz
colobot-2260f6bf4feb62929e32a1bea9cd3f403aa034b1.tar.bz2
colobot-2260f6bf4feb62929e32a1bea9cd3f403aa034b1.zip
Big part of PhysFS support
* removed -mod argument * removed -datadir argument * removed -lang argument * removed some dead ui code * added resource manager and file loaders (stream and SDL) * changed interface textures location to match new directory structure * removed CGameData for mod support * added PhysFS support
Diffstat (limited to 'src/common')
-rw-r--r--src/common/image.cpp3
-rw-r--r--src/common/resources/inputstream.cpp53
-rw-r--r--src/common/resources/inputstream.h33
-rw-r--r--src/common/resources/resourcemanager.cpp200
-rw-r--r--src/common/resources/resourcemanager.h40
-rw-r--r--src/common/resources/resourcestreambuffer.cpp121
-rw-r--r--src/common/resources/resourcestreambuffer.h47
7 files changed, 496 insertions, 1 deletions
diff --git a/src/common/image.cpp b/src/common/image.cpp
index 8a876e3..aec3d4e 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,7 @@ bool CImage::Load(const std::string& fileName)
m_error = "";
- m_data->surface = IMG_Load(fileName.c_str());
+ m_data->surface = IMG_Load_RW(CResourceManager::GetSDLFileHandler(fileName.c_str()), 1);
if (m_data->surface == nullptr)
{
delete m_data;
diff --git a/src/common/resources/inputstream.cpp b/src/common/resources/inputstream.cpp
new file mode 100644
index 0000000..e121971
--- /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/resourcestreambuffer.h"
+
+
+CInputStream::CInputStream() : std::istream(new CResourceStreamBuffer())
+{
+}
+
+
+CInputStream::~CInputStream()
+{
+ delete rdbuf();
+}
+
+
+void CInputStream::open(const std::string& filename)
+{
+ static_cast<CResourceStreamBuffer *>(rdbuf())->open(filename);
+}
+
+
+void CInputStream::close()
+{
+ static_cast<CResourceStreamBuffer *>(rdbuf())->close();
+}
+
+
+bool CInputStream::is_open()
+{
+ return static_cast<CResourceStreamBuffer *>(rdbuf())->is_open();
+}
+
+
+size_t CInputStream::size()
+{
+ return static_cast<CResourceStreamBuffer *>(rdbuf())->size();
+}
diff --git a/src/common/resources/inputstream.h b/src/common/resources/inputstream.h
new file mode 100644
index 0000000..9d1c578
--- /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/resourcemanager.cpp b/src/common/resources/resourcemanager.cpp
new file mode 100644
index 0000000..ccef2a3
--- /dev/null
+++ b/src/common/resources/resourcemanager.cpp
@@ -0,0 +1,200 @@
+// * 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 <physfs.h>
+
+
+CResourceManager::CResourceManager(const char *argv0)
+{
+ if (PHYSFS_init(argv0))
+ {
+ // TODO error
+ }
+}
+
+
+CResourceManager::~CResourceManager()
+{
+ if (PHYSFS_isInit())
+ {
+ if (PHYSFS_deinit())
+ {
+ // TODO error
+ }
+ }
+}
+
+
+bool CResourceManager::AddLocation(const std::string &location, bool prepend)
+{
+ if (PHYSFS_isInit())
+ {
+ if (PHYSFS_mount(location.c_str(), nullptr, prepend ? 0 : 1))
+ {
+ // TODO error
+ }
+ }
+
+ return false;
+}
+
+
+bool CResourceManager::RemoveLocation(const std::string &location)
+{
+ if (PHYSFS_isInit())
+ {
+ if (PHYSFS_removeFromSearchPath(location.c_str()))
+ {
+ // TODO error
+ }
+ }
+
+ return false;
+}
+
+
+bool CResourceManager::SetSaveLocation(const std::string &location)
+{
+ if (PHYSFS_isInit())
+ {
+ if (PHYSFS_setWriteDir(location.c_str()))
+ {
+ // TODO error
+ }
+ }
+
+ return false;
+}
+
+
+std::string CResourceManager::GetLanguageLocation()
+{
+ return COLOBOT_I18N_DIR;
+}
+
+
+SDL_RWops* CResourceManager::GetSDLFileHandler(const std::string &filename)
+{
+ SDL_RWops *handler = SDL_AllocRW();
+ if (!handler)
+ {
+ // TODO error
+ 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 = 0xc010b04f;
+ handler->hidden.unknown.data1 = file;
+
+ return handler;
+}
+
+
+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 != 0xc010b04f)
+ {
+ 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..ba11d73
--- /dev/null
+++ b/src/common/resources/resourcemanager.h
@@ -0,0 +1,40 @@
+// * 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 <SDL.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 std::string GetLanguageLocation();
+ static SDL_RWops* GetSDLFileHandler(const std::string &filename);
+
+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/resourcestreambuffer.cpp b/src/common/resources/resourcestreambuffer.cpp
new file mode 100644
index 0000000..e7be51d
--- /dev/null
+++ b/src/common/resources/resourcestreambuffer.cpp
@@ -0,0 +1,121 @@
+// * 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/resourcestreambuffer.h"
+
+#include <stdexcept>
+#include <sstream>
+
+CResourceStreamBuffer::CResourceStreamBuffer(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];
+}
+
+
+CResourceStreamBuffer::~CResourceStreamBuffer()
+{
+ close();
+ delete m_buffer;
+}
+
+
+void CResourceStreamBuffer::open(const std::string &filename)
+{
+ if (PHYSFS_isInit())
+ {
+ m_file = PHYSFS_openRead(filename.c_str());
+ }
+}
+
+
+void CResourceStreamBuffer::close()
+{
+ if (is_open())
+ {
+ PHYSFS_close(m_file);
+ }
+}
+
+
+bool CResourceStreamBuffer::is_open()
+{
+ return m_file;
+}
+
+
+size_t CResourceStreamBuffer::size()
+{
+ return PHYSFS_fileLength(m_file);
+}
+
+
+std::streambuf::int_type CResourceStreamBuffer::underflow()
+{
+ 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 CResourceStreamBuffer::seekpos(std::streampos sp, std::ios_base::openmode which)
+{
+ return seekoff(off_type(sp), std::ios_base::beg, which);
+}
+
+
+std::streampos CResourceStreamBuffer::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 */
+
+ switch (way)
+ {
+ case std::ios_base::beg:
+ return pos_type(off_type(off));
+
+ case std::ios_base::cur:
+ // tell will give cursor at begining of block so we have to add where in block we currently are
+ return off + static_cast<off_type>(PHYSFS_tell(m_file)) - static_cast<off_type> (egptr() - gptr());
+
+ case std::ios_base::end:
+ return off + static_cast<off_type>(PHYSFS_fileLength(m_file));
+
+ default:
+ break;
+ }
+
+ return pos_type(off_type(-1));
+}
diff --git a/src/common/resources/resourcestreambuffer.h b/src/common/resources/resourcestreambuffer.h
new file mode 100644
index 0000000..a9ec0db
--- /dev/null
+++ b/src/common/resources/resourcestreambuffer.h
@@ -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/.
+
+#pragma once
+
+#include <streambuf>
+#include <string>
+#include <physfs.h>
+
+class CResourceStreamBuffer : public std::streambuf
+{
+public:
+ CResourceStreamBuffer(size_t buffer_size = 512);
+ virtual ~CResourceStreamBuffer();
+
+ 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
+ CResourceStreamBuffer(const CResourceStreamBuffer &);
+ CResourceStreamBuffer &operator= (const CResourceStreamBuffer &);
+
+ PHYSFS_File *m_file;
+ char *m_buffer;
+ size_t m_buffer_size;
+};