diff --git a/src/Application.cpp b/src/Application.cpp index 65ed9b0..1892883 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -41,7 +41,7 @@ bool Application::exitApplication = false; bool Application::quitRequest = false; Application::Application() - : CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x20000) + : CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x800000) , bgMusic(NULL) , video(NULL) , mainWindow(NULL) @@ -59,6 +59,8 @@ Application::Application() bgMusic->Play(); bgMusic->SetVolume(50); + AsyncExecutor::execute([] {DEBUG_FUNCTION_LINE("Hello\n");}); + exitApplication = false; uint64_t titleID = OSGetTitleID(); diff --git a/src/game/GameList.cpp b/src/game/GameList.cpp index 1822928..a58266c 100644 --- a/src/game/GameList.cpp +++ b/src/game/GameList.cpp @@ -13,12 +13,12 @@ #include "fs/FSUtils.h" #include "utils/logger.h" #include "utils/StringTools.h" +#include "system/CMutex.h" void GameList::clear() { for (auto const& x : fullGameList) { if(x != NULL) { if(x->imageData != NULL) { - DEBUG_FUNCTION_LINE("Delete the image data\n"); delete x->imageData; x->imageData = NULL; } @@ -80,8 +80,10 @@ int32_t GameList::readGameList() { titles.resize(realTitleCount); } + CMutex extraInfoMutex; + for (auto title_candidate : titles) { - if(true || (title_candidate.titleId & 0xFFFFFFFF00000000L) == 0x0005000000000000L) { + if((title_candidate.titleId & 0xFFFFFFFF00000000L) == 0x0005000000000000L) { gameInfo* newGameInfo = new gameInfo; newGameInfo->titleId = title_candidate.titleId; newGameInfo->gamePath = title_candidate.path; @@ -91,6 +93,39 @@ int32_t GameList::readGameList() { fullGameList.push_back(newGameInfo); titleAdded(newGameInfo); cnt++; + + AsyncExecutor::execute([newGameInfo, this, &extraInfoMutex] { + extraInfoMutex.lock(); + DEBUG_FUNCTION_LINE("Load extra infos of %016llX\n",newGameInfo->titleId); + ACPMetaXml* meta = (ACPMetaXml*)calloc(1, 0x4000); //TODO fix wut + if(meta) { + auto acp = ACPGetTitleMetaXml(newGameInfo->titleId, meta); + if(acp >= 0) { + newGameInfo->name = meta->shortname_en; + } + free(meta); + } + + if(newGameInfo->imageData == NULL) { + std::string filepath = "fs:" + newGameInfo->gamePath + META_PATH + "/iconTex.tga"; + uint8_t *buffer = NULL; + uint32_t bufferSize = 0; + int iResult = FSUtils::LoadFileToMem(filepath.c_str(), &buffer, &bufferSize); + + if(iResult > 0) { + GuiImageData * imageData = new GuiImageData(buffer, bufferSize, GX2_TEX_CLAMP_MODE_MIRROR); + if(imageData) { + newGameInfo->imageData = imageData; + } + + //! free original image buffer which is converted to texture now and not needed anymore + free(buffer); + } + } + DCFlushRange(newGameInfo, sizeof(gameInfo)); + titleUpdated(newGameInfo); + extraInfoMutex.unlock(); + }); } } diff --git a/src/menu/MainWindow.cpp b/src/menu/MainWindow.cpp index 95d1aac..7234e92 100644 --- a/src/menu/MainWindow.cpp +++ b/src/menu/MainWindow.cpp @@ -124,10 +124,7 @@ void MainWindow::OnGameTitleUpdated(gameInfo * info) { } void MainWindow::OnGameTitleAdded(gameInfo * info) { - DEBUG_FUNCTION_LINE("%08X\n", info); - if(info == NULL) { - return; - } + currentTvFrame->OnGameTitleAdded(info); if(currentTvFrame != currentDrcFrame) { currentDrcFrame->OnGameTitleAdded(info); diff --git a/src/utils/AsyncExecutor.cpp b/src/utils/AsyncExecutor.cpp index edec646..bfbd2ce 100644 --- a/src/utils/AsyncExecutor.cpp +++ b/src/utils/AsyncExecutor.cpp @@ -6,15 +6,39 @@ AsyncExecutor * AsyncExecutor::instance = NULL; void AsyncExecutor::pushForDelete(GuiElement * ptr) { execute([ptr] {delete ptr;}); } +AsyncExecutor::AsyncExecutor() { + thread = new std::thread([&]() { + while(!exitThread) { + instance->mutex.lock(); + auto it = instance->elements.begin(); + while (it != instance->elements.end()) { + auto future = it; + auto status = future->wait_for(std::chrono::seconds(0)); + if (status == std::future_status::ready) { + it = instance->elements.erase(it); + } else { + ++it; + } + } + instance->mutex.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + DCFlushRange((void*)&exitThread, sizeof(exitThread)); + } + }); + + thread->detach(); +} void AsyncExecutor::execute(std::function func) { if(!instance) { instance = new AsyncExecutor(); } - instance->elements.push(std::async(std::launch::async,func)); - if(instance->elements.size() >= 25){ - //DEBUG_FUNCTION_LINE("Wait on queue %d\n",instance->elements.size()); - instance->elements.front().get(); - instance->elements.pop(); + + while(instance->elements.size() > 10) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } + + instance->mutex.lock(); + instance->elements.push_back(std::async(std::launch::async,func)); + instance->mutex.unlock(); } diff --git a/src/utils/AsyncExecutor.h b/src/utils/AsyncExecutor.h index 599d6ec..702c65d 100644 --- a/src/utils/AsyncExecutor.h +++ b/src/utils/AsyncExecutor.h @@ -1,8 +1,14 @@ -#pragma once +#ifndef ___ASYNCEXECUTER_H_ +#define ___ASYNCEXECUTER_H_ -#include + +#include #include +#include #include +#include +#include +#include "utils/logger.h" class AsyncExecutor { public: @@ -19,8 +25,17 @@ public: private: static AsyncExecutor *instance; - AsyncExecutor() {} - ~AsyncExecutor() {} + AsyncExecutor(); - std::queue> elements; + ~AsyncExecutor() { + exitThread = true; + DCFlushRange((void*)&exitThread, sizeof(exitThread)); + } + + CMutex mutex; + std::thread * thread; + volatile bool exitThread = false; + + std::vector> elements; }; +#endif