Skip to content

Commit

Permalink
More accurate PS3 memory consumption
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Aug 2, 2023
1 parent bb2d706 commit 8c1e5ce
Show file tree
Hide file tree
Showing 11 changed files with 267 additions and 47 deletions.
45 changes: 42 additions & 3 deletions rpcs3/Emu/Cell/Modules/cellAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_process.h"
#include "Emu/Cell/lv2/sys_event.h"
#include "Emu/Cell/lv2/sys_memory.h"
#include "util/asm.hpp"
#include "cellAudio.h"

#include <cmath>
Expand Down Expand Up @@ -1203,6 +1205,7 @@ error_code cellAudioInit()
cellAudio.warning("cellAudioInit()");

auto& g_audio = g_fxo->get<cell_audio>();
auto& dct = g_fxo->get<lv2_memory_container>();

std::lock_guard lock(g_audio.mutex);

Expand All @@ -1211,6 +1214,12 @@ error_code cellAudioInit()
return CELL_AUDIO_ERROR_ALREADY_INIT;
}

// TODO: This is the minimum amount, it can allocate more if specified by VSH (needs investigation)
if (!dct.take(0x10000))
{
return CELL_AUDIO_ERROR_SHAREDMEMORY;
}

std::memset(g_audio_buffer.get_ptr(), 0, g_audio_buffer.alloc_size);
std::memset(g_audio_indices.get_ptr(), 0, g_audio_indices.alloc_size);

Expand All @@ -1232,6 +1241,7 @@ error_code cellAudioQuit()
cellAudio.warning("cellAudioQuit()");

auto& g_audio = g_fxo->get<cell_audio>();
auto& dct = g_fxo->get<lv2_memory_container>();

std::lock_guard lock(g_audio.mutex);

Expand All @@ -1240,6 +1250,19 @@ error_code cellAudioQuit()
return CELL_AUDIO_ERROR_NOT_INIT;
}

// See cellAudioInit
u32 to_free = 0x10000;

for (auto& port : g_audio.ports)
{
if (port.state.exchange(audio_port_state::closed) != audio_port_state::closed)
{
to_free += utils::align<u32>(port.size, 0x10000) + 0x10000;
}
}

dct.free(to_free);

// NOTE: Do not clear event queues here. They are handled independently.
g_audio.init = 0;

Expand All @@ -1252,6 +1275,8 @@ error_code cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32

auto& g_audio = g_fxo->get<cell_audio>();

auto& dct = g_fxo->get<lv2_memory_container>();

std::lock_guard lock(g_audio.mutex);

if (!g_audio.init)
Expand Down Expand Up @@ -1319,6 +1344,9 @@ error_code cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32
cellAudio.todo("cellAudioPortOpen(): unknown attributes (0x%llx)", attr);
}

const u32 mem_size = ::narrow<u32>(num_channels * num_blocks * AUDIO_BUFFER_SAMPLES * sizeof(f32));
const u32 mem_page_size = utils::align<u32>(mem_size, 0x10000) + 0x10000;

// Open audio port
audio_port* port = g_audio.open_port();

Expand All @@ -1327,13 +1355,20 @@ error_code cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32
return CELL_AUDIO_ERROR_PORT_FULL;
}

// Fake memory allocation required for the port creation (64k flags)
if (!dct.take(mem_page_size))
{
ensure(port->state.compare_and_swap_test(audio_port_state::opened, audio_port_state::closed));
return CELL_AUDIO_ERROR_SHAREDMEMORY;
}

// TODO: is this necessary in any way? (Based on libaudio.prx)
//const u64 num_channels_non_0 = std::max<u64>(1, num_channels);

port->num_channels = ::narrow<u32>(num_channels);
port->num_blocks = ::narrow<u32>(num_blocks);
port->attr = attr;
port->size = ::narrow<u32>(num_channels * num_blocks * AUDIO_BUFFER_SAMPLES * sizeof(f32));
port->size = mem_size;
port->cur_pos = 0;
port->global_counter = g_audio.m_counter;
port->active_counter = 0;
Expand Down Expand Up @@ -1452,10 +1487,14 @@ error_code cellAudioPortClose(u32 portNum)
switch (audio_port_state state = g_audio.ports[portNum].state.exchange(audio_port_state::closed))
{
case audio_port_state::closed: return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
case audio_port_state::started: return CELL_OK;
case audio_port_state::opened: return CELL_OK;
case audio_port_state::started: break;
case audio_port_state::opened: break;
default: fmt::throw_exception("Invalid port state (%d: %d)", portNum, static_cast<u32>(state));
}

const u32 mem_page_size = utils::align<u32>(g_audio.ports[portNum].size, 0x10000) + 0x10000;
g_fxo->get<lv2_memory_container>().free(mem_page_size);
return CELL_OK;
}

