Skip to content

Commit

Permalink
Cheevos: Implement hrash VFS API
Browse files Browse the repository at this point in the history
  • Loading branch information
garbear authored and NikosSiak committed Jan 23, 2022
1 parent 88536bc commit d54d5a6
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ set(LIBRETRO_SOURCES src/client.cpp
src/audio/AudioStream.cpp
src/audio/SingleFrameAudio.cpp
src/cheevos/Cheevos.cpp
src/cheevos/CheevosEnvironment.cpp
src/cheevos/CheevosFrontendBridge.cpp
src/GameInfoLoader.cpp
src/input/ButtonMapper.cpp
src/input/ControllerLayout.cpp
Expand Down
36 changes: 36 additions & 0 deletions src/cheevos/CheevosEnvironment.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2020 Team Kodi (https://kodi.tv)
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSE.md for more information.
*/

#include "CheevosEnvironment.h"
#include "CheevosFrontendBridge.h"

#include <rcheevos/rhash.h>

using namespace LIBRETRO;

CCheevosEnvironment& CCheevosEnvironment::Get(void)
{
static CCheevosEnvironment _instance;
return _instance;
}

void CCheevosEnvironment::Initialize()
{
static rc_hash_filereader fileReader = {
CCheevosFrontendBridge::OpenFile,
CCheevosFrontendBridge::Seek,
CCheevosFrontendBridge::GetPosition,
CCheevosFrontendBridge::ReadFile,
CCheevosFrontendBridge::CloseFile,
};

rc_hash_init_custom_filereader(&fileReader);
}

void CCheevosEnvironment::Deinitialize()
{
}
24 changes: 24 additions & 0 deletions src/cheevos/CheevosEnvironment.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2020 Team Kodi (https://kodi.tv)
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSE.md for more information.
*/

#pragma once

namespace LIBRETRO
{
class CCheevosEnvironment
{
public:
static CCheevosEnvironment& Get(void);

void Initialize();

void Deinitialize();

private:
CCheevosEnvironment() = default;
};
} // namespace LIBRETRO
110 changes: 110 additions & 0 deletions src/cheevos/CheevosFrontendBridge.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (C) 2020 Team Kodi (https://kodi.tv)
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSE.md for more information.
*/

#include "CheevosFrontendBridge.h"

#include <kodi/Filesystem.h>
#include <stdio.h>

using namespace LIBRETRO;

void *CCheevosFrontendBridge::OpenFile(const char* path_utf8)
{
// Return NULL for error
if (path_utf8 == nullptr)
return nullptr;

// TODO: Handle UTF-8?
std::unique_ptr<FileHandle> fileHandle(new FileHandle{ path_utf8 });
fileHandle->file.reset(new kodi::vfs::CFile);

if (!fileHandle->file->OpenFile(fileHandle->path, 0))
return nullptr;

// Return the opaque file handle on success
return static_cast<void*>(fileHandle.release());
}

void CCheevosFrontendBridge::CloseFile(void* file_handle)
{
if (file_handle == nullptr)
return;

FileHandle *fileHandle = static_cast<FileHandle*>(file_handle);

fileHandle->file->Close();
delete fileHandle;
}

size_t CCheevosFrontendBridge::GetPosition(void* file_handle)
{
// Return 0 for error
if (file_handle == nullptr)
return 0;

FileHandle *fileHandle = static_cast<FileHandle*>(file_handle);

const int64_t currentPosition = fileHandle->file->GetPosition();

if (currentPosition < 0)
return 0;

// Return the current read / write position for the file
return currentPosition;
}

void CCheevosFrontendBridge::Seek(void* file_handle, size_t offset, int origin)
{
if (file_handle == nullptr)
return;

FileHandle *fileHandle = static_cast<FileHandle*>(file_handle);

int whence = -1;

switch (origin)
{
case 0:
whence = SEEK_SET;
break;
case 1:
whence = SEEK_CUR;
break;
case 2:
whence = SEEK_END;
break;
default:
break;
}

if (whence == -1)
return;

fileHandle->file->Seek(offset, whence);
}

size_t CCheevosFrontendBridge::ReadFile(void* file_handle, void* buffer, size_t requested_bytes)
{
// Return 0 for error
if (file_handle == nullptr)
return 0;

FileHandle *fileHandle = static_cast<FileHandle*>(file_handle);

const ssize_t bytesRead = fileHandle->file->Read(buffer, requested_bytes);

if (bytesRead < 0)
return 0;

// Return 0 if no bytes are available to read (end of file was reached) or
// undetectable error occurred
if (bytesRead == 0)
return 0;

// Return the number of bytes read
return static_cast<size_t>(bytesRead);
}
47 changes: 47 additions & 0 deletions src/cheevos/CheevosFrontendBridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2020 Team Kodi (https://kodi.tv)
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSE.md for more information.
*/

#pragma once

#include <memory>
#include <rcheevos/rhash.h>
#include <string>

namespace kodi
{
namespace vfs
{
class CFile;
}
}

namespace LIBRETRO
{
/*!
* Provide a bridge for frontend callbacks given to the rcheevos library.
*
* These functions are given to the rcheevos library in
* CheevosEnvironment::Initialize().
*/
class CCheevosFrontendBridge
{
public:
// Forward to Kodi VFS API
static void *OpenFile(const char* path_utf8);
static void CloseFile(void* file_handle);
static size_t GetPosition(void* file_handle);
static void Seek(void* file_handle, size_t offset, int origin);
static size_t ReadFile(void* file_handle, void* buffer, size_t requested_bytes);

private:
struct FileHandle
{
std::string path;
std::unique_ptr<kodi::vfs::CFile> file;
};
};
} // namespace LIBRETRO
3 changes: 3 additions & 0 deletions src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include "cheevos/Cheevos.h"
#include "cheevos/CheevosEnvironment.h"
#include "input/ButtonMapper.h"
#include "input/ControllerTopology.h"
#include "input/InputManager.h"
Expand Down Expand Up @@ -51,6 +52,7 @@ CGameLibRetro::~CGameLibRetro()
CControllerTopology::GetInstance().Clear();

CLibretroEnvironment::Get().Deinitialize();
CCheevosEnvironment::Get().Deinitialize();

CCheevos::Get().Deinitialize();

Expand Down Expand Up @@ -82,6 +84,7 @@ ADDON_STATUS CGameLibRetro::Create()

// Environment must be initialized before calling retro_init()
CLibretroEnvironment::Get().Initialize(this, &m_client, &m_clientBridge);
CCheevosEnvironment::Get().Initialize();

CButtonMapper::Get().LoadButtonMap();
CControllerTopology::GetInstance().LoadTopology();
Expand Down

0 comments on commit d54d5a6

Please sign in to comment.