mirror of
https://github.com/izzy2lost/WeeU.git
synced 2026-07-06 00:19:59 -07:00
Move wxGui files to gui & remove AndroidGui
This commit is contained in:
@@ -1,56 +0,0 @@
|
||||
#include "AndroidAudio.h"
|
||||
|
||||
#include "Cafe/OS/libs/snd_core/ax.h"
|
||||
#include "audio/IAudioAPI.h"
|
||||
|
||||
#if HAS_CUBEB
|
||||
#include "audio/CubebAPI.h"
|
||||
#endif // HAS_CUBEB
|
||||
|
||||
namespace AndroidAudio
|
||||
{
|
||||
|
||||
void createAudioDevice(IAudioAPI::AudioAPI audioApi, sint32 channels, sint32 volume, bool isTV)
|
||||
{
|
||||
static constexpr int AX_FRAMES_PER_GROUP = 4;
|
||||
std::unique_lock lock(g_audioMutex);
|
||||
auto& audioDevice = isTV ? g_tvAudio : g_padAudio;
|
||||
switch (channels)
|
||||
{
|
||||
case 0:
|
||||
channels = 1;
|
||||
break;
|
||||
case 2:
|
||||
channels = 6;
|
||||
break;
|
||||
default: // stereo
|
||||
channels = 2;
|
||||
break;
|
||||
}
|
||||
switch (audioApi)
|
||||
{
|
||||
#if HAS_CUBEB
|
||||
case IAudioAPI::AudioAPI::Cubeb:
|
||||
{
|
||||
audioDevice.reset();
|
||||
std::shared_ptr<CubebAPI::CubebDeviceDescription> deviceDescriptionPtr = std::make_shared<CubebAPI::CubebDeviceDescription>(nullptr, std::string(), std::wstring());
|
||||
audioDevice = IAudioAPI::CreateDevice(IAudioAPI::AudioAPI::Cubeb, deviceDescriptionPtr, 48000, channels, snd_core::AX_SAMPLES_PER_3MS_48KHZ * AX_FRAMES_PER_GROUP, 16);
|
||||
audioDevice->SetVolume(volume);
|
||||
break;
|
||||
}
|
||||
#endif // HAS_CUBEB
|
||||
default:
|
||||
cemuLog_log(LogType::Force, fmt::format("Invalid audio api: {}", audioApi));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setAudioVolume(sint32 volume, bool isTV)
|
||||
{
|
||||
std::shared_lock lock(g_audioMutex);
|
||||
auto& audioDevice = isTV ? g_tvAudio : g_padAudio;
|
||||
if (audioDevice)
|
||||
audioDevice->SetVolume(volume);
|
||||
}
|
||||
|
||||
}; // namespace AndroidAudio
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "audio/IAudioAPI.h"
|
||||
|
||||
namespace AndroidAudio
|
||||
{
|
||||
void createAudioDevice(IAudioAPI::AudioAPI audioApi, sint32 channels, sint32 volume, bool isTV = true);
|
||||
void setAudioVolume(sint32 volume, bool isTV = true);
|
||||
}; // namespace AndroidAudio
|
||||
@@ -1,3 +0,0 @@
|
||||
#include "AndroidEmulatedController.h"
|
||||
|
||||
std::array<std::unique_ptr<AndroidEmulatedController>, InputManager::kMaxController> AndroidEmulatedController::s_emulatedControllers;
|
||||
@@ -1,112 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "input/InputManager.h"
|
||||
#include "input/api/Controller.h"
|
||||
#include "input/emulated/ClassicController.h"
|
||||
#include "input/emulated/ProController.h"
|
||||
#include "input/emulated/WiimoteController.h"
|
||||
|
||||
class AndroidEmulatedController
|
||||
{
|
||||
private:
|
||||
size_t m_index;
|
||||
static std::array<std::unique_ptr<AndroidEmulatedController>, InputManager::kMaxController> s_emulatedControllers;
|
||||
EmulatedControllerPtr m_emulatedController;
|
||||
AndroidEmulatedController(size_t index) : m_index(index)
|
||||
{
|
||||
m_emulatedController = InputManager::instance().get_controller(m_index);
|
||||
}
|
||||
|
||||
public:
|
||||
static AndroidEmulatedController &getAndroidEmulatedController(size_t index)
|
||||
{
|
||||
auto &controller = s_emulatedControllers.at(index);
|
||||
if (!controller)
|
||||
controller = std::unique_ptr<AndroidEmulatedController>(new AndroidEmulatedController(index));
|
||||
return *controller;
|
||||
}
|
||||
void setType(EmulatedController::Type type)
|
||||
{
|
||||
if (m_emulatedController && m_emulatedController->type() == type)
|
||||
return;
|
||||
m_emulatedController = InputManager::instance().set_controller(m_index, type);
|
||||
InputManager::instance().save(m_index);
|
||||
}
|
||||
void setMapping(uint64 mappingId, ControllerPtr controller, uint64 buttonId)
|
||||
{
|
||||
if (m_emulatedController && controller)
|
||||
{
|
||||
const auto &controllers = m_emulatedController->get_controllers();
|
||||
auto controllerIt = std::find_if(controllers.begin(), controllers.end(), [&](const ControllerPtr &c)
|
||||
{ return c->api() == controller->api() && c->uuid() == controller->uuid(); });
|
||||
if (controllerIt == controllers.end())
|
||||
m_emulatedController->add_controller(controller);
|
||||
else
|
||||
controller = *controllerIt;
|
||||
m_emulatedController->set_mapping(mappingId, controller, buttonId);
|
||||
InputManager::instance().save(m_index);
|
||||
}
|
||||
}
|
||||
std::optional<std::string> getMapping(uint64 mapping) const
|
||||
{
|
||||
if (!m_emulatedController)
|
||||
return {};
|
||||
auto controller = m_emulatedController->get_mapping_controller(mapping);
|
||||
if (!controller)
|
||||
return {};
|
||||
auto mappingName = m_emulatedController->get_mapping_name(mapping);
|
||||
return fmt::format("{}: {}", controller->display_name(), mappingName);
|
||||
}
|
||||
std::map<uint64, std::string> getMappings() const
|
||||
{
|
||||
if (!m_emulatedController)
|
||||
return {};
|
||||
std::map<uint64, std::string> mappings;
|
||||
auto type = m_emulatedController->type();
|
||||
uint64 mapping = 0;
|
||||
uint64 maxMapping = 0;
|
||||
if (type == EmulatedController::Type::VPAD)
|
||||
{
|
||||
mapping = VPADController::ButtonId::kButtonId_A;
|
||||
maxMapping = VPADController::ButtonId::kButtonId_Max;
|
||||
}
|
||||
if (type == EmulatedController::Type::Pro)
|
||||
{
|
||||
mapping = ProController::ButtonId::kButtonId_A;
|
||||
maxMapping = ProController::ButtonId::kButtonId_Max;
|
||||
}
|
||||
if (type == EmulatedController::Type::Classic)
|
||||
{
|
||||
mapping = ClassicController::ButtonId::kButtonId_A;
|
||||
maxMapping = ClassicController::ButtonId::kButtonId_Max;
|
||||
}
|
||||
if (type == EmulatedController::Type::Wiimote)
|
||||
{
|
||||
mapping = WiimoteController::ButtonId::kButtonId_A;
|
||||
maxMapping = WiimoteController::ButtonId::kButtonId_Max;
|
||||
}
|
||||
for (; mapping < maxMapping; mapping++)
|
||||
{
|
||||
auto mappingName = getMapping(mapping);
|
||||
if (mappingName.has_value())
|
||||
mappings[mapping] = mappingName.value();
|
||||
}
|
||||
return mappings;
|
||||
}
|
||||
void setDisabled()
|
||||
{
|
||||
InputManager::instance().delete_controller(m_index, true);
|
||||
m_emulatedController.reset();
|
||||
}
|
||||
EmulatedControllerPtr getEmulatedController()
|
||||
{
|
||||
return m_emulatedController;
|
||||
}
|
||||
|
||||
void clearMapping(int mapping)
|
||||
{
|
||||
if (!m_emulatedController)
|
||||
return;
|
||||
m_emulatedController->delete_mapping(mapping);
|
||||
}
|
||||
};
|
||||
@@ -1,206 +0,0 @@
|
||||
#include <Cafe/TitleList/TitleInfo.h>
|
||||
#include <Cafe/TitleList/TitleList.h>
|
||||
#include <Cafe/CafeSystem.h>
|
||||
#include "AndroidGuiWrapper.h"
|
||||
#include "GameIconLoader.h"
|
||||
#include "GameTitleLoader.h"
|
||||
|
||||
bool g_inputConfigWindowHasFocus;
|
||||
WindowInfo g_window_info;
|
||||
|
||||
GameTitleLoader g_gameTitleLoader;
|
||||
GameIconLoader g_gameIconLoader;
|
||||
|
||||
void gui_setOnGameTitleLoaded(const std::shared_ptr<GameTitleLoadedCallback> &onGameTitleLoaded)
|
||||
{
|
||||
g_gameTitleLoader.setOnTitleLoaded(onGameTitleLoaded);
|
||||
}
|
||||
|
||||
const Image& gui_getGameIcon(TitleId titleId)
|
||||
{
|
||||
return g_gameIconLoader.getGameIcon(titleId);
|
||||
}
|
||||
|
||||
void gui_setOnGameIconLoaded(const std::shared_ptr<class GameIconLoadedCallback>& onGameIconLoaded)
|
||||
{
|
||||
g_gameIconLoader.setOnIconLoaded(onGameIconLoaded);
|
||||
}
|
||||
void gui_addGamePath(const fs::path& gamePath)
|
||||
{
|
||||
g_gameTitleLoader.addGamePath(gamePath);
|
||||
}
|
||||
void gui_requestGameIcon(TitleId titleId)
|
||||
{
|
||||
g_gameIconLoader.requestIcon(titleId);
|
||||
}
|
||||
void gui_reloadGameTitles()
|
||||
{
|
||||
g_gameTitleLoader.reloadGameTitles();
|
||||
}
|
||||
void gui_createCemuDirs()
|
||||
{
|
||||
|
||||
}
|
||||
void gui_loggingWindowLog(std::string_view filter, std::string_view message)
|
||||
{
|
||||
}
|
||||
void gui_loggingWindowLog(std::string_view message)
|
||||
{
|
||||
}
|
||||
|
||||
void gui_create()
|
||||
{
|
||||
}
|
||||
|
||||
WindowInfo& gui_getWindowInfo()
|
||||
{
|
||||
return g_window_info;
|
||||
}
|
||||
|
||||
void gui_updateWindowTitles(bool isIdle, bool isLoading, double fps)
|
||||
{
|
||||
}
|
||||
void gui_getWindowSize(int& w, int& h)
|
||||
{
|
||||
w = gui_getWindowInfo().width;
|
||||
h = gui_getWindowInfo().height;
|
||||
}
|
||||
void gui_getPadWindowSize(int& w, int& h)
|
||||
{
|
||||
w = gui_getWindowInfo().pad_width;
|
||||
h = gui_getWindowInfo().pad_height;
|
||||
}
|
||||
void gui_getWindowPhysSize(int& w, int& h)
|
||||
{
|
||||
gui_getWindowSize(w, h);
|
||||
}
|
||||
void gui_getPadWindowPhysSize(int& w, int& h)
|
||||
{
|
||||
gui_getPadWindowSize(w, h);
|
||||
}
|
||||
double gui_getWindowDPIScale()
|
||||
{
|
||||
return gui_getWindowInfo().dpi_scale;
|
||||
}
|
||||
double gui_getPadDPIScale()
|
||||
{
|
||||
return gui_getWindowInfo().pad_dpi_scale;
|
||||
}
|
||||
bool gui_isPadWindowOpen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool gui_isKeyDown(uint32 key)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool gui_isKeyDown(PlatformKeyCodes key)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void gui_notifyGameLoaded()
|
||||
{
|
||||
}
|
||||
void gui_notifyGameExited()
|
||||
{
|
||||
}
|
||||
|
||||
bool gui_isFullScreen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void gui_initHandleContextFromWxWidgetsWindow(WindowHandleInfo& handleInfoOut, class wxWindow* wxw)
|
||||
{
|
||||
}
|
||||
|
||||
void gui_requestGameListRefresh()
|
||||
{
|
||||
}
|
||||
|
||||
std::string gui_RawKeyCodeToString(uint32 keyCode)
|
||||
{
|
||||
}
|
||||
|
||||
bool gui_saveScreenshotToFile(const fs::path& imagePath, std::vector<uint8>& data, int width, int height)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool gui_saveScreenshotToClipboard(std::vector<uint8>& data, int width, int height)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Returns true if a screenshot request is queued
|
||||
* Once this function has returned true, it will reset back to
|
||||
* false until the next time a screenshot is requested
|
||||
*/
|
||||
bool gui_hasScreenshotRequest()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// debugger stuff
|
||||
void debuggerWindow_updateViewThreadsafe2()
|
||||
{
|
||||
}
|
||||
void debuggerWindow_notifyDebugBreakpointHit2()
|
||||
{
|
||||
}
|
||||
void debuggerWindow_notifyRun()
|
||||
{
|
||||
}
|
||||
void debuggerWindow_moveIP()
|
||||
{
|
||||
}
|
||||
void debuggerWindow_notifyModuleLoaded(void* module)
|
||||
{
|
||||
}
|
||||
void debuggerWindow_notifyModuleUnloaded(void* module)
|
||||
{
|
||||
}
|
||||
|
||||
void gui_startGame(TitleId titleId) {
|
||||
TitleInfo launchTitle;
|
||||
|
||||
if (!CafeTitleList::GetFirstByTitleId(titleId, launchTitle))
|
||||
return;
|
||||
|
||||
if (launchTitle.IsValid())
|
||||
{
|
||||
// the title might not be in the TitleList, so we add it as a temporary entry
|
||||
CafeTitleList::AddTitleFromPath(launchTitle.GetPath());
|
||||
// title is valid, launch from TitleId
|
||||
TitleId baseTitleId;
|
||||
if (!CafeTitleList::FindBaseTitleId(launchTitle.GetAppTitleId(), baseTitleId))
|
||||
{
|
||||
}
|
||||
CafeSystem::STATUS_CODE statusCode = CafeSystem::PrepareForegroundTitle(baseTitleId);
|
||||
if (statusCode == CafeSystem::STATUS_CODE::INVALID_RPX)
|
||||
{
|
||||
}
|
||||
else if (statusCode == CafeSystem::STATUS_CODE::UNABLE_TO_MOUNT)
|
||||
{
|
||||
}
|
||||
else if (statusCode != CafeSystem::STATUS_CODE::SUCCESS)
|
||||
{
|
||||
}
|
||||
}
|
||||
else // if (launchTitle.GetFormat() == TitleInfo::TitleDataFormat::INVALID_STRUCTURE )
|
||||
{
|
||||
// title is invalid, if its an RPX/ELF we can launch it directly
|
||||
// otherwise its an error
|
||||
CafeTitleFileType fileType = DetermineCafeSystemFileType(launchTitle.GetPath());
|
||||
if (fileType == CafeTitleFileType::RPX || fileType == CafeTitleFileType::ELF)
|
||||
{
|
||||
CafeSystem::STATUS_CODE statusCode = CafeSystem::PrepareForegroundTitleFromStandaloneRPX(
|
||||
launchTitle.GetPath());
|
||||
if (statusCode != CafeSystem::STATUS_CODE::SUCCESS)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CafeSystem::LaunchForegroundTitle();
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cafe/TitleList/TitleId.h"
|
||||
#include "gui/guiWrapper.h"
|
||||
#include "Image.h"
|
||||
|
||||
void gui_startGame(TitleId titleId);
|
||||
|
||||
|
||||
void gui_setOnGameTitleLoaded(const std::shared_ptr<class GameTitleLoadedCallback> &onGameTitleLoaded);
|
||||
|
||||
void gui_setOnGameIconLoaded(const std::shared_ptr<class GameIconLoadedCallback>& onGameIconLoaded);
|
||||
|
||||
const Image& gui_getGameIcon(TitleId titleId);
|
||||
|
||||
void gui_requestGameIcon(TitleId titleId);
|
||||
|
||||
void gui_reloadGameTitles();
|
||||
|
||||
void gui_createCemuDirs();
|
||||
|
||||
void gui_addGamePath(const fs::path& gamePath);
|
||||
@@ -1,37 +0,0 @@
|
||||
|
||||
add_library(CemuAndroidGui
|
||||
AndroidAudio.cpp
|
||||
AndroidAudio.h
|
||||
AndroidEmulatedController.h
|
||||
AndroidEmulatedController.cpp
|
||||
AndroidGuiWrapper.cpp
|
||||
AndroidGuiWrapper.h
|
||||
GameIconLoader.cpp
|
||||
GameIconLoader.h
|
||||
GameTitleLoader.cpp
|
||||
GameTitleLoader.h
|
||||
OpenGLCanvas.cpp
|
||||
Image.cpp
|
||||
Image.h
|
||||
Utils.cpp
|
||||
Utils.h
|
||||
)
|
||||
|
||||
target_include_directories(CemuAndroidGui PUBLIC "../")
|
||||
|
||||
target_link_libraries(CemuAndroidGui PRIVATE
|
||||
CemuAudio
|
||||
CemuCafe
|
||||
CemuCommon
|
||||
CemuComponents
|
||||
CemuConfig
|
||||
CemuInput
|
||||
CemuResource
|
||||
CemuUtil
|
||||
Boost::headers
|
||||
CURL::libcurl
|
||||
libzip::zip
|
||||
OpenSSL::Crypto
|
||||
pugixml::pugixml
|
||||
ZArchive::zarchive
|
||||
)
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "GameIconLoader.h"
|
||||
|
||||
#include "Cafe/TitleList/TitleInfo.h"
|
||||
#include "Cafe/TitleList/TitleList.h"
|
||||
|
||||
GameIconLoader::GameIconLoader() {
|
||||
m_loaderThread = std::thread(&GameIconLoader::loadGameIcons, this);
|
||||
}
|
||||
|
||||
GameIconLoader::~GameIconLoader() {
|
||||
m_continueLoading = false;
|
||||
m_condVar.notify_one();
|
||||
m_loaderThread.join();
|
||||
}
|
||||
|
||||
const Image &GameIconLoader::getGameIcon(TitleId titleId) {
|
||||
return m_iconCache.at(titleId);
|
||||
}
|
||||
|
||||
void GameIconLoader::requestIcon(TitleId titleId) {
|
||||
{
|
||||
std::lock_guard lock(m_threadMutex);
|
||||
m_iconsToLoad.emplace_front(titleId);
|
||||
}
|
||||
m_condVar.notify_one();
|
||||
}
|
||||
|
||||
void GameIconLoader::loadGameIcons() {
|
||||
while (m_continueLoading) {
|
||||
TitleId titleId = 0;
|
||||
{
|
||||
std::unique_lock lock(m_threadMutex);
|
||||
m_condVar.wait(lock, [this] {
|
||||
return !m_iconsToLoad.empty() || !m_continueLoading;
|
||||
});
|
||||
if (!m_continueLoading)
|
||||
return;
|
||||
titleId = m_iconsToLoad.front();
|
||||
m_iconsToLoad.pop_front();
|
||||
}
|
||||
TitleInfo titleInfo;
|
||||
if (!CafeTitleList::GetFirstByTitleId(titleId, titleInfo))
|
||||
continue;
|
||||
|
||||
if (auto iconIt = m_iconCache.find(titleId); iconIt != m_iconCache.end()) {
|
||||
if (m_onIconLoaded) m_onIconLoaded->onIconLoaded(titleId);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string tempMountPath = TitleInfo::GetUniqueTempMountingPath();
|
||||
if (!titleInfo.Mount(tempMountPath, "", FSC_PRIORITY_BASE))
|
||||
continue;
|
||||
auto tgaData = fsc_extractFile((tempMountPath + "/meta/iconTex.tga").c_str());
|
||||
if (tgaData && tgaData->size() > 16) {
|
||||
int width, height, channels;
|
||||
Image image(tgaData.value());
|
||||
if (image.isOk()) {
|
||||
m_iconCache.emplace(titleId, std::move(image));
|
||||
if (m_onIconLoaded) m_onIconLoaded->onIconLoaded(titleId);
|
||||
}
|
||||
} else {
|
||||
cemuLog_log(LogType::Force, "Failed to load icon for title {:016x}", titleId);
|
||||
}
|
||||
titleInfo.Unmount(tempMountPath);
|
||||
}
|
||||
}
|
||||
|
||||
void GameIconLoader::setOnIconLoaded(const std::shared_ptr<GameIconLoadedCallback> &onIconLoaded) {
|
||||
{
|
||||
std::lock_guard lock(m_threadMutex);
|
||||
m_onIconLoaded = onIconLoaded;
|
||||
}
|
||||
m_condVar.notify_one();
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cafe/TitleList/TitleId.h"
|
||||
#include "Image.h"
|
||||
|
||||
class GameIconLoadedCallback {
|
||||
public:
|
||||
virtual void onIconLoaded(TitleId titleId) = 0;
|
||||
};
|
||||
|
||||
class GameIconLoader {
|
||||
std::atomic_bool m_continueLoading = true;
|
||||
std::condition_variable m_condVar;
|
||||
std::thread m_loaderThread;
|
||||
std::mutex m_threadMutex;
|
||||
std::deque <TitleId> m_iconsToLoad;
|
||||
std::map <TitleId, Image> m_iconCache;
|
||||
std::shared_ptr <GameIconLoadedCallback> m_onIconLoaded = nullptr;
|
||||
public:
|
||||
GameIconLoader();
|
||||
|
||||
~GameIconLoader();
|
||||
|
||||
const Image &getGameIcon(TitleId titleId);
|
||||
|
||||
void setOnIconLoaded(const std::shared_ptr <GameIconLoadedCallback> &onIconLoaded);
|
||||
|
||||
void requestIcon(TitleId titleId);
|
||||
|
||||
private:
|
||||
void loadGameIcons();
|
||||
};
|
||||
@@ -1,122 +0,0 @@
|
||||
#include "GameTitleLoader.h"
|
||||
|
||||
GameTitleLoader::GameTitleLoader() {
|
||||
m_loaderThread = std::thread(&GameTitleLoader::loadGameTitles, this);
|
||||
}
|
||||
|
||||
void GameTitleLoader::queueTitle(TitleId titleId) {
|
||||
{
|
||||
std::lock_guard lock(m_threadMutex);
|
||||
m_titlesToLoad.emplace_front(titleId);
|
||||
}
|
||||
m_condVar.notify_one();
|
||||
}
|
||||
|
||||
|
||||
void GameTitleLoader::setOnTitleLoaded(
|
||||
const std::shared_ptr<GameTitleLoadedCallback> &gameTitleLoadedCallback) {
|
||||
{
|
||||
std::lock_guard lock(m_threadMutex);
|
||||
m_gameTitleLoadedCallback = gameTitleLoadedCallback;
|
||||
}
|
||||
m_condVar.notify_one();
|
||||
}
|
||||
|
||||
void GameTitleLoader::reloadGameTitles() {
|
||||
if (m_callbackIdTitleList.has_value()) {
|
||||
CafeTitleList::Refresh();
|
||||
CafeTitleList::UnregisterCallback(m_callbackIdTitleList.value());
|
||||
}
|
||||
m_gameInfos.clear();
|
||||
registerCallback();
|
||||
}
|
||||
|
||||
GameTitleLoader::~GameTitleLoader() {
|
||||
m_continueLoading = false;
|
||||
m_condVar.notify_one();
|
||||
m_loaderThread.join();
|
||||
if (m_callbackIdTitleList.has_value())
|
||||
CafeTitleList::UnregisterCallback(m_callbackIdTitleList.value());
|
||||
}
|
||||
|
||||
void GameTitleLoader::titleRefresh(TitleId titleId) {
|
||||
GameInfo2 gameInfo = CafeTitleList::GetGameInfo(titleId);
|
||||
if (!gameInfo.IsValid()) {
|
||||
return;
|
||||
}
|
||||
TitleId baseTitleId = gameInfo.GetBaseTitleId();
|
||||
bool isNewEntry = false;
|
||||
if (auto gameInfoIt = m_gameInfos.find(baseTitleId); gameInfoIt == m_gameInfos.end()) {
|
||||
isNewEntry = true;
|
||||
m_gameInfos[baseTitleId] = Game();
|
||||
}
|
||||
Game &game = m_gameInfos[baseTitleId];
|
||||
game.titleId = baseTitleId;
|
||||
game.name = GetNameByTitleId(baseTitleId);
|
||||
game.version = gameInfo.GetVersion();
|
||||
game.region = gameInfo.GetRegion();
|
||||
if (gameInfo.HasAOC()) {
|
||||
game.dlc = gameInfo.GetAOCVersion();
|
||||
}
|
||||
if (isNewEntry) {
|
||||
iosu::pdm::GameListStat playTimeStat{};
|
||||
if (iosu::pdm::GetStatForGamelist(baseTitleId, playTimeStat))
|
||||
game.secondsPlayed = playTimeStat.numMinutesPlayed * 60;
|
||||
if (m_gameTitleLoadedCallback) m_gameTitleLoadedCallback->onTitleLoaded(game);
|
||||
} else {
|
||||
// TODO: Update
|
||||
}
|
||||
}
|
||||
|
||||
void GameTitleLoader::loadGameTitles() {
|
||||
while (m_continueLoading) {
|
||||
TitleId titleId = 0;
|
||||
{
|
||||
std::unique_lock lock(m_threadMutex);
|
||||
m_condVar.wait(lock, [this] {
|
||||
return (!m_titlesToLoad.empty()) ||
|
||||
!m_continueLoading;
|
||||
});
|
||||
if (!m_continueLoading)
|
||||
return;
|
||||
titleId = m_titlesToLoad.front();
|
||||
m_titlesToLoad.pop_front();
|
||||
}
|
||||
titleRefresh(titleId);
|
||||
}
|
||||
}
|
||||
|
||||
std::string GameTitleLoader::GetNameByTitleId(uint64 titleId) {
|
||||
auto it = m_name_cache.find(titleId);
|
||||
if (it != m_name_cache.end())
|
||||
return it->second;
|
||||
TitleInfo titleInfo;
|
||||
if (!CafeTitleList::GetFirstByTitleId(titleId, titleInfo))
|
||||
return "Unknown title";
|
||||
std::string name;
|
||||
if (!GetConfig().GetGameListCustomName(titleId, name))
|
||||
name = titleInfo.GetTitleName();
|
||||
m_name_cache.emplace(titleId, name);
|
||||
return name;
|
||||
}
|
||||
|
||||
void GameTitleLoader::registerCallback() {
|
||||
m_callbackIdTitleList = CafeTitleList::RegisterCallback(
|
||||
[](CafeTitleListCallbackEvent *evt,
|
||||
void *ctx) {
|
||||
static_cast<GameTitleLoader *>(ctx)->HandleTitleListCallback(evt);
|
||||
}, this);
|
||||
}
|
||||
|
||||
void GameTitleLoader::HandleTitleListCallback(CafeTitleListCallbackEvent *evt) {
|
||||
if (evt->eventType == CafeTitleListCallbackEvent::TYPE::TITLE_DISCOVERED ||
|
||||
evt->eventType == CafeTitleListCallbackEvent::TYPE::TITLE_REMOVED) {
|
||||
queueTitle(evt->titleInfo->GetAppTitleId());
|
||||
}
|
||||
}
|
||||
|
||||
void GameTitleLoader::addGamePath(const fs::path &path) {
|
||||
CafeTitleList::ClearScanPaths();
|
||||
CafeTitleList::AddScanPath(path);
|
||||
CafeTitleList::Refresh();
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cafe/IOSU/PDM/iosu_pdm.h"
|
||||
#include "Cafe/TitleList/TitleId.h"
|
||||
#include "Cafe/TitleList/TitleList.h"
|
||||
|
||||
struct Game {
|
||||
std::string name;
|
||||
uint32 secondsPlayed;
|
||||
uint16 dlc;
|
||||
uint16 version;
|
||||
TitleId titleId;
|
||||
CafeConsoleRegion region;
|
||||
};
|
||||
|
||||
class GameTitleLoadedCallback {
|
||||
public:
|
||||
virtual void onTitleLoaded(const Game &game) = 0;
|
||||
};
|
||||
|
||||
class GameTitleLoader {
|
||||
std::atomic_bool m_continueLoading = true;
|
||||
std::mutex m_threadMutex;
|
||||
std::condition_variable m_condVar;
|
||||
std::thread m_loaderThread;
|
||||
std::deque<TitleId> m_titlesToLoad;
|
||||
std::optional<uint64> m_callbackIdTitleList;
|
||||
std::map<TitleId, Game> m_gameInfos;
|
||||
std::map<TitleId, std::string> m_name_cache;
|
||||
std::shared_ptr<GameTitleLoadedCallback> m_gameTitleLoadedCallback = nullptr;
|
||||
public:
|
||||
GameTitleLoader();
|
||||
|
||||
void queueTitle(TitleId titleId);
|
||||
|
||||
void setOnTitleLoaded(const std::shared_ptr<GameTitleLoadedCallback> &gameTitleLoadedCallback);
|
||||
|
||||
void reloadGameTitles();
|
||||
|
||||
~GameTitleLoader();
|
||||
|
||||
void titleRefresh(TitleId titleId);
|
||||
|
||||
void addGamePath(const fs::path &path);
|
||||
|
||||
private:
|
||||
void loadGameTitles();
|
||||
|
||||
std::string GetNameByTitleId(uint64 titleId);
|
||||
|
||||
void registerCallback();
|
||||
|
||||
void HandleTitleListCallback(CafeTitleListCallbackEvent *evt);
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
#include "Image.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_ONLY_TGA
|
||||
|
||||
#include "stb_image.h"
|
||||
|
||||
Image::Image(Image &&image) {
|
||||
this->m_image = image.m_image;
|
||||
this->m_width = image.m_width;
|
||||
this->m_height = image.m_height;
|
||||
this->m_channels = image.m_channels;
|
||||
image.m_image = nullptr;
|
||||
}
|
||||
|
||||
Image::Image(const std::vector<uint8> &imageBytes) {
|
||||
m_image =
|
||||
stbi_load_from_memory(imageBytes.data(), imageBytes.size(), &m_width,
|
||||
&m_height, &m_channels, STBI_rgb_alpha);
|
||||
if (m_image) {
|
||||
for (int i = 0; i < m_width * m_height * 4; i += 4) {
|
||||
uint8 r = m_image[i];
|
||||
uint8 g = m_image[i + 1];
|
||||
uint8 b = m_image[i + 2];
|
||||
uint8 a = m_image[i + 3];
|
||||
m_image[i] = b;
|
||||
m_image[i + 1] = g;
|
||||
m_image[i + 2] = r;
|
||||
m_image[i + 3] = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Image::isOk() const { return m_image != nullptr; }
|
||||
|
||||
int *Image::intColors() const { return reinterpret_cast<int *>(m_image); }
|
||||
|
||||
Image::~Image() {
|
||||
if (m_image)
|
||||
stbi_image_free(m_image);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
struct Image {
|
||||
uint8_t *m_image = nullptr;
|
||||
int m_width = 0;
|
||||
int m_height = 0;
|
||||
int m_channels = 0;
|
||||
|
||||
Image(Image &&image);
|
||||
|
||||
Image(const std::vector <uint8> &imageBytes);
|
||||
|
||||
bool isOk() const;
|
||||
|
||||
int *intColors() const;
|
||||
|
||||
~Image();
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
bool GLCanvas_MakeCurrent(bool padView) {}
|
||||
void GLCanvas_SwapBuffers(bool swapTV, bool swapDRC) {}
|
||||
bool GLCanvas_HasPadViewOpen() {}
|
||||
@@ -1,80 +0,0 @@
|
||||
#include "Utils.h"
|
||||
#include "config/ActiveSettings.h"
|
||||
#include "Cemu/ncrypto/ncrypto.h"
|
||||
|
||||
void createCemuDirectories()
|
||||
{
|
||||
std::wstring mlc = ActiveSettings::GetMlcPath().generic_wstring();
|
||||
|
||||
// create sys/usr folder in mlc01
|
||||
try {
|
||||
const auto sysFolder = fs::path(mlc).append(L"sys");
|
||||
fs::create_directories(sysFolder);
|
||||
|
||||
const auto usrFolder = fs::path(mlc).append(L"usr");
|
||||
fs::create_directories(usrFolder);
|
||||
fs::create_directories(fs::path(usrFolder).append("title/00050000")); // base
|
||||
fs::create_directories(fs::path(usrFolder).append("title/0005000c")); // dlc
|
||||
fs::create_directories(fs::path(usrFolder).append("title/0005000e")); // update
|
||||
|
||||
// Mii Maker save folders {0x500101004A000, 0x500101004A100, 0x500101004A200},
|
||||
fs::create_directories(fs::path(mlc).append(L"usr/save/00050010/1004a000/user/common/db"));
|
||||
fs::create_directories(fs::path(mlc).append(L"usr/save/00050010/1004a100/user/common/db"));
|
||||
fs::create_directories(fs::path(mlc).append(L"usr/save/00050010/1004a200/user/common/db"));
|
||||
|
||||
// lang files
|
||||
auto langDir = fs::path(mlc).append(L"sys/title/0005001b/1005c000/content");
|
||||
fs::create_directories(langDir);
|
||||
|
||||
auto langFile = fs::path(langDir).append("language.txt");
|
||||
if (!fs::exists(langFile)) {
|
||||
std::ofstream file(langFile);
|
||||
if (file.is_open()) {
|
||||
const char *langStrings[] = {"ja", "en", "fr", "de", "it", "es", "zh", "ko", "nl",
|
||||
"pt", "ru", "zh"};
|
||||
for (const char *lang: langStrings)
|
||||
file << fmt::format(R"("{}",)", lang) << std::endl;
|
||||
|
||||
file.flush();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
auto countryFile = fs::path(langDir).append("country.txt");
|
||||
if (!fs::exists(countryFile)) {
|
||||
std::ofstream file(countryFile);
|
||||
for (sint32 i = 0; i < 201; i++) {
|
||||
const char *countryCode = NCrypto::GetCountryAsString(i);
|
||||
if (boost::iequals(countryCode, "NN"))
|
||||
file << "NULL," << std::endl;
|
||||
else
|
||||
file << fmt::format(R"("{}",)", countryCode) << std::endl;
|
||||
}
|
||||
file.flush();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
catch (const std::exception &ex) {
|
||||
// std::stringstream errorMsg;
|
||||
// errorMsg << fmt::format(fmt::runtime(_("Couldn't create a required mlc01 subfolder or file!\n\nError: {0}\nTarget path:\n{1}").ToStdString()), ex.what(), boost::nowide::narrow(mlc));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// cemu directories
|
||||
try {
|
||||
const auto controllerProfileFolder = ActiveSettings::GetConfigPath(
|
||||
L"controllerProfiles").generic_wstring();
|
||||
if (!fs::exists(controllerProfileFolder))
|
||||
fs::create_directories(controllerProfileFolder);
|
||||
|
||||
const auto memorySearcherFolder = ActiveSettings::GetUserDataPath(
|
||||
L"memorySearcher").generic_wstring();
|
||||
if (!fs::exists(memorySearcherFolder))
|
||||
fs::create_directories(memorySearcherFolder);
|
||||
}
|
||||
catch (const std::exception &ex) {
|
||||
std::stringstream errorMsg;
|
||||
// errorMsg << fmt::format(fmt::runtime(_("Couldn't create a required cemu directory or file!\n\nError: {0}").ToStdString()), ex.what());
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "config/ActiveSettings.h"
|
||||
#include "Cemu/ncrypto/ncrypto.h"
|
||||
|
||||
void createCemuDirectories();
|
||||
File diff suppressed because it is too large
Load Diff
+165
-8
@@ -1,13 +1,170 @@
|
||||
add_library(CemuGui
|
||||
guiWrapper.h
|
||||
add_library(CemuGui
|
||||
canvas/IRenderCanvas.h
|
||||
canvas/OpenGLCanvas.cpp
|
||||
canvas/OpenGLCanvas.h
|
||||
canvas/VulkanCanvas.cpp
|
||||
canvas/VulkanCanvas.h
|
||||
CemuApp.cpp
|
||||
CemuApp.h
|
||||
CemuUpdateWindow.cpp
|
||||
CemuUpdateWindow.h
|
||||
ChecksumTool.cpp
|
||||
ChecksumTool.h
|
||||
components/TextList.cpp
|
||||
components/TextList.h
|
||||
components/wxDownloadManagerList.cpp
|
||||
components/wxDownloadManagerList.h
|
||||
components/wxGameList.cpp
|
||||
components/wxGameList.h
|
||||
components/wxInputDraw.cpp
|
||||
components/wxInputDraw.h
|
||||
components/wxLogCtrl.cpp
|
||||
components/wxLogCtrl.h
|
||||
components/wxTitleManagerList.cpp
|
||||
components/wxTitleManagerList.h
|
||||
debugger/AudioDebuggerWindow.cpp
|
||||
debugger/AudioDebuggerWindow.h
|
||||
debugger/BreakpointWindow.cpp
|
||||
debugger/BreakpointWindow.h
|
||||
debugger/DebuggerWindow2.cpp
|
||||
debugger/DebuggerWindow2.h
|
||||
debugger/DisasmCtrl.cpp
|
||||
debugger/DisasmCtrl.h
|
||||
debugger/DumpCtrl.cpp
|
||||
debugger/DumpCtrl.h
|
||||
debugger/DumpWindow.cpp
|
||||
debugger/DumpWindow.h
|
||||
debugger/ModuleWindow.cpp
|
||||
debugger/ModuleWindow.h
|
||||
debugger/RegisterCtrl.cpp
|
||||
debugger/RegisterCtrl.h
|
||||
debugger/RegisterWindow.cpp
|
||||
debugger/RegisterWindow.h
|
||||
debugger/SymbolCtrl.cpp
|
||||
debugger/SymbolCtrl.h
|
||||
debugger/SymbolWindow.cpp
|
||||
debugger/SymbolWindow.h
|
||||
dialogs/CreateAccount/wxCreateAccountDialog.cpp
|
||||
dialogs/CreateAccount/wxCreateAccountDialog.h
|
||||
dialogs/SaveImport/SaveImportWindow.cpp
|
||||
dialogs/SaveImport/SaveImportWindow.h
|
||||
dialogs/SaveImport/SaveTransfer.cpp
|
||||
dialogs/SaveImport/SaveTransfer.h
|
||||
DownloadGraphicPacksWindow.cpp
|
||||
DownloadGraphicPacksWindow.h
|
||||
GameProfileWindow.cpp
|
||||
GameProfileWindow.h
|
||||
GameUpdateWindow.cpp
|
||||
GameUpdateWindow.h
|
||||
GeneralSettings2.cpp
|
||||
GeneralSettings2.h
|
||||
GettingStartedDialog.cpp
|
||||
GettingStartedDialog.h
|
||||
GraphicPacksWindow2.cpp
|
||||
GraphicPacksWindow2.h
|
||||
helpers/wxControlObject.h
|
||||
helpers/wxCustomData.h
|
||||
helpers/wxCustomEvents.cpp
|
||||
helpers/wxCustomEvents.h
|
||||
helpers/wxHelpers.cpp
|
||||
helpers/wxHelpers.h
|
||||
helpers/wxLogEvent.h
|
||||
helpers/wxWayland.cpp
|
||||
helpers/wxWayland.h
|
||||
input/InputAPIAddWindow.cpp
|
||||
input/InputAPIAddWindow.h
|
||||
input/InputSettings2.cpp
|
||||
input/InputSettings2.h
|
||||
input/panels/ClassicControllerInputPanel.cpp
|
||||
input/panels/ClassicControllerInputPanel.h
|
||||
input/panels/InputPanel.cpp
|
||||
input/panels/InputPanel.h
|
||||
input/panels/ProControllerInputPanel.cpp
|
||||
input/panels/ProControllerInputPanel.h
|
||||
input/panels/VPADInputPanel.cpp
|
||||
input/panels/VPADInputPanel.h
|
||||
input/panels/WiimoteInputPanel.cpp
|
||||
input/panels/WiimoteInputPanel.h
|
||||
input/settings/DefaultControllerSettings.cpp
|
||||
input/settings/DefaultControllerSettings.h
|
||||
input/settings/WiimoteControllerSettings.cpp
|
||||
input/settings/WiimoteControllerSettings.h
|
||||
LoggingWindow.cpp
|
||||
LoggingWindow.h
|
||||
MainWindow.cpp
|
||||
MainWindow.h
|
||||
MemorySearcherTool.cpp
|
||||
MemorySearcherTool.h
|
||||
PadViewFrame.cpp
|
||||
PadViewFrame.h
|
||||
TitleManager.cpp
|
||||
TitleManager.h
|
||||
windows/PPCThreadsViewer
|
||||
windows/PPCThreadsViewer/DebugPPCThreadsWindow.cpp
|
||||
windows/PPCThreadsViewer/DebugPPCThreadsWindow.h
|
||||
windows/TextureRelationViewer
|
||||
windows/TextureRelationViewer/TextureRelationWindow.cpp
|
||||
windows/TextureRelationViewer/TextureRelationWindow.h
|
||||
wxcomponents/checked2.xpm
|
||||
wxcomponents/checked_dis.xpm
|
||||
wxcomponents/checked_d.xpm
|
||||
wxcomponents/checked_ld.xpm
|
||||
wxcomponents/checkedlistctrl.cpp
|
||||
wxcomponents/checkedlistctrl.h
|
||||
wxcomponents/checked_mo.xpm
|
||||
wxcomponents/checked.xpm
|
||||
wxcomponents/checktree.cpp
|
||||
wxcomponents/checktree.h
|
||||
wxcomponents/unchecked2.xpm
|
||||
wxcomponents/unchecked_dis.xpm
|
||||
wxcomponents/unchecked_d.xpm
|
||||
wxcomponents/unchecked_ld.xpm
|
||||
wxcomponents/unchecked_mo.xpm
|
||||
wxcomponents/unchecked.xpm
|
||||
wxgui.h
|
||||
wxHelper.h
|
||||
)
|
||||
|
||||
if(ANDROID)
|
||||
add_subdirectory(AndroidGui)
|
||||
target_link_libraries(CemuGui PRIVATE CemuAndroidGui)
|
||||
set_property(TARGET CemuGui PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
|
||||
target_include_directories(CemuGui PUBLIC "../")
|
||||
# PUBLIC because rapidjson/document.h is included in ChecksumTool.h
|
||||
target_include_directories(CemuGui PUBLIC ${RAPIDJSON_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(CemuGui PRIVATE
|
||||
CemuAudio
|
||||
CemuCafe
|
||||
CemuCommon
|
||||
CemuComponents
|
||||
CemuConfig
|
||||
CemuInput
|
||||
CemuResource
|
||||
CemuUtil
|
||||
Boost::headers
|
||||
CURL::libcurl
|
||||
libzip::zip
|
||||
OpenSSL::Crypto
|
||||
pugixml::pugixml
|
||||
ZArchive::zarchive
|
||||
)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(CemuGui PRIVATE GTK3::gtk)
|
||||
if (ENABLE_WAYLAND)
|
||||
target_link_libraries(CemuGui PRIVATE Wayland::Client CemuWaylandProtocols)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_WXWIDGETS)
|
||||
add_subdirectory(wxGui)
|
||||
target_link_libraries(CemuGui PRIVATE CemuwxGui)
|
||||
if(ENABLE_CUBEB)
|
||||
target_link_libraries(CemuGui PRIVATE cubeb::cubeb)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(ENABLE_FERAL_GAMEMODE)
|
||||
target_link_libraries(CemuGui PRIVATE gamemode)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# PUBLIC because wx/app.h is included in CemuApp.h
|
||||
target_link_libraries(CemuGui PUBLIC wx::base wx::core wx::gl wx::propgrid wx::xrc)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user