#include "stdafx.h" #include "Emu/Cell/PPUModule.h" #include "Emu/IdManager.h" #include "sceNp.h" #include "sceNpUtil.h" LOG_CHANNEL(sceNpUtil); struct bandwidth_test { atomic_t status = SCE_NP_UTIL_BANDWIDTH_TEST_STATUS_NONE; atomic_t abort = false; atomic_t shutdown = false; atomic_t finished = false; SceNpUtilBandwidthTestResult test_result{}; static constexpr auto thread_name = "HLE SceNpBandwidthTest"sv; void operator()() { status = SCE_NP_UTIL_BANDWIDTH_TEST_STATUS_RUNNING; u32 fake_sleep_count = 0; while (thread_ctrl::state() != thread_state::aborting) { if (abort || shutdown) { break; } // TODO: run proper bandwidth test, probably with cellHttp thread_ctrl::wait_for(1000); // wait 1ms if (fake_sleep_count++ > 100) // end fake bandwidth test after 100 ms { break; } } test_result.upload_bps = 100'000'000.0; test_result.download_bps = 100'000'000.0; test_result.result = CELL_OK; status = SCE_NP_UTIL_BANDWIDTH_TEST_STATUS_FINISHED; finished = true; } }; struct sce_np_util_manager { shared_mutex mtx{}; std::unique_ptr> bandwidth_test_thread; ~sce_np_util_manager() { join_thread(); } void join_thread() { if (bandwidth_test_thread) { auto& thread = *bandwidth_test_thread; thread = thread_state::aborting; thread(); bandwidth_test_thread.reset(); } } }; error_code sceNpUtilBandwidthTestInitStart([[maybe_unused]] ppu_thread& ppu, u32 prio, u32 stack) { sceNpUtil.todo("sceNpUtilBandwidthTestInitStart(prio=%d, stack=%d)", prio, stack); auto& util_manager = g_fxo->get(); std::lock_guard lock(util_manager.mtx); if (util_manager.bandwidth_test_thread) { return SCE_NP_ERROR_ALREADY_INITIALIZED; } util_manager.bandwidth_test_thread = std::make_unique>(); return CELL_OK; } error_code sceNpUtilBandwidthTestGetStatus() { sceNpUtil.notice("sceNpUtilBandwidthTestGetStatus()"); auto& util_manager = g_fxo->get(); std::lock_guard lock(util_manager.mtx); if (!util_manager.bandwidth_test_thread) { return SCE_NP_ERROR_NOT_INITIALIZED; } return not_an_error(util_manager.bandwidth_test_thread->status); } error_code sceNpUtilBandwidthTestShutdown([[maybe_unused]] ppu_thread& ppu, vm::ptr result) { sceNpUtil.warning("sceNpUtilBandwidthTestShutdown(result=*0x%x)", result); auto& util_manager = g_fxo->get(); std::lock_guard lock(util_manager.mtx); if (!util_manager.bandwidth_test_thread) { return SCE_NP_ERROR_NOT_INITIALIZED; } util_manager.bandwidth_test_thread->shutdown = true; while (!util_manager.bandwidth_test_thread->finished) { thread_ctrl::wait_for(1000); } if (result) // TODO: what happens when this is null ? { *result = util_manager.bandwidth_test_thread->test_result; } util_manager.join_thread(); return CELL_OK; } error_code sceNpUtilBandwidthTestAbort() { sceNpUtil.todo("sceNpUtilBandwidthTestAbort()"); auto& util_manager = g_fxo->get(); std::lock_guard lock(util_manager.mtx); if (!util_manager.bandwidth_test_thread) { return SCE_NP_ERROR_NOT_INITIALIZED; } // TODO: cellHttpTransactionAbortConnection(); util_manager.bandwidth_test_thread->abort = true; return CELL_OK; } DECLARE(ppu_module_manager::sceNpUtil)("sceNpUtil", []() { REG_FUNC(sceNpUtil, sceNpUtilBandwidthTestInitStart); REG_FUNC(sceNpUtil, sceNpUtilBandwidthTestShutdown); REG_FUNC(sceNpUtil, sceNpUtilBandwidthTestGetStatus); REG_FUNC(sceNpUtil, sceNpUtilBandwidthTestAbort); });