error_code cellAudioPortStop(u32 portNum)
Expand Down
63 changes: 50 additions & 13 deletions rpcs3/Emu/Cell/Modules/sceNp2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include "Emu/NP/np_handler.h"
#include "Emu/NP/np_contexts.h"
#include "Emu/NP/np_helpers.h"
#include "Emu/Cell/Modules/sysPrxForUser.h"
#include "Emu/Cell/lv2/sys_ppu_thread.h"
#include "Emu/Cell/lv2/sys_sync.h"
#include "cellSysutil.h"

LOG_CHANNEL(sceNp2);
Expand Down Expand Up @@ -175,9 +178,9 @@ void fmt_class_string<SceNpOauthError>::format(std::string& out, u64 arg)
});
}

error_code sceNpMatching2Init2(u64 stackSize, s32 priority, vm::ptr<SceNpMatching2UtilityInitParam> param);
error_code sceNpMatching2Init2(ppu_thread& ppu, u64 stackSize, s32 priority, vm::ptr<SceNpMatching2UtilityInitParam> param);
error_code sceNpMatching2Term(ppu_thread& ppu);
error_code sceNpMatching2Term2();
error_code sceNpMatching2Term2(ppu_thread& ppu);

error_code generic_match2_error_check(const named_thread<np::np_handler>& nph, SceNpMatching2ContextId ctxId, vm::cptr<void> reqParam, vm::ptr<SceNpMatching2RequestId> assignedReqId)
{
Expand Down Expand Up @@ -230,13 +233,33 @@ error_code sceNp2Init(u32 poolsize, vm::ptr<void> poolptr)
return CELL_OK;
}

error_code sceNpMatching2Init(u32 stackSize, s32 priority)
error_code sceNpMatching2Init(ppu_thread& ppu, u32 stackSize, s32 priority)
{
sceNp2.todo("sceNpMatching2Init(stackSize=0x%x, priority=%d)", stackSize, priority);
return sceNpMatching2Init2(stackSize, priority, vm::null); // > SDK 2.4.0
return sceNpMatching2Init2(ppu, stackSize, priority, vm::null); // > SDK 2.4.0
}

error_code sceNpMatching2Init2(u64 stackSize, s32 priority, vm::ptr<SceNpMatching2UtilityInitParam> param)
static void s_matching2_thread_func(ppu_thread& ppu)
{
lv2_obj::sleep(ppu);
auto& nph = g_fxo->get<named_thread<np::np_handler>>();

while (nph.is_NP2_Match2_init && thread_ctrl::state() != thread_state::aborting && !ppu.is_stopped())
{
thread_ctrl::wait_on(nph.is_NP2_Match2_init, true);
}

if (!nph.is_NP2_Match2_init)
{
ppu_execute<&sys_ppu_thread_exit>(ppu, 0);
}
else
{
ppu.state += cpu_flag::again;
}
}

error_code sceNpMatching2Init2(ppu_thread& ppu, u64 stackSize, s32 priority, vm::ptr<SceNpMatching2UtilityInitParam> param)
{
sceNp2.warning("sceNpMatching2Init2(stackSize=0x%x, priority=%d, param=*0x%x)", stackSize, priority, param);

Expand All @@ -253,9 +276,18 @@ error_code sceNpMatching2Init2(u64 stackSize, s32 priority, vm::ptr<SceNpMatchin
}

// TODO:
// 1. Create an internal thread
// 2. Create heap area to be used by the NP matching 2 utility
// 3. Set maximum lengths for the event data queues in the system
// 1. Create heap area to be used by the NP matching 2 utility
// 2. Set maximum lengths for the event data queues in the system

vm::var<u64> _tid;
vm::var<char[]> _name = vm::make_str("SceNpMatching2ScCb");

const u32 stack_size = stackSize ? stackSize : 0x4000;

// TODO: error checking
ensure(ppu_execute<&sys_ppu_thread_create>(ppu, +_tid, g_fxo->get<ppu_function_manager>().func_addr(FIND_FUNC(s_matching2_thread_func)), 0, priority, stack_size, SYS_PPU_THREAD_CREATE_JOINABLE, +_name) == CELL_OK);

nph.np2_match2_thread_id = static_cast<u32>(*_tid);

nph.is_NP2_Match2_init = true;

Expand Down Expand Up @@ -286,13 +318,13 @@ error_code sceNp2Term(ppu_thread& ppu)
return CELL_OK;
}

error_code sceNpMatching2Term(ppu_thread&)
error_code sceNpMatching2Term(ppu_thread& ppu)
{
sceNp2.warning("sceNpMatching2Term()");
return sceNpMatching2Term2(); // > SDK 2.4.0
return sceNpMatching2Term2(ppu); // > SDK 2.4.0
}

