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 10, 2023
1 parent 4bbe885 commit 22a9502
Show file tree
Hide file tree
Showing 12 changed files with 243 additions and 42 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);
});
3 changes: 3 additions & 0 deletions rpcs3/Emu/Cell/Modules/sysPrxForUser.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ error_code sys_lwcond_wait(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 ti
error_code sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::cptr<char> threadname);
error_code sys_interrupt_thread_disestablish(ppu_thread& ppu, u32 ih);

u32 _sys_malloc(u32 size);
error_code _sys_free(u32 addr);

void sys_ppu_thread_exit(ppu_thread& CPU, u64 val);
void sys_game_process_exitspawn(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags);
void sys_game_process_exitspawn2(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags);
14 changes: 13 additions & 1 deletion 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"


#include "Emu/Cell/lv2/sys_event.h"
#include "Emu/Cell/lv2/sys_ppu_thread.h"
Expand All @@ -19,6 +23,7 @@ struct libio_sys_config
s32 init_ctr = 0;
u32 ppu_id = 0;
u32 queue_id = 0;
u32 malloc_addr = 0;

~libio_sys_config() noexcept
{
Expand All @@ -38,14 +43,19 @@ void config_event_entry(ppu_thread& ppu)
{
if (ppu.is_stopped())
{
ppu.state += cpu_flag::again;
return;
}

// Some delay
thread_ctrl::wait_for(10000);

// Wakeup
ppu.check_state();
if (ppu.check_state();)
{
ppu.state += cpu_flag::again;
return;
}

const u64 arg1 = ppu.gpr[5];
const u64 arg2 = ppu.gpr[6];
Expand Down Expand Up @@ -97,6 +107,7 @@ error_code sys_config_start(ppu_thread& ppu)
attr->type = SYS_PPU_QUEUE;
attr->name_u64 = 0;

ensure(!!(cfg.malloc_addr = ppu_execute<&_sys_malloc>(0x7720 + + 0x28 + 0xe90 + 0x14)));
ensure(CELL_OK == sys_event_queue_create(ppu, queue_id, attr, 0, 0x20));
ensure(CELL_OK == ppu_execute<&sys_ppu_thread_create>(ppu, +_tid, g_fxo->get<ppu_function_manager>().func_addr(FIND_FUNC(config_event_entry)), 0, 512, 0x2000, SYS_PPU_THREAD_CREATE_JOINABLE, +_name));

Expand All @@ -119,6 +130,7 @@ error_code sys_config_stop(ppu_thread& ppu)
{
ensure(CELL_OK == sys_event_queue_destroy(ppu, cfg.queue_id, SYS_EVENT_QUEUE_DESTROY_FORCE));
ensure(CELL_OK == sys_ppu_thread_join(ppu, cfg.ppu_id, +vm::var<u64>{}));
ensure(CELL_OK == ppu_execute<&_sys_free>(cfg.malloc_addr));
}
else
{
Expand Down
Loading

0 comments on commit 22a9502

Please sign in to comment.