175 lines
4.4 KiB
C++
175 lines
4.4 KiB
C++
/*
|
|
* This file is part of the Colobot: Gold Edition source code
|
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
|
* http://epsitec.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/sdl_file_wrapper.h"
|
|
|
|
#include "common/logger.h"
|
|
|
|
#include <physfs.h>
|
|
|
|
|
|
CSDLFileWrapper::CSDLFileWrapper(const std::string& filename)
|
|
: m_rwops(nullptr)
|
|
{
|
|
if (!PHYSFS_isInit())
|
|
{
|
|
GetLogger()->Error("PHYSFS not initialized!\n");
|
|
return;
|
|
}
|
|
|
|
PHYSFS_File *file = PHYSFS_openRead(filename.c_str());
|
|
if (file == nullptr)
|
|
{
|
|
GetLogger()->Error("Error opening file with PHYSFS: \"%s\"\n", filename.c_str());
|
|
return;
|
|
}
|
|
|
|
m_rwops = SDL_AllocRW();
|
|
if (m_rwops == nullptr)
|
|
{
|
|
GetLogger()->Error("Unable to allocate SDL_RWops for \"%s\"\n", filename.c_str());
|
|
return;
|
|
}
|
|
|
|
m_rwops->type = SDL_RWOPS_UNKNOWN;
|
|
m_rwops->hidden.unknown.data1 = file;
|
|
m_rwops->seek = SDLSeek;
|
|
m_rwops->read = SDLRead;
|
|
m_rwops->write = SDLWrite;
|
|
m_rwops->size = SDLSize;
|
|
// This is safe because SDL_FreeRW will be called in destructor
|
|
m_rwops->close = SDLCloseWithoutFreeRW;
|
|
}
|
|
|
|
CSDLFileWrapper::~CSDLFileWrapper()
|
|
{
|
|
SDLCloseWithFreeRW(m_rwops);
|
|
}
|
|
|
|
SDL_RWops* CSDLFileWrapper::GetHandler()
|
|
{
|
|
return m_rwops;
|
|
}
|
|
|
|
bool CSDLFileWrapper::IsOpen() const
|
|
{
|
|
return m_rwops != nullptr;
|
|
}
|
|
|
|
int CSDLFileWrapper::SDLClose(SDL_RWops *context, bool freeRW)
|
|
{
|
|
if (context == nullptr)
|
|
return 0;
|
|
|
|
if (!CheckSDLContext(context))
|
|
return 1;
|
|
|
|
if (context->hidden.unknown.data1 != nullptr)
|
|
{
|
|
PHYSFS_close(static_cast<PHYSFS_File *>(context->hidden.unknown.data1));
|
|
context->hidden.unknown.data1 = nullptr;
|
|
}
|
|
|
|
if (freeRW)
|
|
SDL_FreeRW(context);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CSDLFileWrapper::SDLCloseWithoutFreeRW(SDL_RWops *context)
|
|
{
|
|
return SDLClose(context, false);
|
|
}
|
|
|
|
int CSDLFileWrapper::SDLCloseWithFreeRW(SDL_RWops *context)
|
|
{
|
|
return SDLClose(context, true);
|
|
}
|
|
|
|
bool CSDLFileWrapper::CheckSDLContext(SDL_RWops *context)
|
|
{
|
|
if (context->type != SDL_RWOPS_UNKNOWN)
|
|
{
|
|
SDL_SetError("Wrong kind of RWops");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Sint64 CSDLFileWrapper::SDLSeek(SDL_RWops *context, Sint64 offset, int whence)
|
|
{
|
|
if (CheckSDLContext(context))
|
|
{
|
|
PHYSFS_File *file = static_cast<PHYSFS_File *>(context->hidden.unknown.data1);
|
|
|
|
switch (whence)
|
|
{
|
|
default:
|
|
case RW_SEEK_SET:
|
|
{
|
|
auto result = PHYSFS_seek(file, offset);
|
|
return (result != 0) ? offset : -1;
|
|
}
|
|
|
|
case RW_SEEK_CUR:
|
|
{
|
|
int position = offset + PHYSFS_tell(file);
|
|
auto result = PHYSFS_seek(file, position);
|
|
return (result != 0) ? position : -1;
|
|
}
|
|
|
|
case RW_SEEK_END:
|
|
{
|
|
int position = PHYSFS_fileLength(file) - offset;
|
|
auto result = PHYSFS_seek(file, position);
|
|
return (result != 0) ? position : -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
Sint64 CSDLFileWrapper::SDLSize(SDL_RWops *context)
|
|
{
|
|
return -1; // Not needed for now
|
|
}
|
|
|
|
size_t CSDLFileWrapper::SDLRead(SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
|
|
{
|
|
if (CheckSDLContext(context))
|
|
{
|
|
PHYSFS_File *file = static_cast<PHYSFS_File *>(context->hidden.unknown.data1);
|
|
SDL_memset(ptr, 0, size * maxnum);
|
|
|
|
auto result = PHYSFS_read(file, ptr, size, maxnum);
|
|
return (result >= 0) ? result : 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
size_t CSDLFileWrapper::SDLWrite(SDL_RWops *context, const void *ptr, size_t size, size_t num)
|
|
{
|
|
assert(!!"Writing to CSDLFileWrapper is currently not supported");
|
|
return 0;
|
|
}
|