error_code sceNpMatching2Term2()
error_code sceNpMatching2Term2(ppu_thread& ppu)
{
sceNp2.warning("sceNpMatching2Term2()");

Expand All @@ -311,6 +343,9 @@ error_code sceNpMatching2Term2()
}

nph.is_NP2_Match2_init = false;
nph.is_NP2_Match2_init.notify_one();

ensure(sys_ppu_thread_join(ppu, nph.np2_match2_thread_id, +vm::var<u64>{}) == CELL_OK);
}

// TODO: for all contexts: sceNpMatching2DestroyContext
Expand Down Expand Up @@ -1789,8 +1824,8 @@ error_code sceNpAuthGetAuthorizationCode2()
return CELL_OK;
}

DECLARE(ppu_module_manager::sceNp2)
("sceNp2", []() {
DECLARE(ppu_module_manager::sceNp2)("sceNp2", []()
{
REG_FUNC(sceNp2, sceNpMatching2DestroyContext);
REG_FUNC(sceNp2, sceNpMatching2LeaveLobby);
REG_FUNC(sceNp2, sceNpMatching2RegisterLobbyMessageCallback);
Expand Down Expand Up @@ -1872,4 +1907,6 @@ DECLARE(ppu_module_manager::sceNp2)
REG_FUNC(sceNp2, sceNpAuthAbortOAuthRequest);
REG_FUNC(sceNp2, sceNpAuthGetAuthorizationCode);
REG_FUNC(sceNp2, sceNpAuthGetAuthorizationCode2);

REG_HIDDEN_FUNC(s_matching2_thread_func);
});
46 changes: 38 additions & 8 deletions rpcs3/Emu/Cell/Modules/sys_io_.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_ppu_thread.h"
#include "Emu/Cell/lv2/sys_sync.h"
#include "Emu/Cell/Modules/sysPrxForUser.h"


LOG_CHANNEL(sys_io);

Expand All @@ -12,17 +16,37 @@ extern void cellMouse_init();
struct libio_sys_config
{
shared_mutex mtx;
s32 init_ctr = 0;
u32 stack_addr = 0;
atomic_t<s32> init_ctr = 0;
u32 ppu_id = 0;
};

static void s_evt_hndlr_thread_func(ppu_thread& ppu)
{
lv2_obj::sleep(ppu);

~libio_sys_config() noexcept
auto& cfg = g_fxo->get<libio_sys_config>();

while (thread_ctrl::state() != thread_state::aborting && !ppu.is_stopped())
{
if (stack_addr)
const s32 ctr = cfg.init_ctr;

if (!ctr)
{
ensure(vm::dealloc(stack_addr, vm::stack));
break;
}

thread_ctrl::wait_on(cfg.init_ctr, ctr);
}
};

if (!cfg.init_ctr)
{
ppu_execute<&sys_ppu_thread_exit>(ppu, 0);
}
else
{
ppu.state += cpu_flag::again;
}
}

// Only exists internally (has no name)
extern void libio_sys_config_init()
Expand All @@ -34,7 +58,10 @@ extern void libio_sys_config_init()
if (cfg.init_ctr++ == 0)
{
// Belongs to "_cfg_evt_hndlr" thread (8k stack)
cfg.stack_addr = ensure(vm::alloc(0x2000, vm::stack, 4096));
vm::var<u64> _tid;
vm::var<char[]> _name = vm::make_str("_cfg_evt_hndlr");
ensure(ppu_execute<&sys_ppu_thread_create>(*cpu_thread::get_current<ppu_thread>(), +_tid, g_fxo->get<ppu_function_manager>().func_addr(FIND_FUNC(s_evt_hndlr_thread_func)), 0, 3071, 0x2000, SYS_PPU_THREAD_CREATE_JOINABLE, +_name) == CELL_OK);
cfg.ppu_id = static_cast<u32>(*_tid);
}
}

Expand All @@ -46,7 +73,8 @@ extern void libio_sys_config_end()

if (cfg.init_ctr-- == 1)
{
ensure(vm::dealloc(std::exchange(cfg.stack_addr, 0), vm::stack));
cfg.init_ctr.notify_one();
ensure(sys_ppu_thread_join(*cpu_thread::get_current<ppu_thread>(), cfg.ppu_id, +vm::var<u64>{}) == CELL_OK);
}
}

Expand Down Expand Up @@ -114,4 +142,6 @@ DECLARE(ppu_module_manager::sys_io)("sys_io", []()
REG_FUNC(sys_io, sys_config_register_service);
REG_FUNC(sys_io, sys_config_unregister_io_error_handler);
REG_FUNC(sys_io, sys_config_unregister_service);

REG_HIDDEN_FUNC(s_evt_hndlr_thread_func);
});
Loading

0 comments on commit 8c1e5ce

Please sign in to comment.