diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/Cell/Modules/cellAdec.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellAdec.cpp rename to rpcs3/Emu/Cell/Modules/cellAdec.cpp index 3a1234f6ae..ba9b76fe19 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAdec.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" extern std::mutex g_mutex_avcodec_open2; @@ -16,7 +15,7 @@ extern "C" #include "cellPamf.h" #include "cellAdec.h" -extern Module<> cellAdec; +LOG_CHANNEL(cellAdec); AudioDecoder::AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr func, u32 arg) : type(type) @@ -467,8 +466,9 @@ void adecOpen(u32 adec_id) // TODO: call from the constructor }; - adec.adecCb->run(); - adec.adecCb->exec(); + adec.adecCb->cpu_init(); + adec.adecCb->state -= cpu_state::stop; + adec.adecCb->safe_notify(); } bool adecCheckType(s32 type) @@ -572,7 +572,7 @@ s32 cellAdecClose(u32 handle) std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack } - idm::remove(adec->adecCb->get_id()); + idm::remove(adec->adecCb->id); idm::remove(handle); return CELL_OK; } @@ -863,7 +863,7 @@ s32 cellAdecGetPcmItem(u32 handle, vm::pptr pcmItem) return CELL_OK; } -Module<> cellAdec("cellAdec", []() +DECLARE(ppu_module_manager::cellAdec)("cellAdec", []() { REG_FUNC(cellAdec, cellAdecQueryAttr); REG_FUNC(cellAdec, cellAdecOpen); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/Cell/Modules/cellAdec.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellAdec.h rename to rpcs3/Emu/Cell/Modules/cellAdec.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp b/rpcs3/Emu/Cell/Modules/cellAtrac.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp rename to rpcs3/Emu/Cell/Modules/cellAtrac.cpp index 977aa05480..d251fe9bcb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAtrac.cpp @@ -1,10 +1,11 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellAtrac.h" +LOG_CHANNEL(cellAtrac); + s32 cellAtracSetDataAndGetMemSize(vm::ptr pHandle, vm::ptr pucBufferAddr, u32 uiReadByte, u32 uiBufferByte, vm::ptr puiWorkMemByte) { cellAtrac.warning("cellAtracSetDataAndGetMemSize(pHandle=*0x%x, pucBufferAddr=*0x%x, uiReadByte=0x%x, uiBufferByte=0x%x, puiWorkMemByte=*0x%x)", pHandle, pucBufferAddr, uiReadByte, uiBufferByte, puiWorkMemByte); @@ -194,7 +195,7 @@ s32 cellAtracGetInternalErrorInfo(vm::ptr pHandle, vm::ptr return CELL_OK; } -Module<> cellAtrac("cellAtrac", []() +DECLARE(ppu_module_manager::cellAtrac)("cellAtrac", []() { REG_FUNC(cellAtrac, cellAtracSetDataAndGetMemSize); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAtrac.h b/rpcs3/Emu/Cell/Modules/cellAtrac.h similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellAtrac.h rename to rpcs3/Emu/Cell/Modules/cellAtrac.h index 391c838959..e9cca6f3bf 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAtrac.h +++ b/rpcs3/Emu/Cell/Modules/cellAtrac.h @@ -57,5 +57,3 @@ struct CellAtracExtRes vm::ptr pSpurs; u8 priority[8]; }; - -extern Module<> cellAtrac; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAtracMulti.cpp b/rpcs3/Emu/Cell/Modules/cellAtracMulti.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellAtracMulti.cpp rename to rpcs3/Emu/Cell/Modules/cellAtracMulti.cpp index 5e8c78596d..75e1263f62 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAtracMulti.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAtracMulti.cpp @@ -1,10 +1,11 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellAtracMulti.h" +LOG_CHANNEL(cellAtracMulti); + s32 cellAtracMultiSetDataAndGetMemSize(vm::ptr pHandle, vm::ptr pucBufferAddr, u32 uiReadByte, u32 uiBufferByte, u32 uiOutputChNum, vm::ptr piTrackArray, vm::ptr puiWorkMemByte) { cellAtracMulti.warning("cellAtracMultiSetDataAndGetMemSize(pHandle=*0x%x, pucBufferAddr=*0x%x, uiReadByte=0x%x, uiBufferByte=0x%x, uiOutputChNum=%d, piTrackArray=*0x%x, puiWorkMemByte=*0x%x)", @@ -202,7 +203,7 @@ s32 cellAtracMultiGetInternalErrorInfo(vm::ptr pHandle, vm return CELL_OK; } -Module<> cellAtracMulti("cellAtrac", []() +DECLARE(ppu_module_manager::cellAtracMulti)("cellAtracMulti", []() { REG_FUNC(cellAtracMulti, cellAtracMultiSetDataAndGetMemSize); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAtracMulti.h b/rpcs3/Emu/Cell/Modules/cellAtracMulti.h similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellAtracMulti.h rename to rpcs3/Emu/Cell/Modules/cellAtracMulti.h index d2807ae34c..51d5b7d889 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAtracMulti.h +++ b/rpcs3/Emu/Cell/Modules/cellAtracMulti.h @@ -58,5 +58,3 @@ struct CellAtracMultiExtRes vm::ptr pSpurs; u8 priority[8]; }; - -extern Module<> cellAtracMulti; diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.cpp b/rpcs3/Emu/Cell/Modules/cellAudio.cpp new file mode 100644 index 0000000000..d5239f2557 --- /dev/null +++ b/rpcs3/Emu/Cell/Modules/cellAudio.cpp @@ -0,0 +1,956 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/IdManager.h" +#include "Emu/Cell/PPUModule.h" + +#include "Emu/Cell/lv2/sys_event.h" +#include "Emu/Audio/AudioDumper.h" +#include "Emu/Audio/AudioThread.h" +#include "cellAudio.h" + +LOG_CHANNEL(cellAudio); + +cfg::bool_entry g_cfg_audio_dump_to_file(cfg::root.audio, "Dump to file"); +cfg::bool_entry g_cfg_audio_convert_to_u16(cfg::root.audio, "Convert to 16 bit"); + +void audio_config::on_task() +{ + for (u32 i = 0; i < AUDIO_PORT_COUNT; i++) + { + ports[i].number = i; + ports[i].addr = m_buffer + AUDIO_PORT_OFFSET * i; + ports[i].index = m_indexes + i; + } + + AudioDumper m_dump(g_cfg_audio_dump_to_file ? 2 : 0); // Init AudioDumper for 2 channels if enabled + + float buf2ch[2 * BUFFER_SIZE]{}; // intermediate buffer for 2 channels + float buf8ch[8 * BUFFER_SIZE]{}; // intermediate buffer for 8 channels + + static const size_t out_buffer_size = 8 * BUFFER_SIZE; // output buffer for 8 channels + + std::unique_ptr out_buffer[BUFFER_NUM]; + + for (u32 i = 0; i < BUFFER_NUM; i++) + { + out_buffer[i].reset(new float[out_buffer_size] {}); + } + + const auto audio = Emu.GetCallbacks().get_audio(); + audio->Open(buf8ch, out_buffer_size * (g_cfg_audio_convert_to_u16 ? 2 : 4)); + + while (fxm::check() && !Emu.IsStopped()) + { + if (Emu.IsPaused()) + { + std::this_thread::sleep_for(1ms); // hack + continue; + } + + const u64 stamp0 = get_system_time(); + + const u64 time_pos = stamp0 - start_time - Emu.GetPauseTime(); + + // TODO: send beforemix event (in ~2,6 ms before mixing) + + // precise time of sleeping: 5,(3) ms (or 256/48000 sec) + const u64 expected_time = m_counter * AUDIO_SAMPLES * 1000000 / 48000; + if (expected_time >= time_pos) + { + std::this_thread::sleep_for(1ms); // hack + continue; + } + + m_counter++; + + const u32 out_pos = m_counter % BUFFER_NUM; + + bool first_mix = true; + + // mixing: + for (auto& port : ports) + { + if (port.state != audio_port_state::started) continue; + + const u32 block_size = port.channel * AUDIO_SAMPLES; + const u32 position = port.tag % port.block; // old value + const u32 buf_addr = port.addr.addr() + position * block_size * sizeof(float); + + auto buf = vm::_ptr(buf_addr); + + static const float k = 1.0f; // may be 1.0f + const float& m = port.level; + + auto step_volume = [](audio_port& port) // part of cellAudioSetPortLevel functionality + { + const auto param = port.level_set.load(); + + if (param.inc != 0.0f) + { + port.level += param.inc; + const bool dec = param.inc < 0.0f; + + if ((!dec && param.value - port.level <= 0.0f) || (dec && param.value - port.level >= 0.0f)) + { + port.level = param.value; + port.level_set.compare_and_swap(param, { param.value, 0.0f }); + } + } + }; + + if (port.channel == 2) + { + if (first_mix) + { + for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 2) + { + step_volume(port); + + // reverse byte order + const float left = buf[i + 0] * m; + const float right = buf[i + 1] * m; + + buf2ch[i + 0] = left; + buf2ch[i + 1] = right; + + buf8ch[i * 4 + 0] = left; + buf8ch[i * 4 + 1] = right; + buf8ch[i * 4 + 2] = 0.0f; + buf8ch[i * 4 + 3] = 0.0f; + buf8ch[i * 4 + 4] = 0.0f; + buf8ch[i * 4 + 5] = 0.0f; + buf8ch[i * 4 + 6] = 0.0f; + buf8ch[i * 4 + 7] = 0.0f; + } + first_mix = false; + } + else + { + for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 2) + { + step_volume(port); + + const float left = buf[i + 0] * m; + const float right = buf[i + 1] * m; + + buf2ch[i + 0] += left; + buf2ch[i + 1] += right; + + buf8ch[i * 4 + 0] += left; + buf8ch[i * 4 + 1] += right; + } + } + } + else if (port.channel == 8) + { + if (first_mix) + { + for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 2) + { + step_volume(port); + + const float left = buf[i * 4 + 0] * m; + const float right = buf[i * 4 + 1] * m; + const float center = buf[i * 4 + 2] * m; + const float low_freq = buf[i * 4 + 3] * m; + const float rear_left = buf[i * 4 + 4] * m; + const float rear_right = buf[i * 4 + 5] * m; + const float side_left = buf[i * 4 + 6] * m; + const float side_right = buf[i * 4 + 7] * m; + + const float mid = (center + low_freq) * 0.708f; + buf2ch[i + 0] = (left + rear_left + side_left + mid) * k; + buf2ch[i + 1] = (right + rear_right + side_right + mid) * k; + + buf8ch[i * 4 + 0] = left; + buf8ch[i * 4 + 1] = right; + buf8ch[i * 4 + 2] = center; + buf8ch[i * 4 + 3] = low_freq; + buf8ch[i * 4 + 4] = rear_left; + buf8ch[i * 4 + 5] = rear_right; + buf8ch[i * 4 + 6] = side_left; + buf8ch[i * 4 + 7] = side_right; + } + first_mix = false; + } + else + { + for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 2) + { + step_volume(port); + + const float left = buf[i * 4 + 0] * m; + const float right = buf[i * 4 + 1] * m; + const float center = buf[i * 4 + 2] * m; + const float low_freq = buf[i * 4 + 3] * m; + const float rear_left = buf[i * 4 + 4] * m; + const float rear_right = buf[i * 4 + 5] * m; + const float side_left = buf[i * 4 + 6] * m; + const float side_right = buf[i * 4 + 7] * m; + + const float mid = (center + low_freq) * 0.708f; + buf2ch[i + 0] += (left + rear_left + side_left + mid) * k; + buf2ch[i + 1] += (right + rear_right + side_right + mid) * k; + + buf8ch[i * 4 + 0] += left; + buf8ch[i * 4 + 1] += right; + buf8ch[i * 4 + 2] += center; + buf8ch[i * 4 + 3] += low_freq; + buf8ch[i * 4 + 4] += rear_left; + buf8ch[i * 4 + 5] += rear_right; + buf8ch[i * 4 + 6] += side_left; + buf8ch[i * 4 + 7] += side_right; + } + } + } + else + { + throw EXCEPTION("Unknown channel count (port=%u, channel=%d)", port.number, port.channel); + } + + memset(buf, 0, block_size * sizeof(float)); + } + + + if (!first_mix) + { + // copy output data (2 ch) + //for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i++) + //{ + // out_buffer[out_pos][i] = buf2ch[i]; + //} + + // copy output data (8 ch) + for (u32 i = 0; i < (sizeof(buf8ch) / sizeof(float)); i++) + { + out_buffer[out_pos][i] = buf8ch[i]; + } + } + + const u64 stamp1 = get_system_time(); + + if (first_mix) + { + memset(out_buffer[out_pos].get(), 0, out_buffer_size * sizeof(float)); + } + + if (g_cfg_audio_convert_to_u16) + { + // convert the data from float to u16 with clipping: + // 2x MULPS + // 2x MAXPS (optional) + // 2x MINPS (optional) + // 2x CVTPS2DQ (converts float to s32) + // PACKSSDW (converts s32 to s16 with signed saturation) + + u16 buf_u16[out_buffer_size]; + for (size_t i = 0; i < out_buffer_size; i += 8) + { + const auto scale = _mm_set1_ps(0x8000); + (__m128i&)(buf_u16[i]) = _mm_packs_epi32( + _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(out_buffer[out_pos].get() + i), scale)), + _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(out_buffer[out_pos].get() + i + 4), scale))); + } + + audio->AddData(buf_u16, out_buffer_size * sizeof(u16)); + } + else + { + audio->AddData(out_buffer[out_pos].get(), out_buffer_size * sizeof(float)); + } + + const u64 stamp2 = get_system_time(); + + { + // update indices: + + for (u32 i = 0; i < AUDIO_PORT_COUNT; i++) + { + audio_port& port = ports[i]; + + if (port.state != audio_port_state::started) continue; + + u32 position = port.tag % port.block; // old value + port.counter = m_counter; + port.tag++; // absolute index of block that will be read + m_indexes[i] = (position + 1) % port.block; // write new value + } + + // send aftermix event (normal audio event) + + LV2_LOCK; + + std::lock_guard lock(mutex); + + for (u64 key : keys) + { + if (auto&& queue = lv2_event_queue_t::find(key)) + { + if (queue->events() < queue->size) + queue->push(lv2_lock, 0, 0, 0, 0); // TODO: check arguments + } + } + } + + const u64 stamp3 = get_system_time(); + + switch (m_dump.GetCh()) + { + case 2: m_dump.WriteData(&buf2ch, sizeof(buf2ch)); break; // write file data (2 ch) + case 8: m_dump.WriteData(&buf8ch, sizeof(buf8ch)); break; // write file data (8 ch) + } + + cellAudio.trace("Audio perf: start=%d (access=%d, AddData=%d, events=%d, dump=%d)", + time_pos, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3); + } +} + +s32 cellAudioInit() +{ + cellAudio.warning("cellAudioInit()"); + + // Start audio thread + const auto g_audio = fxm::make(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_ALREADY_INIT; + } + + return CELL_OK; +} + +s32 cellAudioQuit() +{ + cellAudio.warning("cellAudioQuit()"); + + // Stop audio thread + const auto g_audio = fxm::withdraw(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + return CELL_OK; +} + +s32 cellAudioPortOpen(vm::ptr audioParam, vm::ptr portNum) +{ + cellAudio.warning("cellAudioPortOpen(audioParam=*0x%x, portNum=*0x%x)", audioParam, portNum); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (!audioParam || !portNum) + { + return CELL_AUDIO_ERROR_PARAM; + } + + const u64 channel = audioParam->nChannel; + const u64 block = audioParam->nBlock; + const u64 attr = audioParam->attr; + + // check attributes + if (channel != CELL_AUDIO_PORT_2CH && + channel != CELL_AUDIO_PORT_8CH && + channel) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (block != CELL_AUDIO_BLOCK_8 && + block != CELL_AUDIO_BLOCK_16 && + block != 2 && + block != 4 && + block != 32) + { + return CELL_AUDIO_ERROR_PARAM; + } + + // list unsupported flags + if (attr & CELL_AUDIO_PORTATTR_BGM) + { + cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_BGM"); + } + if (attr & CELL_AUDIO_PORTATTR_OUT_SECONDARY) + { + cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_SECONDARY"); + } + if (attr & CELL_AUDIO_PORTATTR_OUT_PERSONAL_0) + { + cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_PERSONAL_0"); + } + if (attr & CELL_AUDIO_PORTATTR_OUT_PERSONAL_1) + { + cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_PERSONAL_1"); + } + if (attr & CELL_AUDIO_PORTATTR_OUT_PERSONAL_2) + { + cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_PERSONAL_2"); + } + if (attr & CELL_AUDIO_PORTATTR_OUT_PERSONAL_3) + { + cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_PERSONAL_3"); + } + if (attr & CELL_AUDIO_PORTATTR_OUT_NO_ROUTE) + { + cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_NO_ROUTE"); + } + if (attr & 0xFFFFFFFFF0EFEFEEULL) + { + cellAudio.todo("cellAudioPortOpen(): unknown attributes (0x%llx)", attr); + } + + // Open audio port + const auto port = g_audio->open_port(); + + if (!port) + { + return CELL_AUDIO_ERROR_PORT_FULL; + } + + port->channel = ::narrow(channel); + port->block = ::narrow(block); + port->attr = attr; + port->size = ::narrow(channel * block * AUDIO_SAMPLES * sizeof(f32)); + port->tag = 0; + + if (attr & CELL_AUDIO_PORTATTR_INITLEVEL) + { + port->level = audioParam->level; + } + else + { + port->level = 1.0f; + } + + port->level_set.store({ port->level, 0.0f }); + + *portNum = port->number; + return CELL_OK; +} + +s32 cellAudioGetPortConfig(u32 portNum, vm::ptr portConfig) +{ + cellAudio.warning("cellAudioGetPortConfig(portNum=%d, portConfig=*0x%x)", portNum, portConfig); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (!portConfig || portNum >= AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + audio_port& port = g_audio->ports[portNum]; + + portConfig->readIndexAddr = port.index; + + switch (auto state = port.state.load()) + { + case audio_port_state::closed: portConfig->status = CELL_AUDIO_STATUS_CLOSE; break; + case audio_port_state::opened: portConfig->status = CELL_AUDIO_STATUS_READY; break; + case audio_port_state::started: portConfig->status = CELL_AUDIO_STATUS_RUN; break; + default: throw fmt::exception("Invalid port state (%d: %d)", portNum, state); + } + + portConfig->nChannel = port.channel; + portConfig->nBlock = port.block; + portConfig->portSize = port.size; + portConfig->portAddr = port.addr.addr(); + return CELL_OK; +} + +s32 cellAudioPortStart(u32 portNum) +{ + cellAudio.warning("cellAudioPortStart(portNum=%d)", portNum); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (portNum >= AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + switch (auto state = g_audio->ports[portNum].state.compare_and_swap(audio_port_state::opened, audio_port_state::started)) + { + case audio_port_state::closed: return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + case audio_port_state::started: return CELL_AUDIO_ERROR_PORT_ALREADY_RUN; + case audio_port_state::opened: return CELL_OK; + default: throw fmt::exception("Invalid port state (%d: %d)", portNum, state); + } +} + +s32 cellAudioPortClose(u32 portNum) +{ + cellAudio.warning("cellAudioPortClose(portNum=%d)", portNum); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (portNum >= AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + switch (auto 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; + default: throw fmt::exception("Invalid port state (%d: %d)", portNum, state); + } +} + +s32 cellAudioPortStop(u32 portNum) +{ + cellAudio.warning("cellAudioPortStop(portNum=%d)", portNum); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (portNum >= AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + switch (auto state = g_audio->ports[portNum].state.compare_and_swap(audio_port_state::started, audio_port_state::opened)) + { + case audio_port_state::closed: return CELL_AUDIO_ERROR_PORT_NOT_RUN; + case audio_port_state::started: return CELL_OK; + case audio_port_state::opened: return CELL_AUDIO_ERROR_PORT_NOT_RUN; + default: throw fmt::exception("Invalid port state (%d: %d)", portNum, state); + } +} + +s32 cellAudioGetPortTimestamp(u32 portNum, u64 tag, vm::ptr stamp) +{ + cellAudio.trace("cellAudioGetPortTimestamp(portNum=%d, tag=0x%llx, stamp=*0x%x)", portNum, tag, stamp); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (portNum >= AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + audio_port& port = g_audio->ports[portNum]; + + if (port.state == audio_port_state::closed) + { + return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + } + + // TODO: check tag (CELL_AUDIO_ERROR_TAG_NOT_FOUND error) + + *stamp = g_audio->start_time + Emu.GetPauseTime() + (port.counter + (tag - port.tag)) * 256000000 / 48000; + + return CELL_OK; +} + +s32 cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr tag) +{ + cellAudio.trace("cellAudioGetPortBlockTag(portNum=%d, blockNo=0x%llx, tag=*0x%x)", portNum, blockNo, tag); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (portNum >= AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + audio_port& port = g_audio->ports[portNum]; + + if (port.state == audio_port_state::closed) + { + return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + } + + if (blockNo >= port.block) + { + return CELL_AUDIO_ERROR_PARAM; + } + + u64 tag_base = port.tag; + if (tag_base % port.block > blockNo) + { + tag_base &= ~(port.block - 1); + tag_base += port.block; + } + else + { + tag_base &= ~(port.block - 1); + } + *tag = tag_base + blockNo; + + return CELL_OK; +} + +s32 cellAudioSetPortLevel(u32 portNum, float level) +{ + cellAudio.trace("cellAudioSetPortLevel(portNum=%d, level=%f)", portNum, level); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (portNum >= AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + audio_port& port = g_audio->ports[portNum]; + + if (port.state == audio_port_state::closed) + { + return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + } + + if (level >= 0.0f) + { + port.level_set.exchange({ level, (port.level - level) / 624.0f }); + } + else + { + cellAudio.todo("cellAudioSetPortLevel(%d): negative level value (%f)", portNum, level); + } + + return CELL_OK; +} + +s32 cellAudioCreateNotifyEventQueue(vm::ptr id, vm::ptr key) +{ + cellAudio.warning("cellAudioCreateNotifyEventQueue(id=*0x%x, key=*0x%x)", id, key); + + for (u64 k = 0; k < 100; k++) + { + const u64 key_value = 0x80004d494f323221ull + k; + + // Create an event queue "bruteforcing" an available key + if (auto&& queue = lv2_event_queue_t::make(SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0, key_value, 32)) + { + *id = queue->id; + *key = key_value; + + return CELL_OK; + } + } + + return CELL_AUDIO_ERROR_EVENT_QUEUE; +} + +s32 cellAudioCreateNotifyEventQueueEx(vm::ptr id, vm::ptr key, u32 iFlags) +{ + cellAudio.todo("cellAudioCreateNotifyEventQueueEx(id=*0x%x, key=*0x%x, iFlags=0x%x)", id, key, iFlags); + + if (iFlags & ~CELL_AUDIO_CREATEEVENTFLAG_SPU) + { + return CELL_AUDIO_ERROR_PARAM; + } + + // TODO + + return CELL_AUDIO_ERROR_EVENT_QUEUE; +} + +s32 cellAudioSetNotifyEventQueue(u64 key) +{ + cellAudio.warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + std::lock_guard lock(g_audio->mutex); + + for (auto k : g_audio->keys) // check for duplicates + { + if (k == key) + { + return CELL_AUDIO_ERROR_TRANS_EVENT; + } + } + + g_audio->keys.emplace_back(key); + + return CELL_OK; +} + +s32 cellAudioSetNotifyEventQueueEx(u64 key, u32 iFlags) +{ + cellAudio.todo("cellAudioSetNotifyEventQueueEx(key=0x%llx, iFlags=0x%x)", key, iFlags); + + // TODO + + return CELL_OK; +} + +s32 cellAudioRemoveNotifyEventQueue(u64 key) +{ + cellAudio.warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + std::lock_guard lock(g_audio->mutex); + + for (auto i = g_audio->keys.begin(); i != g_audio->keys.end(); i++) + { + if (*i == key) + { + g_audio->keys.erase(i); + + return CELL_OK; + } + } + + return CELL_AUDIO_ERROR_TRANS_EVENT; +} + +s32 cellAudioRemoveNotifyEventQueueEx(u64 key, u32 iFlags) +{ + cellAudio.todo("cellAudioRemoveNotifyEventQueueEx(key=0x%llx, iFlags=0x%x)", key, iFlags); + + // TODO + + return CELL_OK; +} + +s32 cellAudioAddData(u32 portNum, vm::ptr src, u32 samples, float volume) +{ + cellAudio.trace("cellAudioAddData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned()) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (samples != 256) + { + // despite the docs, seems that only fixed value is supported + cellAudio.error("cellAudioAddData(): invalid samples value (%d)", samples); + return CELL_AUDIO_ERROR_PARAM; + } + + const audio_port& port = g_audio->ports[portNum]; + + const auto dst = vm::ptr::make(port.addr.addr() + u32(port.tag % port.block) * port.channel * 256 * SIZE_32(float)); + + for (u32 i = 0; i < samples * port.channel; i++) + { + dst[i] += src[i] * volume; // mix all channels + } + + return CELL_OK; +} + +s32 cellAudioAdd2chData(u32 portNum, vm::ptr src, u32 samples, float volume) +{ + cellAudio.trace("cellAudioAdd2chData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned()) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (samples != 256) + { + // despite the docs, seems that only fixed value is supported + cellAudio.error("cellAudioAdd2chData(): invalid samples value (%d)", samples); + return CELL_AUDIO_ERROR_PARAM; + } + + const audio_port& port = g_audio->ports[portNum]; + + const auto dst = vm::ptr::make(port.addr.addr() + s32(port.tag % port.block) * port.channel * 256 * SIZE_32(float)); + + if (port.channel == 2) + { + cellAudio.error("cellAudioAdd2chData(portNum=%d): port.channel = 2", portNum); + } + else if (port.channel == 6) + { + for (u32 i = 0; i < samples; i++) + { + dst[i * 6 + 0] += src[i * 2 + 0] * volume; // mix L ch + dst[i * 6 + 1] += src[i * 2 + 1] * volume; // mix R ch + //dst[i * 6 + 2] += 0.0f; // center + //dst[i * 6 + 3] += 0.0f; // LFE + //dst[i * 6 + 4] += 0.0f; // rear L + //dst[i * 6 + 5] += 0.0f; // rear R + } + } + else if (port.channel == 8) + { + for (u32 i = 0; i < samples; i++) + { + dst[i * 8 + 0] += src[i * 2 + 0] * volume; // mix L ch + dst[i * 8 + 1] += src[i * 2 + 1] * volume; // mix R ch + //dst[i * 8 + 2] += 0.0f; // center + //dst[i * 8 + 3] += 0.0f; // LFE + //dst[i * 8 + 4] += 0.0f; // rear L + //dst[i * 8 + 5] += 0.0f; // rear R + //dst[i * 8 + 6] += 0.0f; // side L + //dst[i * 8 + 7] += 0.0f; // side R + } + } + else + { + cellAudio.error("cellAudioAdd2chData(portNum=%d): invalid port.channel value (%d)", portNum, port.channel); + } + + return CELL_OK; +} + +s32 cellAudioAdd6chData(u32 portNum, vm::ptr src, float volume) +{ + cellAudio.trace("cellAudioAdd6chData(portNum=%d, src=*0x%x, volume=%f)", portNum, src, volume); + + const auto g_audio = fxm::get(); + + if (!g_audio) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned()) + { + return CELL_AUDIO_ERROR_PARAM; + } + + const audio_port& port = g_audio->ports[portNum]; + + const auto dst = vm::ptr::make(port.addr.addr() + s32(port.tag % port.block) * port.channel * 256 * SIZE_32(float)); + + if (port.channel == 2 || port.channel == 6) + { + cellAudio.error("cellAudioAdd2chData(portNum=%d): port.channel = %d", portNum, port.channel); + } + else if (port.channel == 8) + { + for (u32 i = 0; i < 256; i++) + { + dst[i * 8 + 0] += src[i * 6 + 0] * volume; // mix L ch + dst[i * 8 + 1] += src[i * 6 + 1] * volume; // mix R ch + dst[i * 8 + 2] += src[i * 6 + 2] * volume; // mix center + dst[i * 8 + 3] += src[i * 6 + 3] * volume; // mix LFE + dst[i * 8 + 4] += src[i * 6 + 4] * volume; // mix rear L + dst[i * 8 + 5] += src[i * 6 + 5] * volume; // mix rear R + //dst[i * 8 + 6] += 0.0f; // side L + //dst[i * 8 + 7] += 0.0f; // side R + } + } + else + { + cellAudio.error("cellAudioAdd6chData(portNum=%d): invalid port.channel value (%d)", portNum, port.channel); + } + + return CELL_OK; +} + +s32 cellAudioMiscSetAccessoryVolume(u32 devNum, float volume) +{ + cellAudio.todo("cellAudioMiscSetAccessoryVolume(devNum=%d, volume=%f)", devNum, volume); + return CELL_OK; +} + +s32 cellAudioSendAck(u64 data3) +{ + cellAudio.todo("cellAudioSendAck(data3=0x%llx)", data3); + return CELL_OK; +} + +s32 cellAudioSetPersonalDevice(s32 iPersonalStream, s32 iDevice) +{ + cellAudio.todo("cellAudioSetPersonalDevice(iPersonalStream=%d, iDevice=%d)", iPersonalStream, iDevice); + return CELL_OK; +} + +s32 cellAudioUnsetPersonalDevice(s32 iPersonalStream) +{ + cellAudio.todo("cellAudioUnsetPersonalDevice(iPersonalStream=%d)", iPersonalStream); + return CELL_OK; +} + +DECLARE(ppu_module_manager::cellAudio)("cellAudio", []() +{ + REG_FUNC(cellAudio, cellAudioInit); + REG_FUNC(cellAudio, cellAudioPortClose); + REG_FUNC(cellAudio, cellAudioPortStop); + REG_FUNC(cellAudio, cellAudioGetPortConfig); + REG_FUNC(cellAudio, cellAudioPortStart); + REG_FUNC(cellAudio, cellAudioQuit); + REG_FUNC(cellAudio, cellAudioPortOpen); + REG_FUNC(cellAudio, cellAudioSetPortLevel); + REG_FUNC(cellAudio, cellAudioCreateNotifyEventQueue); + REG_FUNC(cellAudio, cellAudioCreateNotifyEventQueueEx); + REG_FUNC(cellAudio, cellAudioMiscSetAccessoryVolume); + REG_FUNC(cellAudio, cellAudioSetNotifyEventQueue); + REG_FUNC(cellAudio, cellAudioSetNotifyEventQueueEx); + REG_FUNC(cellAudio, cellAudioGetPortTimestamp); + REG_FUNC(cellAudio, cellAudioAdd2chData); + REG_FUNC(cellAudio, cellAudioAdd6chData); + REG_FUNC(cellAudio, cellAudioAddData); + REG_FUNC(cellAudio, cellAudioGetPortBlockTag); + REG_FUNC(cellAudio, cellAudioRemoveNotifyEventQueue); + REG_FUNC(cellAudio, cellAudioRemoveNotifyEventQueueEx); + REG_FUNC(cellAudio, cellAudioSendAck); + REG_FUNC(cellAudio, cellAudioSetPersonalDevice); + REG_FUNC(cellAudio, cellAudioUnsetPersonalDevice); +}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.h b/rpcs3/Emu/Cell/Modules/cellAudio.h similarity index 76% rename from rpcs3/Emu/SysCalls/Modules/cellAudio.h rename to rpcs3/Emu/Cell/Modules/cellAudio.h index dd184d6e2a..e64a65f9ca 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.h +++ b/rpcs3/Emu/Cell/Modules/cellAudio.h @@ -1,5 +1,7 @@ #pragma once +#include "Utilities/Thread.h" + namespace vm { using namespace ps3; } // Error codes @@ -66,7 +68,7 @@ struct CellAudioPortParam struct CellAudioPortConfig { - be_t readIndexAddr; + vm::bptr readIndexAddr; be_t status; be_t nChannel; be_t nBlock; @@ -83,36 +85,31 @@ enum : u32 AUDIO_SAMPLES = CELL_AUDIO_BLOCK_SAMPLES, }; -enum AudioState : u32 +extern u64 get_system_time(); + +enum class audio_port_state : u32 { - AUDIO_STATE_NOT_INITIALIZED, - AUDIO_STATE_INITIALIZED, - AUDIO_STATE_FINALIZED, + closed, + opened, + started, }; -enum AudioPortState : u32 +struct audio_port { - AUDIO_PORT_STATE_CLOSED, - AUDIO_PORT_STATE_OPENED, - AUDIO_PORT_STATE_STARTED, -}; + atomic_t state{ audio_port_state::closed }; -struct AudioPortConfig -{ - atomic_t state; - - std::mutex mutex; + u32 number; + vm::ptr addr{}; + vm::ptr index{}; u32 channel; u32 block; u64 attr; u64 tag; u64 counter; // copy of global counter - u32 addr; - u32 read_index_addr; u32 size; - struct level_set_t + struct alignas(8) level_set_t { float value; float inc; @@ -122,31 +119,36 @@ struct AudioPortConfig atomic_t level_set; }; -struct AudioConfig final // custom structure +class audio_config final : public named_thread { - atomic_t state; + void on_task() override; - std::mutex mutex; + std::string get_name() const override { return "Audio Thread"; } + + vm::var> m_buffer{ AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT }; + vm::var> m_indexes{ AUDIO_PORT_COUNT }; + + u64 m_counter{}; + +public: + const u64 start_time = get_system_time(); + + std::array ports; - AudioPortConfig ports[AUDIO_PORT_COUNT]; - u32 buffer; // 1 MB memory for audio ports - u32 indexes; // current block indexes and other info - u64 counter; - u64 start_time; std::vector keys; - u32 open_port() + ~audio_config() noexcept = default; + + audio_port* open_port() { for (u32 i = 0; i < AUDIO_PORT_COUNT; i++) { - if (ports[i].state.compare_and_swap_test(AUDIO_PORT_STATE_CLOSED, AUDIO_PORT_STATE_OPENED)) + if (ports[i].state.compare_and_swap_test(audio_port_state::closed, audio_port_state::opened)) { - return i; + return &ports[i]; } } - return ~0; + return nullptr; } }; - -extern AudioConfig g_audio; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudioIn.h b/rpcs3/Emu/Cell/Modules/cellAudioIn.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellAudioIn.h rename to rpcs3/Emu/Cell/Modules/cellAudioIn.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudioOut.cpp b/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellAudioOut.cpp rename to rpcs3/Emu/Cell/Modules/cellAudioOut.cpp index 0734bee4b8..d294bbd776 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudioOut.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp @@ -1,10 +1,9 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellAudioOut.h" -extern Module<> cellSysutil; +extern _log::channel cellSysutil; s32 cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudioOut.h b/rpcs3/Emu/Cell/Modules/cellAudioOut.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellAudioOut.h rename to rpcs3/Emu/Cell/Modules/cellAudioOut.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp b/rpcs3/Emu/Cell/Modules/cellAvconfExt.cpp similarity index 63% rename from rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp rename to rpcs3/Emu/Cell/Modules/cellAvconfExt.cpp index c34df3052d..7a005dc34a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAvconfExt.cpp @@ -1,15 +1,14 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" -#include "Emu/state.h" +#include "Emu/System.h" +#include "Emu/Cell/PPUModule.h" #include "cellAudioIn.h" #include "cellAudioOut.h" #include "cellVideoOut.h" -extern Module<> cellAvconfExt; +LOG_CHANNEL(cellAvconfExt); -f32 g_gamma; +vm::gvar g_gamma; // TODO s32 cellAudioOutUnregisterDevice() { @@ -50,7 +49,7 @@ s32 cellVideoOutGetGamma(u32 videoOut, vm::ptr gamma) return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; } - *gamma = g_gamma; + *gamma = *g_gamma; return CELL_OK; } @@ -79,7 +78,7 @@ s32 cellVideoOutSetGamma(u32 videoOut, f32 gamma) return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER; } - g_gamma = gamma; + *g_gamma = gamma; return CELL_OK; } @@ -127,34 +126,32 @@ s32 cellVideoOutGetScreenSize(u32 videoOut, vm::ptr screenSize) // float diagonal = roundf(sqrtf((powf(wxGetDisplaySizeMM().GetWidth(), 2) + powf(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393f); #endif - if (rpcs3::config.rsx._3dtv.value()) - { - *screenSize = 24.0f; - return CELL_OK; - } - return CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET; } -Module<> cellAvconfExt("cellAvconfExt", []() +DECLARE(ppu_module_manager::cellAvconfExt)("cellSysutilAvconfExt", []() { - g_gamma = 1.0f; + REG_VNID(cellSysutilAvconfExt, 0x00000000, g_gamma, [] + { + // Test + *g_gamma = 1.0f; + }); - REG_FUNC(cellAvconfExt, cellAudioOutUnregisterDevice); - REG_FUNC(cellAvconfExt, cellAudioOutGetDeviceInfo2); - REG_FUNC(cellAvconfExt, cellVideoOutSetXVColor); - REG_FUNC(cellAvconfExt, cellVideoOutSetupDisplay); - REG_FUNC(cellAvconfExt, cellAudioInGetDeviceInfo); - REG_FUNC(cellAvconfExt, cellVideoOutConvertCursorColor); - REG_FUNC(cellAvconfExt, cellVideoOutGetGamma); - REG_FUNC(cellAvconfExt, cellAudioInGetAvailableDeviceInfo); - REG_FUNC(cellAvconfExt, cellAudioOutGetAvailableDeviceInfo); - REG_FUNC(cellAvconfExt, cellVideoOutSetGamma); - REG_FUNC(cellAvconfExt, cellAudioOutRegisterDevice); - REG_FUNC(cellAvconfExt, cellAudioOutSetDeviceMode); - REG_FUNC(cellAvconfExt, cellAudioInSetDeviceMode); - REG_FUNC(cellAvconfExt, cellAudioInRegisterDevice); - REG_FUNC(cellAvconfExt, cellAudioInUnregisterDevice); - REG_FUNC(cellAvconfExt, cellVideoOutGetScreenSize); + REG_FUNC(cellSysutilAvconfExt, cellAudioOutUnregisterDevice); + REG_FUNC(cellSysutilAvconfExt, cellAudioOutGetDeviceInfo2); + REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetXVColor); + REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetupDisplay); + REG_FUNC(cellSysutilAvconfExt, cellAudioInGetDeviceInfo); + REG_FUNC(cellSysutilAvconfExt, cellVideoOutConvertCursorColor); + REG_FUNC(cellSysutilAvconfExt, cellVideoOutGetGamma); + REG_FUNC(cellSysutilAvconfExt, cellAudioInGetAvailableDeviceInfo); + REG_FUNC(cellSysutilAvconfExt, cellAudioOutGetAvailableDeviceInfo); + REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetGamma); + REG_FUNC(cellSysutilAvconfExt, cellAudioOutRegisterDevice); + REG_FUNC(cellSysutilAvconfExt, cellAudioOutSetDeviceMode); + REG_FUNC(cellSysutilAvconfExt, cellAudioInSetDeviceMode); + REG_FUNC(cellSysutilAvconfExt, cellAudioInRegisterDevice); + REG_FUNC(cellSysutilAvconfExt, cellAudioInUnregisterDevice); + REG_FUNC(cellSysutilAvconfExt, cellVideoOutGetScreenSize); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellBgdl.cpp b/rpcs3/Emu/Cell/Modules/cellBgdl.cpp similarity index 69% rename from rpcs3/Emu/SysCalls/Modules/cellBgdl.cpp rename to rpcs3/Emu/Cell/Modules/cellBgdl.cpp index b57d7befa1..b83c0fa791 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellBgdl.cpp +++ b/rpcs3/Emu/Cell/Modules/cellBgdl.cpp @@ -1,9 +1,8 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellBGDL; +LOG_CHANNEL(cellBGDL); // Return Codes enum @@ -40,10 +39,10 @@ s32 cellBGDLGetMode() return CELL_OK; } -Module<> cellBGDL("cellBGDL", []() +DECLARE(ppu_module_manager::cellBGDL)("cellBGDLUtility", []() { - REG_FUNC(cellBGDL, cellBGDLGetInfo); - REG_FUNC(cellBGDL, cellBGDLGetInfo2); - REG_FUNC(cellBGDL, cellBGDLSetMode); - REG_FUNC(cellBGDL, cellBGDLGetMode); + REG_FUNC(cellBGDLUtility, cellBGDLGetInfo); + REG_FUNC(cellBGDLUtility, cellBGDLGetInfo2); + REG_FUNC(cellBGDLUtility, cellBGDLSetMode); + REG_FUNC(cellBGDLUtility, cellBGDLGetMode); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp b/rpcs3/Emu/Cell/Modules/cellCamera.cpp similarity index 92% rename from rpcs3/Emu/SysCalls/Modules/cellCamera.cpp rename to rpcs3/Emu/Cell/Modules/cellCamera.cpp index e0c194ebac..6a2c491a43 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp +++ b/rpcs3/Emu/Cell/Modules/cellCamera.cpp @@ -1,13 +1,25 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/IdManager.h" #include "Emu/System.h" -#include "Emu/state.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellCamera.h" -extern Module<> cellCamera; +LOG_CHANNEL(cellCamera); + +cfg::map_entry g_cfg_camera(cfg::root.io, "Camera", +{ + { "Null", false }, + { "Fake", true }, +}); + +cfg::map_entry g_cfg_camera_type(cfg::root.io, "Camera type", +{ + { "Unknown", CELL_CAMERA_TYPE_UNKNOWN }, + { "EyeToy", CELL_CAMERA_EYETOY }, + { "PS Eye", CELL_CAMERA_EYETOY2 }, + { "UVC 1.1", CELL_CAMERA_USBVIDEOCLASS }, +}); static const char* get_camera_attr_name(s32 value) { @@ -82,7 +94,7 @@ s32 cellCameraInit() { cellCamera.warning("cellCameraInit()"); - if (rpcs3::config.io.camera.value() == io_camera_state::null) + if (!g_cfg_camera.get()) { return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND; } @@ -94,9 +106,9 @@ s32 cellCameraInit() return CELL_CAMERA_ERROR_ALREADY_INIT; } - switch (rpcs3::config.io.camera_type.value()) + switch (g_cfg_camera_type.get()) { - case io_camera_type::eye_toy: + case CELL_CAMERA_EYETOY: { camera->attr[CELL_CAMERA_SATURATION] = { 164 }; camera->attr[CELL_CAMERA_BRIGHTNESS] = { 96 }; @@ -115,7 +127,7 @@ s32 cellCameraInit() } break; - case io_camera_type::play_station_eye: + case CELL_CAMERA_EYETOY2: { camera->attr[CELL_CAMERA_SATURATION] = { 64 }; camera->attr[CELL_CAMERA_BRIGHTNESS] = { 8 }; @@ -191,14 +203,7 @@ s32 cellCameraGetType(s32 dev_num, vm::ptr type) return CELL_CAMERA_ERROR_NOT_INIT; } - switch (rpcs3::config.io.camera_type.value()) - { - case io_camera_type::eye_toy: *type = CELL_CAMERA_EYETOY; break; - case io_camera_type::play_station_eye: *type = CELL_CAMERA_EYETOY2; break; - case io_camera_type::usb_video_class_1_1: *type = CELL_CAMERA_USBVIDEOCLASS; break; - default: *type = CELL_CAMERA_TYPE_UNKNOWN; break; - } - + *type = g_cfg_camera_type.get(); return CELL_OK; } @@ -212,12 +217,12 @@ s32 cellCameraIsAttached(s32 dev_num) { cellCamera.warning("cellCameraIsAttached(dev_num=%d)", dev_num); - if (rpcs3::config.io.camera.value() == io_camera_state::connected) + if (g_cfg_camera.get()) { return 1; } - return CELL_OK; // CELL_OK means that no camera is attached + return 0; // It's not CELL_OK lol } s32 cellCameraIsOpen(s32 dev_num) @@ -381,7 +386,7 @@ s32 cellCameraRemoveNotifyEventQueue2(u64 key) return CELL_OK; } -Module<> cellCamera("cellCamera", []() +DECLARE(ppu_module_manager::cellCamera)("cellCamera", []() { REG_FUNC(cellCamera, cellCameraInit); REG_FUNC(cellCamera, cellCameraEnd); diff --git a/rpcs3/Emu/SysCalls/Modules/cellCamera.h b/rpcs3/Emu/Cell/Modules/cellCamera.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellCamera.h rename to rpcs3/Emu/Cell/Modules/cellCamera.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellCelp8Enc.cpp b/rpcs3/Emu/Cell/Modules/cellCelp8Enc.cpp similarity index 91% rename from rpcs3/Emu/SysCalls/Modules/cellCelp8Enc.cpp rename to rpcs3/Emu/Cell/Modules/cellCelp8Enc.cpp index b5e29f813a..bb0b24b9ef 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellCelp8Enc.cpp +++ b/rpcs3/Emu/Cell/Modules/cellCelp8Enc.cpp @@ -1,9 +1,8 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellCelp8Enc; +LOG_CHANNEL(cellCelp8Enc); // Return Codes enum @@ -70,7 +69,7 @@ s32 cellCelp8EncGetAu() return CELL_OK; } -Module<> cellCelp8Enc("cellCelp8Enc", []() +DECLARE(ppu_module_manager::cellCelp8Enc)("cellCelp8Enc", []() { REG_FUNC(cellCelp8Enc, cellCelp8EncQueryAttr); REG_FUNC(cellCelp8Enc, cellCelp8EncOpen); diff --git a/rpcs3/Emu/SysCalls/Modules/cellCelpEnc.cpp b/rpcs3/Emu/Cell/Modules/cellCelpEnc.cpp similarity index 91% rename from rpcs3/Emu/SysCalls/Modules/cellCelpEnc.cpp rename to rpcs3/Emu/Cell/Modules/cellCelpEnc.cpp index 2f2dd2c9ef..bb551877bb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellCelpEnc.cpp +++ b/rpcs3/Emu/Cell/Modules/cellCelpEnc.cpp @@ -1,9 +1,8 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellCelpEnc; +LOG_CHANNEL(cellCelpEnc); // Return Codes enum @@ -70,7 +69,7 @@ s32 cellCelpEncGetAu() return CELL_OK; } -Module<> cellCelpEnc("cellCelpEnc", []() +DECLARE(ppu_module_manager::cellCelpEnc)("cellCelpEnc", []() { REG_FUNC(cellCelpEnc, cellCelpEncQueryAttr); REG_FUNC(cellCelpEnc, cellCelpEncOpen); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDaisy.cpp b/rpcs3/Emu/Cell/Modules/cellDaisy.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellDaisy.cpp rename to rpcs3/Emu/Cell/Modules/cellDaisy.cpp index 8556089ea2..bd82c4d31b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDaisy.cpp +++ b/rpcs3/Emu/Cell/Modules/cellDaisy.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellDaisy; +LOG_CHANNEL(cellDaisy); s32 _ZN4cell5Daisy17LFQueue2PushCloseEPNS0_8LFQueue2EPFiPvjE() { @@ -265,7 +264,7 @@ s32 _QN4cell5Daisy22ScatterGatherInterlock7releaseEv() } -Module<> cellDaisy("cellDaisy", []() +DECLARE(ppu_module_manager::cellDaisy)("cellDaisy", []() { REG_FUNC(cellDaisy, _ZN4cell5Daisy17LFQueue2PushCloseEPNS0_8LFQueue2EPFiPvjE); REG_FUNC(cellDaisy, _ZN4cell5Daisy21LFQueue2GetPopPointerEPNS0_8LFQueue2EPij); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/Cell/Modules/cellDmux.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellDmux.cpp rename to rpcs3/Emu/Cell/Modules/cellDmux.cpp index 5a2cbf2135..0c755b197d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/Cell/Modules/cellDmux.cpp @@ -1,13 +1,12 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellPamf.h" #include "cellDmux.h" -extern Module<> cellDmux; +LOG_CHANNEL(cellDmux); PesHeader::PesHeader(DemuxerStream& stream) : pts(CODEC_TS_INVALID) @@ -80,7 +79,6 @@ PesHeader::PesHeader(DemuxerStream& stream) ElementaryStream::ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr cbFunc, u32 cbArg, u32 spec) : dmux(dmux) - , id(idm::get_last_id()) , memAddr(align(addr, 128)) , memSize(size - (addr - memAddr)) , fidMajor(fidMajor) @@ -112,8 +110,7 @@ bool ElementaryStream::is_full(u32 space) u32 first = 0; if (!entries.peek(first, 0, &dmux->is_closed) || !first) { - assert(!"es::is_full() error: entries.Peek() failed"); - return false; + throw std::runtime_error("entries.peek() failed" HERE); } else if (first >= put) { @@ -145,7 +142,7 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra u32 addr; { std::lock_guard lock(m_mutex); - assert(!is_full(size)); + ASSERT(!is_full(size)); if (put + size + 128 > memAddr + memSize) { @@ -185,10 +182,8 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra put_count++; } - if (!entries.push(addr, &dmux->is_closed)) - { - assert(!"es::push_au() error: entries.Push() failed"); - } + + ASSERT(entries.push(addr, &dmux->is_closed)); } void ElementaryStream::push(DemuxerStream& stream, u32 size) @@ -762,8 +757,9 @@ void dmuxOpen(u32 dmux_id) // TODO: call from the constructor dmux.is_finished = true; }; - dmux.dmuxCb->run(); - dmux.dmuxCb->exec(); + dmux.dmuxCb->cpu_init(); + dmux.dmuxCb->state -= cpu_state::stop; + dmux.dmuxCb->safe_notify(); } s32 cellDmuxQueryAttr(vm::cptr type, vm::ptr attr) @@ -872,7 +868,7 @@ s32 cellDmuxClose(u32 handle) std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack } - idm::remove(dmux->dmuxCb->get_id()); + idm::remove(dmux->dmuxCb->id); idm::remove(handle); return CELL_OK; } @@ -1178,7 +1174,7 @@ s32 cellDmuxFlushEs(u32 esHandle) return CELL_OK; } -Module<> cellDmux("cellDmux", []() +DECLARE(ppu_module_manager::cellDmux)("cellDmux", []() { REG_FUNC(cellDmux, cellDmuxQueryAttr); REG_FUNC(cellDmux, cellDmuxQueryAttr2); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/Cell/Modules/cellDmux.h similarity index 99% rename from rpcs3/Emu/SysCalls/Modules/cellDmux.h rename to rpcs3/Emu/Cell/Modules/cellDmux.h index 407cdad56e..3341718e61 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/Cell/Modules/cellDmux.h @@ -405,8 +405,8 @@ public: u32 id; volatile bool is_finished; volatile bool is_closed; - std::atomic is_running; - std::atomic is_working; + atomic_t is_running; + atomic_t is_working; std::shared_ptr dmuxCb; @@ -440,7 +440,7 @@ public: ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr cbFunc, u32 cbArg, u32 spec); Demuxer* dmux; - const u32 id; + const u32 id{}; const u32 memAddr; const u32 memSize; const u32 fidMajor; diff --git a/rpcs3/Emu/SysCalls/Modules/cellFiber.cpp b/rpcs3/Emu/Cell/Modules/cellFiber.cpp similarity index 61% rename from rpcs3/Emu/SysCalls/Modules/cellFiber.cpp rename to rpcs3/Emu/Cell/Modules/cellFiber.cpp index 906b8d5184..ba744dc37a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFiber.cpp +++ b/rpcs3/Emu/Cell/Modules/cellFiber.cpp @@ -1,11 +1,10 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellFiber.h" -extern Module<> cellFiber; +LOG_CHANNEL(cellFiber); s32 _cellFiberPpuInitialize() { @@ -291,59 +290,59 @@ s32 cellFiberPpuUtilWorkerControlInitializeWithAttribute() return CELL_OK; } -Module<> cellFiber("cellFiber", []() +DECLARE(ppu_module_manager::cellFiber)("cellFiber", []() { - REG_FUNC(cellFiber, _cellFiberPpuInitialize, MFF_NO_RETURN); + REG_FUNC(cellFiber, _cellFiberPpuInitialize); - REG_FUNC(cellFiber, _cellFiberPpuSchedulerAttributeInitialize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuInitializeScheduler, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuFinalizeScheduler, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuRunFibers, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuCheckFlags, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuHasRunnableFiber, MFF_NO_RETURN); + REG_FUNC(cellFiber, _cellFiberPpuSchedulerAttributeInitialize); + REG_FUNC(cellFiber, cellFiberPpuInitializeScheduler); + REG_FUNC(cellFiber, cellFiberPpuFinalizeScheduler); + REG_FUNC(cellFiber, cellFiberPpuRunFibers); + REG_FUNC(cellFiber, cellFiberPpuCheckFlags); + REG_FUNC(cellFiber, cellFiberPpuHasRunnableFiber); - REG_FUNC(cellFiber, _cellFiberPpuAttributeInitialize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuCreateFiber, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuExit, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuYield, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuJoinFiber, MFF_NO_RETURN); + REG_FUNC(cellFiber, _cellFiberPpuAttributeInitialize); + REG_FUNC(cellFiber, cellFiberPpuCreateFiber); + REG_FUNC(cellFiber, cellFiberPpuExit); + REG_FUNC(cellFiber, cellFiberPpuYield); + REG_FUNC(cellFiber, cellFiberPpuJoinFiber); REG_FUNC(cellFiber, cellFiberPpuSelf); - REG_FUNC(cellFiber, cellFiberPpuSendSignal, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuWaitSignal, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuWaitFlag, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuGetScheduler, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuSetPriority, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuCheckStackLimit, MFF_NO_RETURN); + REG_FUNC(cellFiber, cellFiberPpuSendSignal); + REG_FUNC(cellFiber, cellFiberPpuWaitSignal); + REG_FUNC(cellFiber, cellFiberPpuWaitFlag); + REG_FUNC(cellFiber, cellFiberPpuGetScheduler); + REG_FUNC(cellFiber, cellFiberPpuSetPriority); + REG_FUNC(cellFiber, cellFiberPpuCheckStackLimit); - REG_FUNC(cellFiber, _cellFiberPpuContextAttributeInitialize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuContextInitialize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuContextFinalize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuContextRun, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuContextSwitch, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuContextSelf, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuContextReturnToThread, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuContextCheckStackLimit, MFF_NO_RETURN); + REG_FUNC(cellFiber, _cellFiberPpuContextAttributeInitialize); + REG_FUNC(cellFiber, cellFiberPpuContextInitialize); + REG_FUNC(cellFiber, cellFiberPpuContextFinalize); + REG_FUNC(cellFiber, cellFiberPpuContextRun); + REG_FUNC(cellFiber, cellFiberPpuContextSwitch); + REG_FUNC(cellFiber, cellFiberPpuContextSelf); + REG_FUNC(cellFiber, cellFiberPpuContextReturnToThread); + REG_FUNC(cellFiber, cellFiberPpuContextCheckStackLimit); - REG_FUNC(cellFiber, cellFiberPpuContextRunScheduler, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuContextEnterScheduler, MFF_NO_RETURN); + REG_FUNC(cellFiber, cellFiberPpuContextRunScheduler); + REG_FUNC(cellFiber, cellFiberPpuContextEnterScheduler); - REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceInitialize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceFinalize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStart, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStop, MFF_NO_RETURN); + REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceInitialize); + REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceFinalize); + REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStart); + REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStop); - REG_FUNC(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlRunFibers, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitialize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSendSignal, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlFinalize, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlWakeup, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlShutdown, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags, MFF_NO_RETURN); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute, MFF_NO_RETURN); + REG_FUNC(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlRunFibers); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitialize); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSendSignal); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlFinalize); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlWakeup); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlShutdown); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags); + REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellFiber.h b/rpcs3/Emu/Cell/Modules/cellFiber.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellFiber.h rename to rpcs3/Emu/Cell/Modules/cellFiber.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellFont.cpp b/rpcs3/Emu/Cell/Modules/cellFont.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellFont.cpp rename to rpcs3/Emu/Cell/Modules/cellFont.cpp index adae60dc89..0d3f10c2a5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFont.cpp +++ b/rpcs3/Emu/Cell/Modules/cellFont.cpp @@ -1,15 +1,14 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/System.h" +#include "Emu/Cell/PPUModule.h" // Defines STB_TRUETYPE_IMPLEMENTATION *once* before including stb_truetype.h (as noted in stb_truetype.h's comments) #define STB_TRUETYPE_IMPLEMENTATION #include -#include "Emu/FS/vfsFile.h" #include "cellFont.h" -extern Module<> cellFont; +LOG_CHANNEL(cellFont); // Functions s32 cellFontInitializeWithRevision(u64 revisionFlags, vm::ptr config) @@ -68,15 +67,15 @@ s32 cellFontOpenFontFile(vm::ptr library, vm::cptr fontPa { cellFont.warning("cellFontOpenFontFile(library=*0x%x, fontPath=*0x%x, subNum=%d, uniqueId=%d, font=*0x%x)", library, fontPath, subNum, uniqueId, font); - vfsFile f(fontPath.get_ptr()); - if (!f.IsOpened()) + fs::file f(vfs::get(fontPath.get_ptr())); + if (!f) { return CELL_FONT_ERROR_FONT_OPEN_FAILED; } - u32 fileSize = (u32)f.GetSize(); + u32 fileSize = ::size32(f); u32 bufferAddr = vm::alloc(fileSize, vm::main); // Freed in cellFontCloseFont - f.Read(vm::base(bufferAddr), fileSize); + f.read(vm::base(bufferAddr), fileSize); s32 ret = cellFontOpenFontMemory(library, bufferAddr, fileSize, subNum, uniqueId, font); font->origin = CELL_FONT_OPEN_FONT_FILE; @@ -742,7 +741,7 @@ s32 cellFontGraphicsGetLineRGBA() } -Module<> cellFont("cellFont", []() +DECLARE(ppu_module_manager::cellFont)("cellFont", []() { REG_FUNC(cellFont, cellFontSetFontsetOpenMode); REG_FUNC(cellFont, cellFontSetFontOpenMode); diff --git a/rpcs3/Emu/SysCalls/Modules/cellFont.h b/rpcs3/Emu/Cell/Modules/cellFont.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellFont.h rename to rpcs3/Emu/Cell/Modules/cellFont.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellFontFT.cpp b/rpcs3/Emu/Cell/Modules/cellFontFT.cpp similarity index 85% rename from rpcs3/Emu/SysCalls/Modules/cellFontFT.cpp rename to rpcs3/Emu/Cell/Modules/cellFontFT.cpp index 5afe132d5e..5821d440c6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFontFT.cpp +++ b/rpcs3/Emu/Cell/Modules/cellFontFT.cpp @@ -1,10 +1,9 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellFontFT.h" -extern Module<> cellFontFT; +LOG_CHANNEL(cellFontFT); s32 cellFontInitLibraryFreeTypeWithRevision(u64 revisionFlags, vm::ptr config, vm::pptr lib) { @@ -27,7 +26,7 @@ s32 cellFontFTGetInitializedRevisionFlags() return CELL_OK; } -Module<> cellFontFT("cellFontFT", []() +DECLARE(ppu_module_manager::cellFontFT)("cellFontFT", []() { REG_FUNC(cellFontFT, cellFontInitLibraryFreeTypeWithRevision); REG_FUNC(cellFontFT, cellFontFTGetRevisionFlags); diff --git a/rpcs3/Emu/SysCalls/Modules/cellFontFT.h b/rpcs3/Emu/Cell/Modules/cellFontFT.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellFontFT.h rename to rpcs3/Emu/Cell/Modules/cellFontFT.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp b/rpcs3/Emu/Cell/Modules/cellFs.cpp similarity index 79% rename from rpcs3/Emu/SysCalls/Modules/cellFs.cpp rename to rpcs3/Emu/Cell/Modules/cellFs.cpp index 37154ae03b..ee85879eff 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellFs.cpp @@ -1,18 +1,12 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/FS/VFS.h" -#include "Emu/FS/vfsFile.h" -#include "Emu/FS/vfsDir.h" - -#include "Emu/SysCalls/lv2/sys_fs.h" +#include "Emu/Cell/lv2/sys_fs.h" #include "cellFs.h" -extern Module<> cellFs; +LOG_CHANNEL(cellFs); s32 cellFsOpen(vm::cptr path, s32 flags, vm::ptr fd, vm::cptr arg, u64 size) { @@ -222,20 +216,22 @@ s32 cellFsGetDirectoryEntries(u32 fd, vm::ptr entries, u32 for (; count < entries_size; count++) { - if (const auto info = directory->dir->Read()) + fs::dir_entry info; + + if (directory->dir.read(info)) { - entries[count].attribute.mode = info->flags & DirEntry_TypeDir ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666; + entries[count].attribute.mode = info.is_directory ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666; entries[count].attribute.uid = 1; // ??? entries[count].attribute.gid = 1; // ??? - entries[count].attribute.atime = info->access_time; - entries[count].attribute.mtime = info->modify_time; - entries[count].attribute.ctime = info->create_time; - entries[count].attribute.size = info->size; + entries[count].attribute.atime = info.atime; + entries[count].attribute.mtime = info.mtime; + entries[count].attribute.ctime = info.ctime; + entries[count].attribute.size = info.size; entries[count].attribute.blksize = 4096; // ??? - entries[count].entry_name.d_type = info->flags & DirEntry_TypeFile ? CELL_FS_TYPE_REGULAR : CELL_FS_TYPE_DIRECTORY; - entries[count].entry_name.d_namlen = u8(std::min(info->name.length(), CELL_FS_MAX_FS_FILE_NAME_LENGTH)); - strcpy_trunc(entries[count].entry_name.d_name, info->name); + entries[count].entry_name.d_type = info.is_directory ? CELL_FS_TYPE_DIRECTORY : CELL_FS_TYPE_REGULAR; + entries[count].entry_name.d_namlen = u8(std::min(info.name.size(), CELL_FS_MAX_FS_FILE_NAME_LENGTH)); + strcpy_trunc(entries[count].entry_name.d_name, info.name); } else { @@ -263,13 +259,11 @@ s32 cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr buf, u64 buffer_size, std::lock_guard lock(file->mutex); - const auto old_position = file->file->Tell(); + const auto old_pos = file->file.pos(); file->file.seek(offset); - CHECK_ASSERTION(file->file->Seek(offset) != -1); + const auto read = file->file.read(buf.get_ptr(), buffer_size); - const auto read = file->file->Read(buf.get_ptr(), buffer_size); - - CHECK_ASSERTION(file->file->Seek(old_position) != -1); + ASSERT(file->file.seek(old_pos) == old_pos); if (nread) { @@ -294,13 +288,11 @@ s32 cellFsWriteWithOffset(u32 fd, u64 offset, vm::cptr buf, u64 data_size, std::lock_guard lock(file->mutex); - const auto old_position = file->file->Tell(); + const auto old_pos = file->file.pos(); file->file.seek(offset); - CHECK_ASSERTION(file->file->Seek(offset) != -1); + const auto written = file->file.write(buf.get_ptr(), data_size); - const auto written = file->file->Write(buf.get_ptr(), data_size); - - CHECK_ASSERTION(file->file->Seek(old_position) != -1); + ASSERT(file->file.seek(old_pos) == old_pos); if (nwrite) { @@ -489,12 +481,12 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size) } } - offset = std::min(file->file->GetSize(), offset); - size = std::min(file->file->GetSize() - offset, size); + offset = std::min(file->file.size(), offset); + size = std::min(file->file.size() - offset, size); file->st_read_size = size; - file->st_thread = thread_ctrl::spawn(PURE_EXPR("FS ST Thread"s), [=]() + file->st_thread = thread_ctrl::spawn("FS ST Thread", [=]() { std::unique_lock lock(file->mutex); @@ -504,13 +496,13 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size) if (file->st_total_read - file->st_copied <= file->st_ringbuf_size - file->st_block_size && file->st_total_read < file->st_read_size) { // get buffer position - const u32 position = VM_CAST(file->st_buffer + file->st_total_read % file->st_ringbuf_size); + const u32 position = vm::cast(file->st_buffer + file->st_total_read % file->st_ringbuf_size, HERE); // read data - auto old = file->file->Tell(); - CHECK_ASSERTION(file->file->Seek(offset + file->st_total_read) != -1); - auto res = file->file->Read(vm::base(position), file->st_block_size); - CHECK_ASSERTION(file->file->Seek(old) != -1); + auto old = file->file.pos(); + file->file.seek(offset + file->st_total_read); + auto res = file->file.read(vm::base(position), file->st_block_size); + ASSERT(file->file.seek(old) == old); // notify file->st_total_read += res; @@ -594,7 +586,7 @@ s32 cellFsStRead(u32 fd, vm::ptr buf, u64 size, vm::ptr rsize) } const u64 copied = file->st_copied; - const u32 position = VM_CAST(file->st_buffer + copied % file->st_ringbuf_size); + const u32 position = vm::cast(file->st_buffer + copied % file->st_ringbuf_size, HERE); const u64 total_read = file->st_total_read; const u64 copy_size = (*rsize = std::min(size, total_read - copied)); // write rsize @@ -628,7 +620,7 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr addr, vm::ptr size) } const u64 copied = file->st_copied; - const u32 position = VM_CAST(file->st_buffer + copied % file->st_ringbuf_size); + const u32 position = vm::cast(file->st_buffer + copied % file->st_ringbuf_size, HERE); const u64 total_read = file->st_total_read; if ((*size = std::min(file->st_ringbuf_size - (position - file->st_buffer), total_read - copied))) @@ -752,23 +744,23 @@ bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp) s32 sdata_unpack(const std::string& packed_file, const std::string& unpacked_file) { - std::shared_ptr packed_stream(Emu.GetVFS().OpenFile(packed_file, fom::read)); - std::shared_ptr unpacked_stream(Emu.GetVFS().OpenFile(unpacked_file, fom::rewrite)); + fs::file packed_stream(vfs::get(packed_file)); + fs::file unpacked_stream(vfs::get(unpacked_file), fs::rewrite); - if (!packed_stream || !packed_stream->IsOpened()) + if (!packed_stream) { - cellFs.error("File '%s' not found!", packed_file.c_str()); + cellFs.error("File '%s' not found!", packed_file); return CELL_ENOENT; } - if (!unpacked_stream || !unpacked_stream->IsOpened()) + if (!unpacked_stream) { - cellFs.error("File '%s' couldn't be created!", unpacked_file.c_str()); + cellFs.error("File '%s' couldn't be created!", unpacked_file); return CELL_ENOENT; } char buffer[10200]; - packed_stream->Read(buffer, 256); + packed_stream.read(buffer, 256); u32 format = *(be_t*)&buffer[0]; if (format != 0x4E504400) // "NPD\x00" { @@ -780,7 +772,7 @@ s32 sdata_unpack(const std::string& packed_file, const std::string& unpacked_fil u32 flags = *(be_t*)&buffer[0x80]; u32 blockSize = *(be_t*)&buffer[0x84]; u64 filesizeOutput = *(be_t*)&buffer[0x88]; - u64 filesizeInput = packed_stream->GetSize(); + u64 filesizeInput = packed_stream.size(); u32 blockCount = (u32)((filesizeOutput + blockSize - 1) / blockSize); // SDATA file is compressed @@ -804,20 +796,18 @@ s32 sdata_unpack(const std::string& packed_file, const std::string& unpacked_fil if (flags & 0x20) { - CHECK_ASSERTION(packed_stream->Seek(0x100) != -1); + ASSERT(packed_stream.seek(0x100) == 0x100); } else { - CHECK_ASSERTION(packed_stream->Seek(startOffset) != -1); + ASSERT(packed_stream.seek(startOffset) == startOffset); } for (u32 i = 0; i < blockCount; i++) { if (flags & 0x20) { - s64 cur; - CHECK_ASSERTION((cur = packed_stream->Tell()) != -1); - CHECK_ASSERTION(packed_stream->Seek(cur + t1) != -1); + packed_stream.seek(t1, fs::seek_cur); } if (!(blockCount - i - 1)) @@ -825,8 +815,8 @@ s32 sdata_unpack(const std::string& packed_file, const std::string& unpacked_fil blockSize = (u32)(filesizeOutput - i * blockSize); } - packed_stream->Read(buffer + 256, blockSize); - unpacked_stream->Write(buffer + 256, blockSize); + packed_stream.read(buffer + 256, blockSize); + unpacked_stream.write(buffer + 256, blockSize); } } @@ -891,13 +881,13 @@ void fsAio(vm::ptr aio, bool write, s32 xid, fs_aio_cb_t func) { std::lock_guard lock(file->mutex); - const auto old_position = file->file->Tell(); + const auto old_pos = file->file.pos(); file->file.seek(aio->offset); - CHECK_ASSERTION(file->file->Seek(aio->offset) != -1); + result = write + ? file->file.write(aio->buf.get_ptr(), aio->size) + : file->file.read(aio->buf.get_ptr(), aio->size); - result = write ? file->file->Write(aio->buf.get_ptr(), aio->size) : file->file->Read(aio->buf.get_ptr(), aio->size); - - CHECK_ASSERTION(file->file->Seek(old_position) != -1); + ASSERT(file->file.seek(old_pos) == old_pos); } // should be executed directly by FS AIO thread @@ -927,7 +917,7 @@ s32 cellFsAioFinish(vm::cptr mount_point) return CELL_OK; } -std::atomic g_fs_aio_id; +atomic_t g_fs_aio_id; s32 cellFsAioRead(vm::ptr aio, vm::ptr id, fs_aio_cb_t func) { @@ -937,7 +927,7 @@ s32 cellFsAioRead(vm::ptr aio, vm::ptr id, fs_aio_cb_t func) const s32 xid = (*id = ++g_fs_aio_id); - thread_ctrl::spawn(PURE_EXPR("FS AIO Read Thread"s), COPY_EXPR(fsAio(aio, false, xid, func))); + thread_ctrl::spawn("FS AIO Read Thread", COPY_EXPR(fsAio(aio, false, xid, func))); return CELL_OK; } @@ -950,7 +940,7 @@ s32 cellFsAioWrite(vm::ptr aio, vm::ptr id, fs_aio_cb_t func) const s32 xid = (*id = ++g_fs_aio_id); - thread_ctrl::spawn(PURE_EXPR("FS AIO Write Thread"s), COPY_EXPR(fsAio(aio, true, xid, func))); + thread_ctrl::spawn("FS AIO Write Thread", COPY_EXPR(fsAio(aio, true, xid, func))); return CELL_OK; } @@ -1051,66 +1041,64 @@ s32 cellFsUnregisterL10nCallbacks() } -Module<> cellFs("cellFs", []() +DECLARE(ppu_module_manager::cellFs)("sys_fs", []() { - g_fs_aio_id = 1; - - REG_FUNC(cellFs, cellFsOpen); - REG_FUNC(cellFs, cellFsSdataOpen); - REG_FUNC(cellFs, cellFsSdataOpenByFd); - REG_FUNC(cellFs, cellFsRead, MFF_PERFECT); - REG_FUNC(cellFs, cellFsWrite, MFF_PERFECT); - REG_FUNC(cellFs, cellFsClose, MFF_PERFECT); - REG_FUNC(cellFs, cellFsOpendir); - REG_FUNC(cellFs, cellFsReaddir, MFF_PERFECT); - REG_FUNC(cellFs, cellFsClosedir, MFF_PERFECT); - REG_FUNC(cellFs, cellFsStat); - REG_FUNC(cellFs, cellFsFstat, MFF_PERFECT); - REG_FUNC(cellFs, cellFsMkdir); - REG_FUNC(cellFs, cellFsRename); - REG_FUNC(cellFs, cellFsChmod); - REG_FUNC(cellFs, cellFsFsync); - REG_FUNC(cellFs, cellFsRmdir); - REG_FUNC(cellFs, cellFsUnlink); - REG_FUNC(cellFs, cellFsLseek, MFF_PERFECT); - REG_FUNC(cellFs, cellFsFtruncate, MFF_PERFECT); - REG_FUNC(cellFs, cellFsTruncate); - REG_FUNC(cellFs, cellFsFGetBlockSize, MFF_PERFECT); - REG_FUNC(cellFs, cellFsAioInit); - REG_FUNC(cellFs, cellFsAioFinish); - REG_FUNC(cellFs, cellFsAioRead); - REG_FUNC(cellFs, cellFsAioWrite); - REG_FUNC(cellFs, cellFsAioCancel); - REG_FUNC(cellFs, cellFsGetBlockSize); - REG_FUNC(cellFs, cellFsGetFreeSize); - REG_FUNC(cellFs, cellFsReadWithOffset); - REG_FUNC(cellFs, cellFsWriteWithOffset); - REG_FUNC(cellFs, cellFsGetDirectoryEntries); - REG_FUNC(cellFs, cellFsStReadInit); - REG_FUNC(cellFs, cellFsStReadFinish); - REG_FUNC(cellFs, cellFsStReadGetRingBuf); - REG_FUNC(cellFs, cellFsStReadGetStatus); - REG_FUNC(cellFs, cellFsStReadGetRegid); - REG_FUNC(cellFs, cellFsStReadStart); - REG_FUNC(cellFs, cellFsStReadStop); - REG_FUNC(cellFs, cellFsStRead); - REG_FUNC(cellFs, cellFsStReadGetCurrentAddr); - REG_FUNC(cellFs, cellFsStReadPutCurrentAddr); - REG_FUNC(cellFs, cellFsStReadWait); - REG_FUNC(cellFs, cellFsStReadWaitCallback); - REG_FUNC(cellFs, cellFsSetDefaultContainer); - REG_FUNC(cellFs, cellFsSetIoBufferFromDefaultContainer); - REG_FUNC(cellFs, cellFsUtime); - REG_FUNC(cellFs, cellFsArcadeHddSerialNumber); - REG_FUNC(cellFs, cellFsAllocateFileAreaWithInitialData); - REG_FUNC(cellFs, cellFsAllocateFileAreaByFdWithoutZeroFill); - REG_FUNC(cellFs, cellFsSetIoBuffer); - REG_FUNC(cellFs, cellFsAllocateFileAreaByFdWithInitialData); - REG_FUNC(cellFs, cellFsTruncate2); - REG_FUNC(cellFs, cellFsChangeFileSizeWithoutAllocation); - REG_FUNC(cellFs, cellFsAllocateFileAreaWithoutZeroFill); - REG_FUNC(cellFs, cellFsChangeFileSizeByFdWithoutAllocation); - REG_FUNC(cellFs, cellFsSetDiscReadRetrySetting); - REG_FUNC(cellFs, cellFsRegisterConversionCallback); - REG_FUNC(cellFs, cellFsUnregisterL10nCallbacks); + REG_FUNC(sys_fs, cellFsOpen); + REG_FUNC(sys_fs, cellFsSdataOpen); + REG_FUNC(sys_fs, cellFsSdataOpenByFd); + REG_FUNC(sys_fs, cellFsRead, MFF_PERFECT); + REG_FUNC(sys_fs, cellFsWrite, MFF_PERFECT); + REG_FUNC(sys_fs, cellFsClose, MFF_PERFECT); + REG_FUNC(sys_fs, cellFsOpendir); + REG_FUNC(sys_fs, cellFsReaddir, MFF_PERFECT); + REG_FUNC(sys_fs, cellFsClosedir, MFF_PERFECT); + REG_FUNC(sys_fs, cellFsStat); + REG_FUNC(sys_fs, cellFsFstat, MFF_PERFECT); + REG_FUNC(sys_fs, cellFsMkdir); + REG_FUNC(sys_fs, cellFsRename); + REG_FUNC(sys_fs, cellFsChmod); + REG_FUNC(sys_fs, cellFsFsync); + REG_FUNC(sys_fs, cellFsRmdir); + REG_FUNC(sys_fs, cellFsUnlink); + REG_FUNC(sys_fs, cellFsLseek, MFF_PERFECT); + REG_FUNC(sys_fs, cellFsFtruncate, MFF_PERFECT); + REG_FUNC(sys_fs, cellFsTruncate); + REG_FUNC(sys_fs, cellFsFGetBlockSize, MFF_PERFECT); + REG_FUNC(sys_fs, cellFsAioInit); + REG_FUNC(sys_fs, cellFsAioFinish); + REG_FUNC(sys_fs, cellFsAioRead); + REG_FUNC(sys_fs, cellFsAioWrite); + REG_FUNC(sys_fs, cellFsAioCancel); + REG_FUNC(sys_fs, cellFsGetBlockSize); + REG_FUNC(sys_fs, cellFsGetFreeSize); + REG_FUNC(sys_fs, cellFsReadWithOffset); + REG_FUNC(sys_fs, cellFsWriteWithOffset); + REG_FUNC(sys_fs, cellFsGetDirectoryEntries); + REG_FUNC(sys_fs, cellFsStReadInit); + REG_FUNC(sys_fs, cellFsStReadFinish); + REG_FUNC(sys_fs, cellFsStReadGetRingBuf); + REG_FUNC(sys_fs, cellFsStReadGetStatus); + REG_FUNC(sys_fs, cellFsStReadGetRegid); + REG_FUNC(sys_fs, cellFsStReadStart); + REG_FUNC(sys_fs, cellFsStReadStop); + REG_FUNC(sys_fs, cellFsStRead); + REG_FUNC(sys_fs, cellFsStReadGetCurrentAddr); + REG_FUNC(sys_fs, cellFsStReadPutCurrentAddr); + REG_FUNC(sys_fs, cellFsStReadWait); + REG_FUNC(sys_fs, cellFsStReadWaitCallback); + REG_FUNC(sys_fs, cellFsSetDefaultContainer); + REG_FUNC(sys_fs, cellFsSetIoBufferFromDefaultContainer); + REG_FUNC(sys_fs, cellFsUtime); + REG_FUNC(sys_fs, cellFsArcadeHddSerialNumber); + REG_FUNC(sys_fs, cellFsAllocateFileAreaWithInitialData); + REG_FUNC(sys_fs, cellFsAllocateFileAreaByFdWithoutZeroFill); + REG_FUNC(sys_fs, cellFsSetIoBuffer); + REG_FUNC(sys_fs, cellFsAllocateFileAreaByFdWithInitialData); + REG_FUNC(sys_fs, cellFsTruncate2); + REG_FUNC(sys_fs, cellFsChangeFileSizeWithoutAllocation); + REG_FUNC(sys_fs, cellFsAllocateFileAreaWithoutZeroFill); + REG_FUNC(sys_fs, cellFsChangeFileSizeByFdWithoutAllocation); + REG_FUNC(sys_fs, cellFsSetDiscReadRetrySetting); + REG_FUNC(sys_fs, cellFsRegisterConversionCallback); + REG_FUNC(sys_fs, cellFsUnregisterL10nCallbacks); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellFs.h b/rpcs3/Emu/Cell/Modules/cellFs.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellFs.h rename to rpcs3/Emu/Cell/Modules/cellFs.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/Cell/Modules/cellGame.cpp similarity index 83% rename from rpcs3/Emu/SysCalls/Modules/cellGame.cpp rename to rpcs3/Emu/Cell/Modules/cellGame.cpp index 08a535e449..0230547d47 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGame.cpp @@ -1,17 +1,15 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/FS/VFS.h" -#include "Emu/FS/vfsFile.h" -#include "Loader/PSF.h" #include "cellSysutil.h" #include "cellMsgDialog.h" #include "cellGame.h" -extern Module<> cellGame; +#include + +LOG_CHANNEL(cellGame); // Normal content directory (if is_temporary is not involved): // contentInfo = dir @@ -40,7 +38,7 @@ struct content_permission_t final { if (is_temporary) { - Emu.GetVFS().DeleteAll("/dev_hdd1/game/" + dir); + fs::remove_all(vfs::get("/dev_hdd1/game/" + dir)); } } }; @@ -56,7 +54,6 @@ s32 cellHddGameCheck(PPUThread& ppu, u32 version, vm::cptr dirName, u32 er return CELL_HDDGAME_ERROR_PARAM; } - vm::var param; vm::var result; vm::var get; vm::var set; @@ -71,14 +68,17 @@ s32 cellHddGameCheck(PPUThread& ppu, u32 version, vm::cptr dirName, u32 er strcpy_trunc(get->contentInfoPath, "/dev_hdd0/game/" + dir); strcpy_trunc(get->hddGamePath, "/dev_hdd0/game/" + dir + "/USRDIR"); - if (!Emu.GetVFS().ExistsDir("/dev_hdd0/game/" + dir)) + const std::string& local_dir = vfs::get("/dev_hdd0/game/" + dir); + + if (!fs::is_dir(local_dir)) { get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR; + get->getParam = {}; } else { // TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else) - const auto& psf = psf::load(vfsFile("/dev_hdd0/game/" + dir + "/PARAM.SFO").VRead()); + const auto& psf = psf::load_object(fs::file(local_dir +"/PARAM.SFO")); get->getParam.parentalLevel = psf.at("PARENTAL_LEVEL").as_integer(); get->getParam.attribute = psf.at("ATTRIBUTE").as_integer(); @@ -159,16 +159,9 @@ s32 cellGameBootCheck(vm::ptr type, vm::ptr attributes, vm::ptrsysSizeKB = 0; } - const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead()); + // According to testing (in debug mode) cellGameBootCheck doesn't return an error code, when PARAM.SFO doesn't exist. + const std::string& category = psf::get_string(Emu.GetPSF(), "CATEGORY"); - if (psf.empty()) - { - // According to testing (in debug mode) cellGameBootCheck doesn't return an error code, when PARAM.SFO doesn't exist. - cellGame.error("cellGameBootCheck(): Cannot read PARAM.SFO."); - return CELL_GAME_RET_OK; - } - - const std::string& category = psf.at("CATEGORY").as_string(); if (category == "DG") { *type = CELL_GAME_GAMETYPE_DISC; @@ -182,22 +175,20 @@ s32 cellGameBootCheck(vm::ptr type, vm::ptr attributes, vm::ptr("/dev_hdd0/game/" + titleId, false)) + if (!fxm::make("/dev_hdd0/game/" + Emu.GetTitleID(), false)) { return CELL_GAME_ERROR_BUSY; } } else if (category == "GD") { - const std::string& titleId = psf.at("TITLE_ID").as_string(); *type = CELL_GAME_GAMETYPE_DISC; *attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO - if (dirName) strcpy_trunc(*dirName, titleId); // ??? + if (dirName) strcpy_trunc(*dirName, Emu.GetTitleID()); // ??? if (!fxm::make("/dev_bdvd/PS3_GAME", false)) { @@ -206,7 +197,7 @@ s32 cellGameBootCheck(vm::ptr type, vm::ptr attributes, vm::ptr size, vm::ptr reserved size->sysSizeKB = 0; } - const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead()); - - if (psf.empty() || psf.at("CATEGORY").as_string() != "GD") + if (psf::get_string(Emu.GetPSF(), "CATEGORY") != "GD") { cellGame.error("cellGamePatchCheck(): CELL_GAME_ERROR_NOTPATCH"); return CELL_GAME_ERROR_NOTPATCH; } - if (!fxm::make("/dev_hdd0/game/" + psf.at("TITLE_ID").as_string(), false)) + if (!fxm::make("/dev_hdd0/game/" + Emu.GetTitleID(), false)) { return CELL_GAME_ERROR_BUSY; } @@ -262,35 +251,18 @@ s32 cellGameDataCheck(u32 type, vm::cptr dirName, vm::ptrsysSizeKB = 0; } - if (type == CELL_GAME_GAMETYPE_DISC) + // TODO: not sure what should be checked there + const std::string& dir = type == CELL_GAME_GAMETYPE_DISC ? "/dev_bdvd/PS3_GAME"s : "/dev_hdd0/game/"s + dirName.get_ptr(); + + if (!fs::is_dir(vfs::get(dir))) { - // TODO: not sure what should be checked there - - if (!Emu.GetVFS().ExistsDir("/dev_bdvd/PS3_GAME")) - { - cellGame.warning("cellGameDataCheck(): /dev_bdvd/PS3_GAME not found"); - return CELL_GAME_RET_NONE; - } - - if (!fxm::make("/dev_bdvd/PS3_GAME", false)) - { - return CELL_GAME_ERROR_BUSY; - } + cellGame.warning("cellGameDataCheck(): '%s' directory not found", dir.c_str()); + return CELL_GAME_RET_NONE; } - else + + if (!fxm::make(dir, false)) { - const std::string dir = "/dev_hdd0/game/"s + dirName.get_ptr(); - - if (!Emu.GetVFS().ExistsDir(dir)) - { - cellGame.warning("cellGameDataCheck(): '%s' directory not found", dir.c_str()); - return CELL_GAME_RET_NONE; - } - - if (!fxm::make(dir, false)) - { - return CELL_GAME_ERROR_BUSY; - } + return CELL_GAME_ERROR_BUSY; } return CELL_GAME_RET_OK; @@ -314,19 +286,21 @@ s32 cellGameContentPermit(vm::ptr contentInfoPath, vm: if (path_set->is_temporary) { - const std::string dir = "/dev_hdd0/game/" + path_set->dir; + const std::string& dir = "/dev_hdd0/game/" + path_set->dir; - // make temporary directory persistent - if (Emu.GetVFS().Rename("/dev_hdd1/game/" + path_set->dir, dir)) + // Make temporary directory persistent + fs::remove_all(vfs::get(dir)); + + if (fs::rename(vfs::get("/dev_hdd1/game/" + path_set->dir), vfs::get(dir))) { - cellGame.success("cellGameContentPermit(): '%s' directory created", dir); + cellGame.success("cellGameContentPermit(): created directory %s", dir); } else { - throw EXCEPTION("Cannot create gamedata directory"); + throw fmt::exception("cellGameContentPermit(): failed to rename to %s", dir); } - // prevent deleting directory + // Disable deletion path_set->is_temporary = false; strcpy_trunc(*contentInfoPath, dir); @@ -353,17 +327,15 @@ s32 cellGameDataCheckCreate2(PPUThread& ppu, u32 version, vm::cptr dirName // TODO: output errors (errDialog) - const std::string dir = "/dev_hdd0/game/"s + dirName.get_ptr(); + const std::string& dir = "/dev_hdd0/game/"s + dirName.get_ptr(); - if (!Emu.GetVFS().ExistsDir(dir)) + if (!fs::is_dir(vfs::get(dir))) { - cellGame.todo("cellGameDataCheckCreate2(): creating directory '%s'", dir.c_str()); + cellGame.todo("cellGameDataCheckCreate2(): should create directory %s", dir); // TODO: create data return CELL_GAMEDATA_RET_OK; } - const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead()); - vm::var cbResult; vm::var cbGet; vm::var cbSet; @@ -385,10 +357,10 @@ s32 cellGameDataCheckCreate2(PPUThread& ppu, u32 version, vm::cptr dirName cbGet->sysSizeKB = 0; cbGet->getParam.attribute = CELL_GAMEDATA_ATTR_NORMAL; - cbGet->getParam.parentalLevel = psf.at("PARENTAL_LEVEL").as_integer(); - strcpy_trunc(cbGet->getParam.dataVersion, psf.at("APP_VER").as_string()); - strcpy_trunc(cbGet->getParam.titleId, psf.at("TITLE_ID").as_string()); - strcpy_trunc(cbGet->getParam.title, psf.at("TITLE").as_string()); + cbGet->getParam.parentalLevel = Emu.GetPSF().at("PARENTAL_LEVEL").as_integer(); + strcpy_trunc(cbGet->getParam.dataVersion, Emu.GetPSF().at("APP_VER").as_string()); + strcpy_trunc(cbGet->getParam.titleId, Emu.GetPSF().at("TITLE_ID").as_string()); + strcpy_trunc(cbGet->getParam.title, Emu.GetPSF().at("TITLE").as_string()); // TODO: write lang titles funcStat(ppu, cbResult, cbGet, cbSet); @@ -446,15 +418,15 @@ s32 cellGameCreateGameData(vm::ptr init, vm::ptr value) { cellGame.warning("cellGameGetParamInt(id=%d, value=*0x%x)", id, value); - const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead()); - std::string key; switch(id) @@ -498,7 +468,7 @@ s32 cellGameGetParamInt(u32 id, vm::ptr value) return CELL_GAME_ERROR_INVALID_ID; } - *value = psf.at(key).as_integer(); + *value = Emu.GetPSF().at(key).as_integer(); return CELL_OK; } @@ -506,9 +476,8 @@ s32 cellGameGetParamString(u32 id, vm::ptr buf, u32 bufsize) { cellGame.warning("cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d)", id, buf, bufsize); - const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead()); - std::string key; + switch(id) { case CELL_GAME_PARAMID_TITLE: key = "TITLE"; break; // TODO: Is this value correct? @@ -542,7 +511,7 @@ s32 cellGameGetParamString(u32 id, vm::ptr buf, u32 bufsize) return CELL_GAME_ERROR_INVALID_ID; } - const std::string& value = psf.at(key).as_string().substr(0, bufsize - 1); + const std::string& value = Emu.GetPSF().at(key).as_string().substr(0, bufsize - 1); std::copy_n(value.c_str(), value.size() + 1, buf.get_ptr()); @@ -666,8 +635,6 @@ s32 cellGameUnregisterDiscChangeCallback() void cellSysutil_GameData_init() { - extern Module<> cellSysutil; - REG_FUNC(cellSysutil, cellHddGameCheck); REG_FUNC(cellSysutil, cellHddGameCheck2); REG_FUNC(cellSysutil, cellHddGameGetSizeKB); @@ -688,7 +655,7 @@ void cellSysutil_GameData_init() REG_FUNC(cellSysutil, cellGameUnregisterDiscChangeCallback); } -Module<> cellGame("cellGame", []() +DECLARE(ppu_module_manager::cellGame)("cellGame", []() { REG_FUNC(cellGame, cellGameBootCheck); REG_FUNC(cellGame, cellGamePatchCheck); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.h b/rpcs3/Emu/Cell/Modules/cellGame.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellGame.h rename to rpcs3/Emu/Cell/Modules/cellGame.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellGameExec.cpp b/rpcs3/Emu/Cell/Modules/cellGameExec.cpp similarity index 89% rename from rpcs3/Emu/SysCalls/Modules/cellGameExec.cpp rename to rpcs3/Emu/Cell/Modules/cellGameExec.cpp index 01f08d5e30..9367db8796 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGameExec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGameExec.cpp @@ -1,10 +1,9 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellGame.h" -extern Module<> cellGameExec; +LOG_CHANNEL(cellGameExec); s32 cellGameSetExitParam() { @@ -45,7 +44,7 @@ s32 cellGameGetBootGameInfo(vm::ptr type, vm::ptr dirName, vm::ptr cellGameExec("cellGameExec", []() +DECLARE(ppu_module_manager::cellGameExec)("cellGameExec", []() { REG_FUNC(cellGameExec, cellGameSetExitParam); REG_FUNC(cellGameExec, cellGameGetHomeDataExportPath); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp similarity index 89% rename from rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp rename to rpcs3/Emu/Cell/Modules/cellGcmSys.cpp index 3f14986a60..f1e856df33 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp @@ -1,17 +1,16 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/IdManager.h" +#include "Emu/Cell/PPUModule.h" -#include "sysPrxForUser.h" - -//#include "Emu/RSX/GCM.h" -#include "Emu/RSX/GSManager.h" +#include "Emu/Cell/PPUOpcodes.h" +#include "Emu/Memory/Memory.h" #include "Emu/RSX/GSRender.h" -//#include "Emu/SysCalls/lv2/sys_process.h" #include "cellGcmSys.h" -extern Module<> cellGcmSys; +LOG_CHANNEL(cellGcmSys); + +extern s32 cellGcmCallback(vm::ptr context, u32 count); const u32 tiled_pitches[] = { 0x00000000, 0x00000200, 0x00000300, 0x00000400, @@ -101,8 +100,7 @@ vm::ptr cellGcmGetReportDataAddressLocation(u32 index, u32 lo cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong main index (%d)", index); return vm::null; } - // TODO: It seems m_report_main_addr is not initialized - return vm::ptr::make(Emu.GetGSManager().GetRender().report_main_addr + index * 0x10); + return vm::ptr::make(RSXIOMem.RealAddr(index * 0x10)); } cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong location (%d)", location); @@ -200,8 +198,7 @@ u64 cellGcmGetTimeStampLocation(u32 index, u32 location) cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong main index (%d)", index); return 0; } - // TODO: It seems m_report_main_addr is not initialized - return vm::read64(Emu.GetGSManager().GetRender().report_main_addr + index * 0x10); + return vm::read64(RSXIOMem.RealAddr(index * 0x10)); } cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong location (%d)", location); @@ -257,8 +254,7 @@ s32 cellGcmBindTile(u8 index) return CELL_GCM_ERROR_INVALID_VALUE; } - auto& tile = Emu.GetGSManager().GetRender().tiles[index]; - tile.binded = true; + fxm::get()->tiles[index].binded = true; return CELL_OK; } @@ -273,8 +269,7 @@ s32 cellGcmBindZcull(u8 index) return CELL_GCM_ERROR_INVALID_VALUE; } - auto& zcull = Emu.GetGSManager().GetRender().zculls[index]; - zcull.binded = true; + fxm::get()->zculls[index].binded = true; return CELL_OK; } @@ -290,7 +285,7 @@ s32 cellGcmGetConfiguration(vm::ptr config) s32 cellGcmGetFlipStatus() { - s32 status = Emu.GetGSManager().GetRender().flip_status; + s32 status = fxm::get()->flip_status; cellGcmSys.trace("cellGcmGetFlipStatus() -> %d", status); @@ -328,6 +323,11 @@ s32 _cellGcmInitBody(vm::pptr context, u32 cmdSize, u32 ioSi { cellGcmSys.warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress); + current_config.ioAddress = 0; + current_config.localAddress = 0; + local_size = 0; + local_addr = 0; + if (!local_size && !local_addr) { local_size = 0xf900000; // TODO: Get sdk_version in _cellGcmFunc15 and pass it to gcmGetLocalMemorySize @@ -369,15 +369,19 @@ s32 _cellGcmInitBody(vm::pptr context, u32 cmdSize, u32 ioSi g_defaultCommandBufferBegin = ioAddress; g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024); + gcm_info.context_addr = vm::alloc(0x1000, vm::main); + gcm_info.control_addr = vm::alloc(0x1000, vm::main); + gcm_info.label_addr = vm::alloc(0x1000, vm::main); // ??? + current_context.begin.set(g_defaultCommandBufferBegin + 4096); // 4 kb reserved at the beginning current_context.end.set(g_defaultCommandBufferBegin + 32 * 1024 - 4); // 4b at the end for jump current_context.current = current_context.begin; - current_context.callback.set(Emu.GetRSXCallback() - 4); + current_context.callback.set(gcm_info.context_addr + 0x40); - gcm_info.context_addr = vm::alloc(0x1000, vm::main); - gcm_info.control_addr = gcm_info.context_addr + 0x40; - - gcm_info.label_addr = vm::alloc(0x1000, vm::main); // ??? + vm::write32(gcm_info.context_addr + 0x40, gcm_info.context_addr + 0x48); + vm::write32(gcm_info.context_addr + 0x44, 0xabadcafe); + vm::write32(gcm_info.context_addr + 0x48, ppu_instructions::HACK(FIND_FUNC(cellGcmCallback))); + vm::write32(gcm_info.context_addr + 0x4c, ppu_instructions::BLR()); vm::_ref(gcm_info.context_addr) = current_context; context->set(gcm_info.context_addr); @@ -387,16 +391,16 @@ s32 _cellGcmInitBody(vm::pptr context, u32 cmdSize, u32 ioSi ctrl.get = 0; ctrl.ref = -1; - auto& render = Emu.GetGSManager().GetRender(); - render.ctxt_addr = context.addr(); - render.gcm_buffers.set(vm::alloc(sizeof(CellGcmDisplayInfo) * 8, vm::main)); - render.zculls_addr = vm::alloc(sizeof(CellGcmZcullInfo) * 8, vm::main); - render.tiles_addr = vm::alloc(sizeof(CellGcmTileInfo) * 15, vm::main); - render.gcm_buffers_count = 0; - render.gcm_current_buffer = 0; - render.main_mem_addr = 0; - render.label_addr = gcm_info.label_addr; - render.init(g_defaultCommandBufferBegin, cmdSize, gcm_info.control_addr, local_addr); + const auto render = fxm::get(); + render->ctxt_addr = context.addr(); + render->gcm_buffers.set(vm::alloc(sizeof(CellGcmDisplayInfo) * 8, vm::main)); + render->zculls_addr = vm::alloc(sizeof(CellGcmZcullInfo) * 8, vm::main); + render->tiles_addr = vm::alloc(sizeof(CellGcmTileInfo) * 15, vm::main); + render->gcm_buffers_count = 0; + render->gcm_current_buffer = 0; + render->main_mem_addr = 0; + render->label_addr = gcm_info.label_addr; + render->init(g_defaultCommandBufferBegin, cmdSize, gcm_info.control_addr, local_addr); return CELL_OK; } @@ -405,7 +409,7 @@ s32 cellGcmResetFlipStatus() { cellGcmSys.trace("cellGcmResetFlipStatus()"); - Emu.GetGSManager().GetRender().flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_WAITING; + fxm::get()->flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_WAITING; return CELL_OK; } @@ -419,7 +423,7 @@ s32 cellGcmSetDebugOutputLevel(s32 level) case CELL_GCM_DEBUG_LEVEL0: case CELL_GCM_DEBUG_LEVEL1: case CELL_GCM_DEBUG_LEVEL2: - Emu.GetGSManager().GetRender().debug_level = level; + fxm::get()->debug_level = level; break; default: return CELL_EINVAL; @@ -438,16 +442,18 @@ s32 cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height return CELL_EINVAL; } - auto buffers = Emu.GetGSManager().GetRender().gcm_buffers; + const auto render = fxm::get(); + + auto buffers = render->gcm_buffers; buffers[id].offset = offset; buffers[id].pitch = pitch; buffers[id].width = width; buffers[id].height = height; - if (id + 1 > Emu.GetGSManager().GetRender().gcm_buffers_count) + if (id + 1 > render->gcm_buffers_count) { - Emu.GetGSManager().GetRender().gcm_buffers_count = id + 1; + render->gcm_buffers_count = id + 1; } return CELL_OK; @@ -457,7 +463,7 @@ void cellGcmSetFlipHandler(vm::ptr handler) { cellGcmSys.warning("cellGcmSetFlipHandler(handler=*0x%x)", handler); - Emu.GetGSManager().GetRender().flip_handler = handler; + fxm::get()->flip_handler = handler; } s32 cellGcmSetFlipMode(u32 mode) @@ -469,7 +475,7 @@ s32 cellGcmSetFlipMode(u32 mode) case CELL_GCM_DISPLAY_HSYNC: case CELL_GCM_DISPLAY_VSYNC: case CELL_GCM_DISPLAY_HSYNC_WITH_NOISE: - Emu.GetGSManager().GetRender().flip_mode = mode; + fxm::get()->flip_mode = mode; break; default: @@ -483,7 +489,7 @@ void cellGcmSetFlipStatus() { cellGcmSys.warning("cellGcmSetFlipStatus()"); - Emu.GetGSManager().GetRender().flip_status = 0; + fxm::get()->flip_status = 0; } s32 cellGcmSetPrepareFlip(PPUThread& ppu, vm::ptr ctxt, u32 id) @@ -541,14 +547,22 @@ s32 cellGcmSetSecondVFrequency(u32 freq) { cellGcmSys.warning("cellGcmSetSecondVFrequency(level=%d)", freq); + const auto render = fxm::get(); + switch (freq) { case CELL_GCM_DISPLAY_FREQUENCY_59_94HZ: - Emu.GetGSManager().GetRender().frequency_mode = freq; Emu.GetGSManager().GetRender().fps_limit = 59.94; break; + render->frequency_mode = freq; + render->fps_limit = 59.94; + break; case CELL_GCM_DISPLAY_FREQUENCY_SCANOUT: - Emu.GetGSManager().GetRender().frequency_mode = freq; cellGcmSys.todo("Unimplemented display frequency: Scanout"); break; + render->frequency_mode = freq; + cellGcmSys.todo("Unimplemented display frequency: Scanout"); + break; case CELL_GCM_DISPLAY_FREQUENCY_DISABLE: - Emu.GetGSManager().GetRender().frequency_mode = freq; cellGcmSys.todo("Unimplemented display frequency: Disabled"); break; + render->frequency_mode = freq; + cellGcmSys.todo("Unimplemented display frequency: Disabled"); + break; default: cellGcmSys.error("Improper display frequency specified!"); return CELL_OK; } @@ -583,7 +597,9 @@ s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u cellGcmSys.error("cellGcmSetTileInfo: bad compression mode! (%d)", comp); } - auto& tile = Emu.GetGSManager().GetRender().tiles[index]; + const auto render = fxm::get(); + + auto& tile = render->tiles[index]; tile.location = location; tile.offset = offset; tile.size = size; @@ -592,7 +608,7 @@ s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u tile.base = base; tile.bank = bank; - vm::_ptr(Emu.GetGSManager().GetRender().tiles_addr)[index] = tile.pack(); + vm::_ptr(render->tiles_addr)[index] = tile.pack(); return CELL_OK; } @@ -600,7 +616,7 @@ void cellGcmSetUserHandler(vm::ptr handler) { cellGcmSys.warning("cellGcmSetUserHandler(handler=*0x%x)", handler); - Emu.GetGSManager().GetRender().user_handler = handler; + fxm::get()->user_handler = handler; } s32 cellGcmSetUserCommand() @@ -612,7 +628,7 @@ void cellGcmSetVBlankHandler(vm::ptr handler) { cellGcmSys.warning("cellGcmSetVBlankHandler(handler=*0x%x)", handler); - Emu.GetGSManager().GetRender().vblank_handler = handler; + fxm::get()->vblank_handler = handler; } s32 cellGcmSetWaitFlip(vm::ptr ctxt) @@ -640,7 +656,9 @@ s32 cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart, return CELL_GCM_ERROR_INVALID_VALUE; } - auto& zcull = Emu.GetGSManager().GetRender().zculls[index]; + const auto render = fxm::get(); + + auto& zcull = render->zculls[index]; zcull.offset = offset; zcull.width = width; zcull.height = height; @@ -653,7 +671,7 @@ s32 cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart, zcull.sRef = sRef; zcull.sMask = sMask; - vm::_ptr(Emu.GetGSManager().GetRender().zculls_addr)[index] = zcull.pack(); + vm::_ptr(render->zculls_addr)[index] = zcull.pack(); return CELL_OK; } @@ -667,8 +685,7 @@ s32 cellGcmUnbindTile(u8 index) return CELL_GCM_ERROR_INVALID_VALUE; } - auto& tile = Emu.GetGSManager().GetRender().tiles[index]; - tile.binded = false; + fxm::get()->tiles[index].binded = false; return CELL_OK; } @@ -683,8 +700,7 @@ s32 cellGcmUnbindZcull(u8 index) return CELL_EINVAL; } - auto& zcull = Emu.GetGSManager().GetRender().zculls[index]; - zcull.binded = false; + fxm::get()->zculls[index].binded = false; return CELL_OK; } @@ -692,32 +708,30 @@ s32 cellGcmUnbindZcull(u8 index) u32 cellGcmGetTileInfo() { cellGcmSys.warning("cellGcmGetTileInfo()"); - return Emu.GetGSManager().GetRender().tiles_addr; + return fxm::get()->tiles_addr; } u32 cellGcmGetZcullInfo() { cellGcmSys.warning("cellGcmGetZcullInfo()"); - return Emu.GetGSManager().GetRender().zculls_addr; + return fxm::get()->zculls_addr; } u32 cellGcmGetDisplayInfo() { - cellGcmSys.warning("cellGcmGetDisplayInfo() = 0x%x", Emu.GetGSManager().GetRender().gcm_buffers.addr()); - return Emu.GetGSManager().GetRender().gcm_buffers.addr(); + cellGcmSys.warning("cellGcmGetDisplayInfo()"); + return fxm::get()->gcm_buffers.addr(); } s32 cellGcmGetCurrentDisplayBufferId(vm::ptr id) { cellGcmSys.warning("cellGcmGetCurrentDisplayBufferId(id=*0x%x)", id); - if (Emu.GetGSManager().GetRender().gcm_current_buffer > UINT8_MAX) + if ((*id = fxm::get()->gcm_current_buffer) > UINT8_MAX) { throw EXCEPTION("Unexpected"); } - *id = Emu.GetGSManager().GetRender().gcm_current_buffer; - return CELL_OK; } @@ -748,7 +762,7 @@ u64 cellGcmGetLastFlipTime() { cellGcmSys.trace("cellGcmGetLastFlipTime()"); - return Emu.GetGSManager().GetRender().last_flip_time; + return fxm::get()->last_flip_time; } u64 cellGcmGetLastSecondVTime() @@ -761,7 +775,7 @@ u64 cellGcmGetVBlankCount() { cellGcmSys.trace("cellGcmGetVBlankCount()"); - return Emu.GetGSManager().GetRender().vblank_count; + return fxm::get()->vblank_count; } s32 cellGcmSysGetLastVBlankTime() @@ -896,6 +910,8 @@ s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict) { if ((ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE; + const auto render = fxm::get(); + // Check if the mapping was successfull if (RSXIOMem.Map(ea, size, io)) { @@ -904,7 +920,7 @@ s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict) { offsetTable.ioAddress[(ea >> 20) + i] = (io >> 20) + i; offsetTable.eaAddress[(io >> 20) + i] = (ea >> 20) + i; - Emu.GetGSManager().GetRender().strict_ordering[(io >> 20) + i] = is_strict; + render->strict_ordering[(io >> 20) + i] = is_strict; } } else @@ -927,7 +943,7 @@ s32 cellGcmMapEaIoAddressWithFlags(u32 ea, u32 io, u32 size, u32 flags) { cellGcmSys.warning("cellGcmMapEaIoAddressWithFlags(ea=0x%x, io=0x%x, size=0x%x, flags=0x%x)", ea, io, size, flags); - assert(flags == 2 /*CELL_GCM_IOMAP_FLAG_STRICT_ORDERING*/); + ASSERT(flags == 2 /*CELL_GCM_IOMAP_FLAG_STRICT_ORDERING*/); return gcmMapEaIoAddress(ea, io, size, true); } @@ -958,6 +974,8 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr offset) u32 io = RSXIOMem.Map(ea, size); + const auto render = fxm::get(); + //check if the mapping was successfull if (RSXIOMem.RealAddr(io) == ea) { @@ -966,7 +984,7 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr offset) { offsetTable.ioAddress[(ea >> 20) + i] = (u16)((io >> 20) + i); offsetTable.eaAddress[(io >> 20) + i] = (u16)((ea >> 20) + i); - Emu.GetGSManager().GetRender().strict_ordering[(io >> 20) + i] = false; + render->strict_ordering[(io >> 20) + i] = false; } *offset = io; @@ -977,7 +995,7 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr offset) return CELL_GCM_ERROR_NO_IO_PAGE_TABLE; } - Emu.GetGSManager().GetRender().main_mem_addr = Emu.GetGSManager().GetRender().ioAddress; + render->main_mem_addr = render->ioAddress; return CELL_OK; } @@ -1117,7 +1135,7 @@ s32 cellGcmSetCursorImageOffset(u32 offset) void cellGcmSetDefaultCommandBuffer() { cellGcmSys.warning("cellGcmSetDefaultCommandBuffer()"); - vm::write32(Emu.GetGSManager().GetRender().ctxt_addr, gcm_info.context_addr); + vm::write32(fxm::get()->ctxt_addr, gcm_info.context_addr); } s32 cellGcmSetDefaultCommandBufferAndSegmentWordSize() @@ -1174,7 +1192,9 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co cellGcmSys.error("cellGcmSetTile: bad compression mode! (%d)", comp); } - auto& tile = Emu.GetGSManager().GetRender().tiles[index]; + const auto render = fxm::get(); + + auto& tile = render->tiles[index]; tile.location = location; tile.offset = offset; tile.size = size; @@ -1183,7 +1203,7 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co tile.base = base; tile.bank = bank; - vm::_ptr(Emu.GetGSManager().GetRender().tiles_addr)[index] = tile.pack(); + vm::_ptr(render->tiles_addr)[index] = tile.pack(); return CELL_OK; } @@ -1247,7 +1267,7 @@ static std::pair getNextCommandBufferBeginEnd(u32 current) static u32 getOffsetFromAddress(u32 address) { const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits - assert(upper != 0xFFFF); + Expects(upper != 0xFFFF); return (upper << 20) | (address & 0xFFFFF); } @@ -1269,7 +1289,6 @@ static bool isInCommandBufferExcept(u32 getPos, u32 bufferBegin, u32 bufferEnd) return true; } -// TODO: Avoid using syscall 1023 for calling this function s32 cellGcmCallback(vm::ptr context, u32 count) { cellGcmSys.trace("cellGcmCallback(context=*0x%x, count=0x%x)", context, count); @@ -1306,13 +1325,8 @@ s32 cellGcmCallback(vm::ptr context, u32 count) //---------------------------------------------------------------------------- -Module<> cellGcmSys("cellGcmSys", []() +DECLARE(ppu_module_manager::cellGcmSys)("cellGcmSys", []() { - current_config.ioAddress = 0; - current_config.localAddress = 0; - local_size = 0; - local_addr = 0; - // Data Retrieval REG_FUNC(cellGcmSys, cellGcmGetCurrentField); REG_FUNC(cellGcmSys, cellGcmGetLabelAddress); @@ -1419,4 +1433,7 @@ Module<> cellGcmSys("cellGcmSys", []() REG_FUNC(cellGcmSys, cellGcmGpadGetStatus); REG_FUNC(cellGcmSys, cellGcmGpadNotifyCaptureSurface); REG_FUNC(cellGcmSys, cellGcmGpadCaptureSnapshot); + + // Special + REG_FNID(cellGcmSys, 0x00000000, cellGcmCallback); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h b/rpcs3/Emu/Cell/Modules/cellGcmSys.h similarity index 87% rename from rpcs3/Emu/SysCalls/Modules/cellGcmSys.h rename to rpcs3/Emu/Cell/Modules/cellGcmSys.h index 58f7a7dc1a..1c4109cbcb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.h @@ -22,6 +22,3 @@ struct CellGcmOffsetTable // Auxiliary functions s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict); - -// Syscall -s32 cellGcmCallback(vm::ptr context, u32 count); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp similarity index 69% rename from rpcs3/Emu/SysCalls/Modules/cellGem.cpp rename to rpcs3/Emu/Cell/Modules/cellGem.cpp index a2e3910fad..f10e41ea58 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -1,11 +1,10 @@ #include "stdafx.h" #include "Emu/IdManager.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellGem.h" -extern Module<> cellGem; +LOG_CHANNEL(cellGem); struct gem_t { @@ -273,43 +272,43 @@ s32 cellGemWriteExternalPort() return CELL_OK; } -Module<> cellGem("cellGem", []() +DECLARE(ppu_module_manager::cellGem)("libgem", []() { - REG_FUNC(cellGem, cellGemCalibrate); - REG_FUNC(cellGem, cellGemClearStatusFlags); - REG_FUNC(cellGem, cellGemConvertVideoFinish); - REG_FUNC(cellGem, cellGemConvertVideoStart); - REG_FUNC(cellGem, cellGemEnableCameraPitchAngleCorrection); - REG_FUNC(cellGem, cellGemEnableMagnetometer); - REG_FUNC(cellGem, cellGemEnd); - REG_FUNC(cellGem, cellGemFilterState); - REG_FUNC(cellGem, cellGemForceRGB); - REG_FUNC(cellGem, cellGemGetAccelerometerPositionInDevice); - REG_FUNC(cellGem, cellGemGetAllTrackableHues); - REG_FUNC(cellGem, cellGemGetCameraState); - REG_FUNC(cellGem, cellGemGetEnvironmentLightingColor); - REG_FUNC(cellGem, cellGemGetHuePixels); - REG_FUNC(cellGem, cellGemGetImageState); - REG_FUNC(cellGem, cellGemGetInertialState); - REG_FUNC(cellGem, cellGemGetInfo); - REG_FUNC(cellGem, cellGemGetMemorySize); - REG_FUNC(cellGem, cellGemGetRGB); - REG_FUNC(cellGem, cellGemGetRumble); - REG_FUNC(cellGem, cellGemGetState); - REG_FUNC(cellGem, cellGemGetStatusFlags); - REG_FUNC(cellGem, cellGemGetTrackerHue); - REG_FUNC(cellGem, cellGemHSVtoRGB); - REG_FUNC(cellGem, cellGemInit); - REG_FUNC(cellGem, cellGemInvalidateCalibration); - REG_FUNC(cellGem, cellGemIsTrackableHue); - REG_FUNC(cellGem, cellGemPrepareCamera); - REG_FUNC(cellGem, cellGemPrepareVideoConvert); - REG_FUNC(cellGem, cellGemReadExternalPortDeviceInfo); - REG_FUNC(cellGem, cellGemReset); - REG_FUNC(cellGem, cellGemSetRumble); - REG_FUNC(cellGem, cellGemSetYaw); - REG_FUNC(cellGem, cellGemTrackHues); - REG_FUNC(cellGem, cellGemUpdateFinish); - REG_FUNC(cellGem, cellGemUpdateStart); - REG_FUNC(cellGem, cellGemWriteExternalPort); + REG_FUNC(libgem, cellGemCalibrate); + REG_FUNC(libgem, cellGemClearStatusFlags); + REG_FUNC(libgem, cellGemConvertVideoFinish); + REG_FUNC(libgem, cellGemConvertVideoStart); + REG_FUNC(libgem, cellGemEnableCameraPitchAngleCorrection); + REG_FUNC(libgem, cellGemEnableMagnetometer); + REG_FUNC(libgem, cellGemEnd); + REG_FUNC(libgem, cellGemFilterState); + REG_FUNC(libgem, cellGemForceRGB); + REG_FUNC(libgem, cellGemGetAccelerometerPositionInDevice); + REG_FUNC(libgem, cellGemGetAllTrackableHues); + REG_FUNC(libgem, cellGemGetCameraState); + REG_FUNC(libgem, cellGemGetEnvironmentLightingColor); + REG_FUNC(libgem, cellGemGetHuePixels); + REG_FUNC(libgem, cellGemGetImageState); + REG_FUNC(libgem, cellGemGetInertialState); + REG_FUNC(libgem, cellGemGetInfo); + REG_FUNC(libgem, cellGemGetMemorySize); + REG_FUNC(libgem, cellGemGetRGB); + REG_FUNC(libgem, cellGemGetRumble); + REG_FUNC(libgem, cellGemGetState); + REG_FUNC(libgem, cellGemGetStatusFlags); + REG_FUNC(libgem, cellGemGetTrackerHue); + REG_FUNC(libgem, cellGemHSVtoRGB); + REG_FUNC(libgem, cellGemInit); + REG_FUNC(libgem, cellGemInvalidateCalibration); + REG_FUNC(libgem, cellGemIsTrackableHue); + REG_FUNC(libgem, cellGemPrepareCamera); + REG_FUNC(libgem, cellGemPrepareVideoConvert); + REG_FUNC(libgem, cellGemReadExternalPortDeviceInfo); + REG_FUNC(libgem, cellGemReset); + REG_FUNC(libgem, cellGemSetRumble); + REG_FUNC(libgem, cellGemSetYaw); + REG_FUNC(libgem, cellGemTrackHues); + REG_FUNC(libgem, cellGemUpdateFinish); + REG_FUNC(libgem, cellGemUpdateStart); + REG_FUNC(libgem, cellGemWriteExternalPort); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGem.h b/rpcs3/Emu/Cell/Modules/cellGem.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellGem.h rename to rpcs3/Emu/Cell/Modules/cellGem.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp b/rpcs3/Emu/Cell/Modules/cellGifDec.cpp similarity index 94% rename from rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp rename to rpcs3/Emu/Cell/Modules/cellGifDec.cpp index 4cef65232d..64c10ca7cf 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGifDec.cpp @@ -1,19 +1,15 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" // STB_IMAGE_IMPLEMENTATION is already defined in stb_image.cpp #include -#include "Emu/FS/VFS.h" -#include "Emu/FS/vfsFileBase.h" -#include "Emu/SysCalls/lv2/sys_fs.h" - +#include "Emu/Cell/lv2/sys_fs.h" #include "cellGifDec.h" -extern Module<> cellGifDec; +LOG_CHANNEL(cellGifDec); // cellGifDec aliases (only for cellGifDec.cpp) using PPMainHandle = vm::pptr; @@ -61,11 +57,11 @@ s32 cellGifDecOpen(PMainHandle mainHandle, PPSubHandle subHandle, PSrc src, POpe case CELL_GIFDEC_FILE: { // Get file descriptor and size - std::shared_ptr file_s(Emu.GetVFS().OpenFile(src->fileName.get_ptr(), fom::read)); + fs::file file_s(vfs::get(src->fileName.get_ptr())); if (!file_s) return CELL_GIFDEC_ERROR_OPEN_FILE; - current_subHandle.fd = idm::make(file_s, 0, 0); - current_subHandle.fileSize = file_s->GetSize(); + current_subHandle.fileSize = file_s.size(); + current_subHandle.fd = idm::make(std::move(file_s), 0, 0); break; } } @@ -102,8 +98,8 @@ s32 cellGifDecReadHeader(PMainHandle mainHandle, PSubHandle subHandle, PInfo inf case CELL_GIFDEC_FILE: { auto file = idm::get(fd); - file->file->Seek(0); - file->file->Read(buffer, sizeof(buffer)); + file->file.seek(0); + file->file.read(buffer, sizeof(buffer)); break; } } @@ -186,8 +182,8 @@ s32 cellGifDecDecodeData(PMainHandle mainHandle, PSubHandle subHandle, vm::ptr(fd); - file->file->Seek(0); - file->file->Read(gif.get(), fileSize); + file->file.seek(0); + file->file.read(gif.get(), fileSize); break; } } @@ -300,7 +296,7 @@ s32 cellGifDecDestroy(PMainHandle mainHandle) return CELL_OK; } -Module<> cellGifDec("cellGifDec", []() +DECLARE(ppu_module_manager::cellGifDec)("cellGifDec", []() { REG_FUNC(cellGifDec, cellGifDecCreate); REG_FUNC(cellGifDec, cellGifDecExtCreate); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGifDec.h b/rpcs3/Emu/Cell/Modules/cellGifDec.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellGifDec.h rename to rpcs3/Emu/Cell/Modules/cellGifDec.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellHttp.cpp b/rpcs3/Emu/Cell/Modules/cellHttp.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellHttp.cpp rename to rpcs3/Emu/Cell/Modules/cellHttp.cpp index ee6a48fcbc..46328b1cf7 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellHttp.cpp +++ b/rpcs3/Emu/Cell/Modules/cellHttp.cpp @@ -1,9 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellHttp; -extern Module<> cellHttps; +LOG_CHANNEL(cellHttp); s32 cellHttpInit() { @@ -599,7 +597,7 @@ s32 cellHttpClientSetSslIdDestroyCallback() return CELL_OK; } -Module<> cellHttp("cellHttp", []() +DECLARE(ppu_module_manager::cellHttp)("cellHttp", []() { REG_FUNC(cellHttp, cellHttpInit); REG_FUNC(cellHttp, cellHttpEnd); @@ -713,7 +711,7 @@ Module<> cellHttp("cellHttp", []() REG_FUNC(cellHttp, cellHttpClientSetSslIdDestroyCallback); }); -Module<> cellHttps("cellHttps", []() +DECLARE(ppu_module_manager::cellHttps)("cellHttps", []() { // cellHttps doesn't have functions (cellHttpsInit belongs to cellHttp, for example) }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellHttpUtil.cpp b/rpcs3/Emu/Cell/Modules/cellHttpUtil.cpp similarity index 95% rename from rpcs3/Emu/SysCalls/Modules/cellHttpUtil.cpp rename to rpcs3/Emu/Cell/Modules/cellHttpUtil.cpp index 4625593b15..35c7c5328c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellHttpUtil.cpp +++ b/rpcs3/Emu/Cell/Modules/cellHttpUtil.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellHttpUtil; +LOG_CHANNEL(cellHttpUtil); s32 cellHttpUtilParseUri() { @@ -124,7 +123,7 @@ s32 cellHttpUtilBase64Decoder() return CELL_OK; } -Module<> cellHttpUtil("cellHttpUtil", []() +DECLARE(ppu_module_manager::cellHttpUtil)("cellHttpUtil", []() { REG_FUNC(cellHttpUtil, cellHttpUtilParseUri); REG_FUNC(cellHttpUtil, cellHttpUtilParseUriPath); diff --git a/rpcs3/Emu/SysCalls/Modules/cellImejp.cpp b/rpcs3/Emu/Cell/Modules/cellImejp.cpp similarity index 62% rename from rpcs3/Emu/SysCalls/Modules/cellImejp.cpp rename to rpcs3/Emu/Cell/Modules/cellImejp.cpp index d1959b36c9..278103fd3f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellImejp.cpp +++ b/rpcs3/Emu/Cell/Modules/cellImejp.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellImeJp; +LOG_CHANNEL(cellImeJp); // Return Codes enum @@ -262,50 +261,50 @@ s32 cellImeJpConfirmPrediction() return CELL_OK; } -Module<> cellImeJp("cellImeJp", []() +DECLARE(ppu_module_manager::cellImeJp)("cellImeJpUtility", []() { - REG_FUNC(cellImeJp, cellImeJpOpen); - REG_FUNC(cellImeJp, cellImeJpOpen2); - REG_FUNC(cellImeJp, cellImeJpOpen3); - REG_FUNC(cellImeJp, cellImeJpClose); + REG_FUNC(cellImeJpUtility, cellImeJpOpen); + REG_FUNC(cellImeJpUtility, cellImeJpOpen2); + REG_FUNC(cellImeJpUtility, cellImeJpOpen3); + REG_FUNC(cellImeJpUtility, cellImeJpClose); - REG_FUNC(cellImeJp, cellImeJpSetKanaInputMode); - REG_FUNC(cellImeJp, cellImeJpSetInputCharType); - REG_FUNC(cellImeJp, cellImeJpSetFixInputMode); - REG_FUNC(cellImeJp, cellImeJpAllowExtensionCharacters); - REG_FUNC(cellImeJp, cellImeJpReset); + REG_FUNC(cellImeJpUtility, cellImeJpSetKanaInputMode); + REG_FUNC(cellImeJpUtility, cellImeJpSetInputCharType); + REG_FUNC(cellImeJpUtility, cellImeJpSetFixInputMode); + REG_FUNC(cellImeJpUtility, cellImeJpAllowExtensionCharacters); + REG_FUNC(cellImeJpUtility, cellImeJpReset); - REG_FUNC(cellImeJp, cellImeJpGetStatus); + REG_FUNC(cellImeJpUtility, cellImeJpGetStatus); - REG_FUNC(cellImeJp, cellImeJpEnterChar); - REG_FUNC(cellImeJp, cellImeJpEnterCharExt); - REG_FUNC(cellImeJp, cellImeJpEnterString); - REG_FUNC(cellImeJp, cellImeJpEnterStringExt); - REG_FUNC(cellImeJp, cellImeJpModeCaretRight); - REG_FUNC(cellImeJp, cellImeJpModeCaretLeft); - REG_FUNC(cellImeJp, cellImeJpBackspaceWord); - REG_FUNC(cellImeJp, cellImeJpDeleteWord); - REG_FUNC(cellImeJp, cellImeJpAllDeleteConvertString); - REG_FUNC(cellImeJp, cellImeJpConvertForward); - REG_FUNC(cellImeJp, cellImeJpConvertBackward); - REG_FUNC(cellImeJp, cellImeJpCurrentPartConfirm); - REG_FUNC(cellImeJp, cellImeJpAllConfirm); - REG_FUNC(cellImeJp, cellImeJpConvertCancel); - REG_FUNC(cellImeJp, cellImeJpAllConvertCancel); - REG_FUNC(cellImeJp, cellImeJpExtendConvertArea); - REG_FUNC(cellImeJp, cellImeJpShortenConvertArea); - REG_FUNC(cellImeJp, cellImeJpTemporalConfirm); - REG_FUNC(cellImeJp, cellImeJpPostConvert); - REG_FUNC(cellImeJp, cellImeJpMoveFocusClause); - REG_FUNC(cellImeJp, cellImeJpGetFocusTop); - REG_FUNC(cellImeJp, cellImeJpGetFocusLength); - REG_FUNC(cellImeJp, cellImeJpGetConfirmYomiString); - REG_FUNC(cellImeJp, cellImeJpGetConfirmString); - REG_FUNC(cellImeJp, cellImeJpGetConvertYomiString); - REG_FUNC(cellImeJp, cellImeJpGetConvertString); - REG_FUNC(cellImeJp, cellImeJpGetCandidateListSize); - REG_FUNC(cellImeJp, cellImeJpGetCandidateList); - REG_FUNC(cellImeJp, cellImeJpGetCandidateSelect); - REG_FUNC(cellImeJp, cellImeJpGetPredictList); - REG_FUNC(cellImeJp, cellImeJpConfirmPrediction); + REG_FUNC(cellImeJpUtility, cellImeJpEnterChar); + REG_FUNC(cellImeJpUtility, cellImeJpEnterCharExt); + REG_FUNC(cellImeJpUtility, cellImeJpEnterString); + REG_FUNC(cellImeJpUtility, cellImeJpEnterStringExt); + REG_FUNC(cellImeJpUtility, cellImeJpModeCaretRight); + REG_FUNC(cellImeJpUtility, cellImeJpModeCaretLeft); + REG_FUNC(cellImeJpUtility, cellImeJpBackspaceWord); + REG_FUNC(cellImeJpUtility, cellImeJpDeleteWord); + REG_FUNC(cellImeJpUtility, cellImeJpAllDeleteConvertString); + REG_FUNC(cellImeJpUtility, cellImeJpConvertForward); + REG_FUNC(cellImeJpUtility, cellImeJpConvertBackward); + REG_FUNC(cellImeJpUtility, cellImeJpCurrentPartConfirm); + REG_FUNC(cellImeJpUtility, cellImeJpAllConfirm); + REG_FUNC(cellImeJpUtility, cellImeJpConvertCancel); + REG_FUNC(cellImeJpUtility, cellImeJpAllConvertCancel); + REG_FUNC(cellImeJpUtility, cellImeJpExtendConvertArea); + REG_FUNC(cellImeJpUtility, cellImeJpShortenConvertArea); + REG_FUNC(cellImeJpUtility, cellImeJpTemporalConfirm); + REG_FUNC(cellImeJpUtility, cellImeJpPostConvert); + REG_FUNC(cellImeJpUtility, cellImeJpMoveFocusClause); + REG_FUNC(cellImeJpUtility, cellImeJpGetFocusTop); + REG_FUNC(cellImeJpUtility, cellImeJpGetFocusLength); + REG_FUNC(cellImeJpUtility, cellImeJpGetConfirmYomiString); + REG_FUNC(cellImeJpUtility, cellImeJpGetConfirmString); + REG_FUNC(cellImeJpUtility, cellImeJpGetConvertYomiString); + REG_FUNC(cellImeJpUtility, cellImeJpGetConvertString); + REG_FUNC(cellImeJpUtility, cellImeJpGetCandidateListSize); + REG_FUNC(cellImeJpUtility, cellImeJpGetCandidateList); + REG_FUNC(cellImeJpUtility, cellImeJpGetCandidateSelect); + REG_FUNC(cellImeJpUtility, cellImeJpGetPredictList); + REG_FUNC(cellImeJpUtility, cellImeJpConfirmPrediction); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp b/rpcs3/Emu/Cell/Modules/cellJpgDec.cpp similarity index 94% rename from rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp rename to rpcs3/Emu/Cell/Modules/cellJpgDec.cpp index 0c5ded73b9..3fcb2a967e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellJpgDec.cpp @@ -1,19 +1,15 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" // STB_IMAGE_IMPLEMENTATION is already defined in stb_image.cpp #include -#include "Emu/FS/VFS.h" -#include "Emu/FS/vfsFileBase.h" -#include "Emu/SysCalls/lv2/sys_fs.h" - +#include "Emu/Cell/lv2/sys_fs.h" #include "cellJpgDec.h" -extern Module<> cellJpgDec; +LOG_CHANNEL(cellJpgDec); s32 cellJpgDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam) { @@ -51,11 +47,11 @@ s32 cellJpgDecOpen(u32 mainHandle, vm::ptr subHandle, vm::ptr file_s(Emu.GetVFS().OpenFile(src->fileName.get_ptr(), fom::read)); + fs::file file_s(vfs::get(src->fileName.get_ptr())); if (!file_s) return CELL_JPGDEC_ERROR_OPEN_FILE; - current_subHandle.fd = idm::make(file_s, 0, 0); - current_subHandle.fileSize = file_s->GetSize(); + current_subHandle.fileSize = file_s.size(); + current_subHandle.fd = idm::make(std::move(file_s), 0, 0); break; } } @@ -115,8 +111,8 @@ s32 cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr case CELL_JPGDEC_FILE: { auto file = idm::get(fd); - file->file->Seek(0); - file->file->Read(buffer.get(), fileSize); + file->file.seek(0); + file->file.read(buffer.get(), fileSize); break; } } @@ -194,8 +190,8 @@ s32 cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::cp case CELL_JPGDEC_FILE: { auto file = idm::get(fd); - file->file->Seek(0); - file->file->Read(jpg.get(), fileSize); + file->file.seek(0); + file->file.read(jpg.get(), fileSize); break; } } @@ -357,7 +353,7 @@ s32 cellJpgDecExtSetParameter() } -Module<> cellJpgDec("cellJpgDec", []() +DECLARE(ppu_module_manager::cellJpgDec)("cellJpgDec", []() { REG_FUNC(cellJpgDec, cellJpgDecCreate); REG_FUNC(cellJpgDec, cellJpgDecExtCreate); diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.h b/rpcs3/Emu/Cell/Modules/cellJpgDec.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellJpgDec.h rename to rpcs3/Emu/Cell/Modules/cellJpgDec.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgEnc.cpp b/rpcs3/Emu/Cell/Modules/cellJpgEnc.cpp similarity index 92% rename from rpcs3/Emu/SysCalls/Modules/cellJpgEnc.cpp rename to rpcs3/Emu/Cell/Modules/cellJpgEnc.cpp index 2b91af18b4..605a04e930 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgEnc.cpp +++ b/rpcs3/Emu/Cell/Modules/cellJpgEnc.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellJpgEnc; +LOG_CHANNEL(cellJpgEnc); // Error Codes enum @@ -75,7 +74,7 @@ s32 cellJpgEncReset() return CELL_OK; } -Module<> cellJpgEnc("cellJpgEnc", []() +DECLARE(ppu_module_manager::cellJpgEnc)("cellJpgEnc", []() { REG_FUNC(cellJpgEnc, cellJpgEncQueryAttr); REG_FUNC(cellJpgEnc, cellJpgEncOpen); diff --git a/rpcs3/Emu/SysCalls/Modules/cellKb.cpp b/rpcs3/Emu/Cell/Modules/cellKb.cpp similarity index 81% rename from rpcs3/Emu/SysCalls/Modules/cellKb.cpp rename to rpcs3/Emu/Cell/Modules/cellKb.cpp index bab63108c2..a4647993b1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellKb.cpp +++ b/rpcs3/Emu/Cell/Modules/cellKb.cpp @@ -1,35 +1,37 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/IdManager.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/Io/Keyboard.h" +#include "Emu/Io/KeyboardHandler.h" #include "cellKb.h" -extern Module<> sys_io; +extern _log::channel sys_io; s32 cellKbInit(u32 max_connect) { sys_io.warning("cellKbInit(max_connect=%d)", max_connect); - if (Emu.GetKeyboardManager().IsInited()) - return CELL_KB_ERROR_ALREADY_INITIALIZED; if (max_connect > 7) return CELL_KB_ERROR_INVALID_PARAMETER; - Emu.GetKeyboardManager().Init(max_connect); + const auto handler = fxm::import(PURE_EXPR(Emu.GetCallbacks().get_kb_handler())); + + if (!handler) + return CELL_KB_ERROR_ALREADY_INITIALIZED; + + handler->Init(max_connect); return CELL_OK; } s32 cellKbEnd() { - sys_io.trace("cellKbEnd()"); + sys_io.notice("cellKbEnd()"); - if (!Emu.GetKeyboardManager().IsInited()) + if (!fxm::remove()) return CELL_KB_ERROR_UNINITIALIZED; - Emu.GetKeyboardManager().Close(); return CELL_OK; } @@ -37,10 +39,12 @@ s32 cellKbClearBuf(u32 port_no) { sys_io.trace("cellKbClearBuf(port_no=%d)", port_no); - if (!Emu.GetKeyboardManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - if (port_no >= Emu.GetKeyboardManager().GetKeyboards().size()) + if (port_no >= handler->GetKeyboards().size()) return CELL_KB_ERROR_INVALID_PARAMETER; //? @@ -98,10 +102,12 @@ s32 cellKbGetInfo(vm::ptr info) { sys_io.trace("cellKbGetInfo(info=*0x%x)", info); - if (!Emu.GetKeyboardManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - const KbInfo& current_info = Emu.GetKeyboardManager().GetInfo(); + const KbInfo& current_info = handler->GetInfo(); info->max_connect = current_info.max_connect; info->now_connect = current_info.now_connect; info->info = current_info.info; @@ -118,14 +124,17 @@ s32 cellKbRead(u32 port_no, vm::ptr data) { sys_io.trace("cellKbRead(port_no=%d, data=*0x%x)", port_no, data); - const std::vector& keyboards = Emu.GetKeyboardManager().GetKeyboards(); - if (!Emu.GetKeyboardManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_KB_ERROR_UNINITIALIZED; + const std::vector& keyboards = handler->GetKeyboards(); + if (port_no >= keyboards.size()) return CELL_KB_ERROR_INVALID_PARAMETER; - KbData& current_data = Emu.GetKeyboardManager().GetData(port_no); + KbData& current_data = handler->GetData(port_no); data->led = current_data.led; data->mkey = current_data.mkey; data->len = std::min((u32)current_data.len, CELL_KB_MAX_KEYCODES); @@ -144,10 +153,12 @@ s32 cellKbSetCodeType(u32 port_no, u32 type) { sys_io.trace("cellKbSetCodeType(port_no=%d,type=%d)", port_no, type); - if (!Emu.GetKeyboardManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - KbConfig& current_config = Emu.GetKeyboardManager().GetConfig(port_no); + KbConfig& current_config = handler->GetConfig(port_no); current_config.code_type = type; return CELL_OK; } @@ -162,10 +173,12 @@ s32 cellKbSetReadMode(u32 port_no, u32 rmode) { sys_io.trace("cellKbSetReadMode(port_no=%d,rmode=%d)", port_no, rmode); - if (!Emu.GetKeyboardManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - KbConfig& current_config = Emu.GetKeyboardManager().GetConfig(port_no); + KbConfig& current_config = handler->GetConfig(port_no); current_config.read_mode = rmode; return CELL_OK; @@ -175,10 +188,12 @@ s32 cellKbGetConfiguration(u32 port_no, vm::ptr config) { sys_io.trace("cellKbGetConfiguration(port_no=%d, config=*0x%x)", port_no, config); - if (!Emu.GetKeyboardManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - const KbConfig& current_config = Emu.GetKeyboardManager().GetConfig(port_no); + const KbConfig& current_config = handler->GetConfig(port_no); config->arrange = current_config.arrange; config->read_mode = current_config.read_mode; config->code_type = current_config.code_type; diff --git a/rpcs3/Emu/SysCalls/Modules/cellKb.h b/rpcs3/Emu/Cell/Modules/cellKb.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellKb.h rename to rpcs3/Emu/Cell/Modules/cellKb.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellKey2char.cpp b/rpcs3/Emu/Cell/Modules/cellKey2char.cpp similarity index 88% rename from rpcs3/Emu/SysCalls/Modules/cellKey2char.cpp rename to rpcs3/Emu/Cell/Modules/cellKey2char.cpp index 72979257f6..3a51a3c347 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellKey2char.cpp +++ b/rpcs3/Emu/Cell/Modules/cellKey2char.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellKey2char; +LOG_CHANNEL(cellKey2char); // Return Codes enum @@ -46,7 +45,7 @@ s32 cellKey2CharSetArrangement() return CELL_OK; } -Module<> cellKey2char("cellKey2char", []() +DECLARE(ppu_module_manager::cellKey2char)("cellKey2char", []() { REG_FUNC(cellKey2char, cellKey2CharOpen); REG_FUNC(cellKey2char, cellKey2CharClose); diff --git a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp b/rpcs3/Emu/Cell/Modules/cellL10n.cpp similarity index 99% rename from rpcs3/Emu/SysCalls/Modules/cellL10n.cpp rename to rpcs3/Emu/Cell/Modules/cellL10n.cpp index ad209aecfc..73ec6cad6c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp +++ b/rpcs3/Emu/Cell/Modules/cellL10n.cpp @@ -1,9 +1,8 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #ifdef _WIN32 -#include +#include #endif #ifdef _MSC_VER @@ -15,7 +14,7 @@ typedef const char *HostCode; #include "cellL10n.h" -extern Module<> cellL10n; +LOG_CHANNEL(cellL10n); // Translate code id to code name. some codepage may has another name. // If this makes your compilation fail, try replace the string code with one in "iconv -l" @@ -1061,7 +1060,7 @@ s32 UTF8toBIG5() s32 UTF16stoUTF8s(vm::cptr utf16, vm::ref utf16_len, vm::ptr utf8, vm::ref utf8_len) { - cellL10n.error("UTF16stoUTF8s(utf16=*0x%x, utf16_len=*0x%x, utf8=*0x%x, utf8_len=*0x%x)", utf16, utf16_len, utf8, utf8_len); + cellL10n.error("UTF16stoUTF8s(utf16=*0x%x, utf16_len=*0x%x, utf8=*0x%x, utf8_len=*0x%x)", utf16, utf16_len.addr(), utf8, utf8_len.addr()); const u32 max_len = utf8_len; utf8_len = 0; @@ -1170,7 +1169,7 @@ s32 UTF8stoUCS2s() } -Module<> cellL10n("cellL10n", []() +DECLARE(ppu_module_manager::cellL10n)("cellL10n", []() { REG_FUNC(cellL10n, UCS2toEUCJP); REG_FUNC(cellL10n, l10n_convert); diff --git a/rpcs3/Emu/SysCalls/Modules/cellL10n.h b/rpcs3/Emu/Cell/Modules/cellL10n.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellL10n.h rename to rpcs3/Emu/Cell/Modules/cellL10n.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellMic.cpp b/rpcs3/Emu/Cell/Modules/cellMic.cpp similarity index 97% rename from rpcs3/Emu/SysCalls/Modules/cellMic.cpp rename to rpcs3/Emu/Cell/Modules/cellMic.cpp index e5e3a9bce5..b0cd2b8ba7 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMic.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMic.cpp @@ -1,11 +1,10 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellMic.h" -extern Module<> cellMic; +LOG_CHANNEL(cellMic); s32 cellMicInit() { @@ -260,13 +259,12 @@ s32 cellMicGetDeviceIdentifier() return CELL_OK; } -Module<> cellMic("cellMic", []() +DECLARE(ppu_module_manager::cellMic)("cellMic", []() { REG_FUNC(cellMic, cellMicInit); REG_FUNC(cellMic, cellMicEnd); REG_FUNC(cellMic, cellMicOpen); REG_FUNC(cellMic, cellMicClose); - REG_FUNC(cellMic, cellMicGetDeviceGUID); REG_FUNC(cellMic, cellMicGetType); REG_FUNC(cellMic, cellMicIsAttached); @@ -276,16 +274,13 @@ Module<> cellMic("cellMic", []() REG_FUNC(cellMic, cellMicGetSignalAttr); REG_FUNC(cellMic, cellMicSetSignalAttr); REG_FUNC(cellMic, cellMicGetSignalState); - REG_FUNC(cellMic, cellMicStart); REG_FUNC(cellMic, cellMicRead); REG_FUNC(cellMic, cellMicStop); REG_FUNC(cellMic, cellMicReset); - REG_FUNC(cellMic, cellMicSetNotifyEventQueue); REG_FUNC(cellMic, cellMicSetNotifyEventQueue2); REG_FUNC(cellMic, cellMicRemoveNotifyEventQueue); - REG_FUNC(cellMic, cellMicOpenEx); REG_FUNC(cellMic, cellMicStartEx); REG_FUNC(cellMic, cellMicGetFormatRaw); @@ -295,7 +290,6 @@ Module<> cellMic("cellMic", []() REG_FUNC(cellMic, cellMicReadRaw); REG_FUNC(cellMic, cellMicReadAux); REG_FUNC(cellMic, cellMicReadDsp); - REG_FUNC(cellMic, cellMicGetStatus); REG_FUNC(cellMic, cellMicStopEx); // this function shouldn't exist REG_FUNC(cellMic, cellMicSysShareClose); diff --git a/rpcs3/Emu/SysCalls/Modules/cellMic.h b/rpcs3/Emu/Cell/Modules/cellMic.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellMic.h rename to rpcs3/Emu/Cell/Modules/cellMic.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellMouse.cpp b/rpcs3/Emu/Cell/Modules/cellMouse.cpp similarity index 71% rename from rpcs3/Emu/SysCalls/Modules/cellMouse.cpp rename to rpcs3/Emu/Cell/Modules/cellMouse.cpp index e4aae28a40..e9cea73dc8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMouse.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMouse.cpp @@ -1,42 +1,45 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/IdManager.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/Io/Mouse.h" +#include "Emu/Io/MouseHandler.h" #include "cellMouse.h" -extern Module<> sys_io; +extern _log::channel sys_io; s32 cellMouseInit(u32 max_connect) { sys_io.warning("cellMouseInit(max_connect=%d)", max_connect); - if (Emu.GetMouseManager().IsInited()) - { - return CELL_MOUSE_ERROR_ALREADY_INITIALIZED; - } - if (max_connect > 7) { return CELL_MOUSE_ERROR_INVALID_PARAMETER; } - Emu.GetMouseManager().Init(max_connect); + const auto handler = fxm::import(PURE_EXPR(Emu.GetCallbacks().get_mouse_handler())); + + if (!handler) + { + return CELL_MOUSE_ERROR_ALREADY_INITIALIZED; + } + + handler->Init(max_connect); return CELL_OK; } - s32 cellMouseClearBuf(u32 port_no) { sys_io.trace("cellMouseClearBuf(port_no=%d)", port_no); - if (!Emu.GetMouseManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) { return CELL_MOUSE_ERROR_UNINITIALIZED; } - if (port_no >= Emu.GetMouseManager().GetMice().size()) + if (port_no >= handler->GetMice().size()) { return CELL_MOUSE_ERROR_INVALID_PARAMETER; } @@ -48,14 +51,13 @@ s32 cellMouseClearBuf(u32 port_no) s32 cellMouseEnd() { - sys_io.trace("cellMouseEnd()"); + sys_io.notice("cellMouseEnd()"); - if (!Emu.GetMouseManager().IsInited()) + if (!fxm::remove()) { return CELL_MOUSE_ERROR_UNINITIALIZED; } - Emu.GetMouseManager().Close(); return CELL_OK; } @@ -63,12 +65,14 @@ s32 cellMouseGetInfo(vm::ptr info) { sys_io.trace("cellMouseGetInfo(info=*0x%x)", info); - if (!Emu.GetMouseManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) { return CELL_MOUSE_ERROR_UNINITIALIZED; } - const MouseInfo& current_info = Emu.GetMouseManager().GetInfo(); + const MouseInfo& current_info = handler->GetInfo(); info->max_connect = current_info.max_connect; info->now_connect = current_info.now_connect; info->info = current_info.info; @@ -82,12 +86,15 @@ s32 cellMouseGetInfo(vm::ptr info) s32 cellMouseInfoTabletMode(u32 port_no, vm::ptr info) { sys_io.trace("cellMouseInfoTabletMode(port_no=%d, info=*0x%x)", port_no, info); - if (!Emu.GetMouseManager().IsInited()) + + const auto handler = fxm::get(); + + if (!handler) { return CELL_MOUSE_ERROR_UNINITIALIZED; } - if (port_no >= Emu.GetMouseManager().GetMice().size()) + if (port_no >= handler->GetMice().size()) { return CELL_MOUSE_ERROR_INVALID_PARAMETER; } @@ -101,16 +108,20 @@ s32 cellMouseInfoTabletMode(u32 port_no, vm::ptr info) s32 cellMouseGetData(u32 port_no, vm::ptr data) { sys_io.trace("cellMouseGetData(port_no=%d, data=*0x%x)", port_no, data); - if (!Emu.GetMouseManager().IsInited()) + + const auto handler = fxm::get(); + + if (!handler) { return CELL_MOUSE_ERROR_UNINITIALIZED; } - if (port_no >= Emu.GetMouseManager().GetMice().size()) + + if (port_no >= handler->GetMice().size()) { return CELL_MOUSE_ERROR_NO_DEVICE; } - MouseData& current_data = Emu.GetMouseManager().GetData(port_no); + MouseData& current_data = handler->GetData(port_no); data->update = current_data.update; data->buttons = current_data.buttons; data->x_axis = current_data.x_axis; @@ -147,20 +158,21 @@ s32 cellMouseGetTabletDataList(u32 port_no, u32 data_addr) return CELL_OK; } -s32 cellMouseGetRawData(u32 port_no, vm::ptr data) +s32 cellMouseGetRawData(u32 port_no, vm::ptr data) { sys_io.todo("cellMouseGetRawData(port_no=%d, data=*0x%x)", port_no, data); - /*if (!Emu.GetMouseManager().IsInited()) return CELL_MOUSE_ERROR_UNINITIALIZED; - if (port_no >= Emu.GetMouseManager().GetMice().size()) return CELL_MOUSE_ERROR_NO_DEVICE; - CellMouseRawData& current_rawdata = Emu.GetMouseManager().GetRawData(port_no); - data += current_rawdata.len; - for(s32 i=0; i(); + + if (!handler) { - data += current_rawdata.data[i]; + return CELL_MOUSE_ERROR_UNINITIALIZED; } - current_rawdata.len = 0;*/ + if (port_no >= handler->GetMice().size()) + { + return CELL_MOUSE_ERROR_NO_DEVICE; + } return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellMouse.h b/rpcs3/Emu/Cell/Modules/cellMouse.h similarity index 93% rename from rpcs3/Emu/SysCalls/Modules/cellMouse.h rename to rpcs3/Emu/Cell/Modules/cellMouse.h index 3831a6bea3..61b384f18e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMouse.h +++ b/rpcs3/Emu/Cell/Modules/cellMouse.h @@ -51,3 +51,9 @@ struct CellMouseDataList }; static const u32 CELL_MOUSE_MAX_CODES = 64; + +struct CellMouseRawData +{ + be_t len; + u8 data[CELL_MOUSE_MAX_CODES]; +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp similarity index 94% rename from rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp rename to rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp index bbba03473d..9718fa9a95 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp @@ -1,14 +1,14 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/Cell/PPUModule.h" #include "cellSysutil.h" #include "cellMsgDialog.h" -extern Module<> cellSysutil; +#include + +extern _log::channel cellSysutil; s32 cellMsgDialogOpen() { @@ -61,7 +61,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr msgString, vm::ptr(WRAP_EXPR(Emu.GetCallbacks().get_msg_dialog())); + const auto dlg = fxm::import(PURE_EXPR(Emu.GetCallbacks().get_msg_dialog())); if (!dlg) { @@ -103,8 +103,21 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr msgString, vm::ptrCreate(msgString.get_ptr()))).get(); + // Make "shared" promise to workaround std::function limitation + auto spr = std::make_shared>(); + + // Get future + std::future future = spr->get_future(); + + // Run asynchronously in GUI thread + Emu.CallAfter([&, spr = std::move(spr)]() + { + dlg->Create(msgString.get_ptr()); + spr->set_value(); + }); + + // Wait for the "result" + future.get(); return CELL_OK; } @@ -206,7 +219,7 @@ s32 cellMsgDialogClose(f32 delay) const u64 wait_until = get_system_time() + static_cast(std::max(delay, 0.0f) * 1000); - thread_ctrl::spawn(PURE_EXPR("MsgDialog Thread"s), [=]() + thread_ctrl::spawn("MsgDialog Thread", [=]() { while (dlg->state == MsgDialogState::Open && get_system_time() < wait_until) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h b/rpcs3/Emu/Cell/Modules/cellMsgDialog.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h rename to rpcs3/Emu/Cell/Modules/cellMsgDialog.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellMusic.cpp b/rpcs3/Emu/Cell/Modules/cellMusic.cpp similarity index 61% rename from rpcs3/Emu/SysCalls/Modules/cellMusic.cpp rename to rpcs3/Emu/Cell/Modules/cellMusic.cpp index 38525e4f7d..6fe8cd4146 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMusic.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMusic.cpp @@ -1,13 +1,11 @@ #include "stdafx.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Callback.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellMusic.h" -extern Module<> cellMusic; +LOG_CHANNEL(cellMusic); struct music2_t { @@ -144,28 +142,28 @@ s32 cellMusicGetVolume2() } -Module<> cellMusic("cellMusic", []() +DECLARE(ppu_module_manager::cellMusic)("cellMusicUtility", []() { - REG_FUNC(cellMusic, cellMusicGetSelectionContext); - REG_FUNC(cellMusic, cellMusicSetSelectionContext2); - REG_FUNC(cellMusic, cellMusicSetVolume2); - REG_FUNC(cellMusic, cellMusicGetContentsId); - REG_FUNC(cellMusic, cellMusicSetSelectionContext); - REG_FUNC(cellMusic, cellMusicInitialize2SystemWorkload); - REG_FUNC(cellMusic, cellMusicGetPlaybackStatus2); - REG_FUNC(cellMusic, cellMusicGetContentsId2); - REG_FUNC(cellMusic, cellMusicFinalize); - REG_FUNC(cellMusic, cellMusicInitializeSystemWorkload); - REG_FUNC(cellMusic, cellMusicInitialize); - REG_FUNC(cellMusic, cellMusicFinalize2); - REG_FUNC(cellMusic, cellMusicGetSelectionContext2); - REG_FUNC(cellMusic, cellMusicGetVolume); - REG_FUNC(cellMusic, cellMusicGetPlaybackStatus); - REG_FUNC(cellMusic, cellMusicSetPlaybackCommand2); - REG_FUNC(cellMusic, cellMusicSetPlaybackCommand); - REG_FUNC(cellMusic, cellMusicSelectContents2); - REG_FUNC(cellMusic, cellMusicSelectContents); - REG_FUNC(cellMusic, cellMusicInitialize2); - REG_FUNC(cellMusic, cellMusicSetVolume); - REG_FUNC(cellMusic, cellMusicGetVolume2); + REG_FUNC(cellMusicUtility, cellMusicGetSelectionContext); + REG_FUNC(cellMusicUtility, cellMusicSetSelectionContext2); + REG_FUNC(cellMusicUtility, cellMusicSetVolume2); + REG_FUNC(cellMusicUtility, cellMusicGetContentsId); + REG_FUNC(cellMusicUtility, cellMusicSetSelectionContext); + REG_FUNC(cellMusicUtility, cellMusicInitialize2SystemWorkload); + REG_FUNC(cellMusicUtility, cellMusicGetPlaybackStatus2); + REG_FUNC(cellMusicUtility, cellMusicGetContentsId2); + REG_FUNC(cellMusicUtility, cellMusicFinalize); + REG_FUNC(cellMusicUtility, cellMusicInitializeSystemWorkload); + REG_FUNC(cellMusicUtility, cellMusicInitialize); + REG_FUNC(cellMusicUtility, cellMusicFinalize2); + REG_FUNC(cellMusicUtility, cellMusicGetSelectionContext2); + REG_FUNC(cellMusicUtility, cellMusicGetVolume); + REG_FUNC(cellMusicUtility, cellMusicGetPlaybackStatus); + REG_FUNC(cellMusicUtility, cellMusicSetPlaybackCommand2); + REG_FUNC(cellMusicUtility, cellMusicSetPlaybackCommand); + REG_FUNC(cellMusicUtility, cellMusicSelectContents2); + REG_FUNC(cellMusicUtility, cellMusicSelectContents); + REG_FUNC(cellMusicUtility, cellMusicInitialize2); + REG_FUNC(cellMusicUtility, cellMusicSetVolume); + REG_FUNC(cellMusicUtility, cellMusicGetVolume2); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellMusic.h b/rpcs3/Emu/Cell/Modules/cellMusic.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellMusic.h rename to rpcs3/Emu/Cell/Modules/cellMusic.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellMusicDecode.cpp b/rpcs3/Emu/Cell/Modules/cellMusicDecode.cpp similarity index 65% rename from rpcs3/Emu/SysCalls/Modules/cellMusicDecode.cpp rename to rpcs3/Emu/Cell/Modules/cellMusicDecode.cpp index 0d86d8c1d5..dcb43e75a8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMusicDecode.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMusicDecode.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellMusicDecode; +LOG_CHANNEL(cellMusicDecode); // Return Codes enum @@ -145,27 +144,27 @@ s32 cellMusicDecodeGetContentsId2() } -Module<> cellMusicDecode("cellMusicDecode", []() +DECLARE(ppu_module_manager::cellMusicDecode)("cellMusicDecodeUtility", []() { - REG_FUNC(cellMusicDecode, cellMusicDecodeInitialize); - REG_FUNC(cellMusicDecode, cellMusicDecodeInitializeSystemWorkload); - REG_FUNC(cellMusicDecode, cellMusicDecodeFinalize); - REG_FUNC(cellMusicDecode, cellMusicDecodeSelectContents); - REG_FUNC(cellMusicDecode, cellMusicDecodeSetDecodeCommand); - REG_FUNC(cellMusicDecode, cellMusicDecodeGetDecodeStatus); - REG_FUNC(cellMusicDecode, cellMusicDecodeRead); - REG_FUNC(cellMusicDecode, cellMusicDecodeGetSelectionContext); - REG_FUNC(cellMusicDecode, cellMusicDecodeSetSelectionContext); - REG_FUNC(cellMusicDecode, cellMusicDecodeGetContentsId); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeInitialize); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeInitializeSystemWorkload); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeFinalize); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeSelectContents); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeSetDecodeCommand); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeGetDecodeStatus); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeRead); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeGetSelectionContext); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeSetSelectionContext); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeGetContentsId); - REG_FUNC(cellMusicDecode, cellMusicDecodeInitialize2); - REG_FUNC(cellMusicDecode, cellMusicDecodeInitialize2SystemWorkload); - REG_FUNC(cellMusicDecode, cellMusicDecodeFinalize2); - REG_FUNC(cellMusicDecode, cellMusicDecodeSelectContents2); - REG_FUNC(cellMusicDecode, cellMusicDecodeSetDecodeCommand2); - REG_FUNC(cellMusicDecode, cellMusicDecodeGetDecodeStatus2); - REG_FUNC(cellMusicDecode, cellMusicDecodeRead2); - REG_FUNC(cellMusicDecode, cellMusicDecodeGetSelectionContext2); - REG_FUNC(cellMusicDecode, cellMusicDecodeSetSelectionContext2); - REG_FUNC(cellMusicDecode, cellMusicDecodeGetContentsId2); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeInitialize2); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeInitialize2SystemWorkload); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeFinalize2); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeSelectContents2); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeSetDecodeCommand2); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeGetDecodeStatus2); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeRead2); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeGetSelectionContext2); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeSetSelectionContext2); + REG_FUNC(cellMusicDecodeUtility, cellMusicDecodeGetContentsId2); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellMusicExport.cpp b/rpcs3/Emu/Cell/Modules/cellMusicExport.cpp similarity index 72% rename from rpcs3/Emu/SysCalls/Modules/cellMusicExport.cpp rename to rpcs3/Emu/Cell/Modules/cellMusicExport.cpp index 690188e000..0c614e907e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMusicExport.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMusicExport.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellMusicExport; +LOG_CHANNEL(cellMusicExport); // Return Codes enum @@ -51,11 +50,11 @@ s32 cellMusicExportProgress() return CELL_OK; } -Module<> cellMusicExport("cellMusicExport", []() +DECLARE(ppu_module_manager::cellMusicExport)("cellMusicExportUtility", []() { - REG_FUNC(cellMusicExport, cellMusicExportInitialize); - REG_FUNC(cellMusicExport, cellMusicExportInitialize2); - REG_FUNC(cellMusicExport, cellMusicExportFinalize); - REG_FUNC(cellMusicExport, cellMusicExportFromFile); - REG_FUNC(cellMusicExport, cellMusicExportProgress); + REG_FUNC(cellMusicExportUtility, cellMusicExportInitialize); + REG_FUNC(cellMusicExportUtility, cellMusicExportInitialize2); + REG_FUNC(cellMusicExportUtility, cellMusicExportFinalize); + REG_FUNC(cellMusicExportUtility, cellMusicExportFromFile); + REG_FUNC(cellMusicExportUtility, cellMusicExportProgress); }); diff --git a/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp b/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp new file mode 100644 index 0000000000..361daa9849 --- /dev/null +++ b/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp @@ -0,0 +1,211 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/Cell/PPUModule.h" + +#include "cellSysutil.h" +#include "cellNetCtl.h" + +LOG_CHANNEL(cellNetCtl); + +cfg::map_entry g_cfg_net_status(cfg::root.net, "Connection status", +{ + { "Disconnected", CELL_NET_CTL_STATE_Disconnected }, + { "Connecting", CELL_NET_CTL_STATE_Connecting }, + { "Obtaining IP", CELL_NET_CTL_STATE_IPObtaining }, + { "IP Obtained", CELL_NET_CTL_STATE_IPObtained }, +}); + +cfg::string_entry g_cfg_net_ip_address(cfg::root.net, "IP address", "192.168.1.1"); + +s32 cellNetCtlInit() +{ + cellNetCtl.warning("cellNetCtlInit()"); + + return CELL_OK; +} + +s32 cellNetCtlTerm() +{ + cellNetCtl.warning("cellNetCtlTerm()"); + + return CELL_OK; +} + +s32 cellNetCtlGetState(vm::ptr state) +{ + cellNetCtl.trace("cellNetCtlGetState(state=*0x%x)", state); + + *state = g_cfg_net_status.get(); + return CELL_OK; +} + +s32 cellNetCtlAddHandler(vm::ptr handler, vm::ptr arg, vm::ptr hid) +{ + cellNetCtl.todo("cellNetCtlAddHandler(handler=*0x%x, arg=*0x%x, hid=*0x%x)", handler, arg, hid); + + return CELL_OK; +} + +s32 cellNetCtlDelHandler(s32 hid) +{ + cellNetCtl.todo("cellNetCtlDelHandler(hid=0x%x)", hid); + + return CELL_OK; +} + +s32 cellNetCtlGetInfo(s32 code, vm::ptr info) +{ + cellNetCtl.todo("cellNetCtlGetInfo(code=0x%x (%s), info=*0x%x)", code, InfoCodeToName(code), info); + + if (code == CELL_NET_CTL_INFO_MTU) + { + info->mtu = 1500; + } + else if (code == CELL_NET_CTL_INFO_LINK) + { + if (g_cfg_net_status.get() != CELL_NET_CTL_STATE_Disconnected) + { + info->link = CELL_NET_CTL_LINK_CONNECTED; + } + else + { + info->link = CELL_NET_CTL_LINK_DISCONNECTED; + } + } + else if (code == CELL_NET_CTL_INFO_IP_ADDRESS) + { + if (g_cfg_net_status.get() != CELL_NET_CTL_STATE_IPObtained) + { + // 0.0.0.0 seems to be the default address when no ethernet cables are connected to the PS3 + strcpy_trunc(info->ip_address, "0.0.0.0"); + } + else + { + strcpy_trunc(info->ip_address, g_cfg_net_ip_address); + } + } + else if (code == CELL_NET_CTL_INFO_NETMASK) + { + strcpy_trunc(info->netmask, "255.255.255.255"); + } + + return CELL_OK; +} + +s32 cellNetCtlNetStartDialogLoadAsync(vm::ptr param) +{ + cellNetCtl.error("cellNetCtlNetStartDialogLoadAsync(param=*0x%x)", param); + + // TODO: Actually sign into PSN or an emulated network similar to PSN (ESN) + // TODO: Properly open the dialog prompt for sign in + sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_LOADED, 0); + sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED, 0); + + return CELL_OK; +} + +s32 cellNetCtlNetStartDialogAbortAsync() +{ + cellNetCtl.error("cellNetCtlNetStartDialogAbortAsync()"); + + return CELL_OK; +} + +s32 cellNetCtlNetStartDialogUnloadAsync(vm::ptr result) +{ + cellNetCtl.warning("cellNetCtlNetStartDialogUnloadAsync(result=*0x%x)", result); + + result->result = CELL_NET_CTL_ERROR_DIALOG_CANCELED; + sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_UNLOADED, 0); + + return CELL_OK; +} + +s32 cellNetCtlGetNatInfo(vm::ptr natInfo) +{ + cellNetCtl.todo("cellNetCtlGetNatInfo(natInfo=*0x%x)", natInfo); + + if (natInfo->size == 0) + { + cellNetCtl.error("cellNetCtlGetNatInfo : CELL_NET_CTL_ERROR_INVALID_SIZE"); + return CELL_NET_CTL_ERROR_INVALID_SIZE; + } + + return CELL_OK; +} + +s32 cellGameUpdateInit() +{ + throw EXCEPTION(""); +} + +s32 cellGameUpdateTerm() +{ + throw EXCEPTION(""); +} + + +s32 cellGameUpdateCheckStartAsync() +{ + throw EXCEPTION(""); +} + +s32 cellGameUpdateCheckFinishAsync() +{ + throw EXCEPTION(""); +} + +s32 cellGameUpdateCheckStartWithoutDialogAsync() +{ + throw EXCEPTION(""); +} + +s32 cellGameUpdateCheckAbort() +{ + throw EXCEPTION(""); +} + +s32 cellGameUpdateCheckStartAsyncEx() +{ + throw EXCEPTION(""); +} + +s32 cellGameUpdateCheckFinishAsyncEx() +{ + throw EXCEPTION(""); +} + +s32 cellGameUpdateCheckStartWithoutDialogAsyncEx() +{ + throw EXCEPTION(""); +} + + +DECLARE(ppu_module_manager::cellNetCtl)("cellNetCtl", []() +{ + REG_FUNC(cellNetCtl, cellNetCtlInit); + REG_FUNC(cellNetCtl, cellNetCtlTerm); + + REG_FUNC(cellNetCtl, cellNetCtlGetState); + REG_FUNC(cellNetCtl, cellNetCtlAddHandler); + REG_FUNC(cellNetCtl, cellNetCtlDelHandler); + + REG_FUNC(cellNetCtl, cellNetCtlGetInfo); + + REG_FUNC(cellNetCtl, cellNetCtlNetStartDialogLoadAsync); + REG_FUNC(cellNetCtl, cellNetCtlNetStartDialogAbortAsync); + REG_FUNC(cellNetCtl, cellNetCtlNetStartDialogUnloadAsync); + + REG_FUNC(cellNetCtl, cellNetCtlGetNatInfo); + + REG_FUNC(cellNetCtl, cellGameUpdateInit); + REG_FUNC(cellNetCtl, cellGameUpdateTerm); + + REG_FUNC(cellNetCtl, cellGameUpdateCheckStartAsync); + REG_FUNC(cellNetCtl, cellGameUpdateCheckFinishAsync); + REG_FUNC(cellNetCtl, cellGameUpdateCheckStartWithoutDialogAsync); + REG_FUNC(cellNetCtl, cellGameUpdateCheckAbort); + REG_FUNC(cellNetCtl, cellGameUpdateCheckStartAsyncEx); + REG_FUNC(cellNetCtl, cellGameUpdateCheckFinishAsyncEx); + REG_FUNC(cellNetCtl, cellGameUpdateCheckStartWithoutDialogAsyncEx); +}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.h b/rpcs3/Emu/Cell/Modules/cellNetCtl.h similarity index 97% rename from rpcs3/Emu/SysCalls/Modules/cellNetCtl.h rename to rpcs3/Emu/Cell/Modules/cellNetCtl.h index 4e08262927..28900f7a56 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.h +++ b/rpcs3/Emu/Cell/Modules/cellNetCtl.h @@ -220,19 +220,19 @@ union CellNetCtlInfo CellNetCtlSSID ssid; be_t wlan_security; be_t auth_8021x_type; - s8 auth_8021x_auth_name[128]; + char auth_8021x_auth_name[128]; u8 rssi; u8 channel; be_t ip_config; - s8 dhcp_hostname[256]; - s8 pppoe_auth_name[128]; + char dhcp_hostname[256]; + char pppoe_auth_name[128]; char ip_address[16]; - s8 netmask[16]; - s8 default_route[16]; - s8 primary_dns[16]; - s8 secondary_dns[16]; + char netmask[16]; + char default_route[16]; + char primary_dns[16]; + char secondary_dns[16]; be_t http_proxy_config; - s8 http_proxy_server[256]; + char http_proxy_server[256]; be_t http_proxy_port; be_t upnp_config; }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellOskDialog.cpp b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp similarity index 68% rename from rpcs3/Emu/SysCalls/Modules/cellOskDialog.cpp rename to rpcs3/Emu/Cell/Modules/cellOskDialog.cpp index 6a83bd544e..ccc0c51f7f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellOskDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellOskDialog; +LOG_CHANNEL(cellOskDialog); s32 cellOskDialogLoadAsync() { @@ -153,9 +152,6 @@ s32 cellOskDialogExtRegisterForceFinishCallback() void cellSysutil_OskDialog_init() { - extern Module<> cellSysutil; - - // cellOskDialog functions: REG_FUNC(cellSysutil, cellOskDialogLoadAsync); REG_FUNC(cellSysutil, cellOskDialogUnloadAsync); REG_FUNC(cellSysutil, cellOskDialogGetSize); @@ -171,23 +167,22 @@ void cellSysutil_OskDialog_init() REG_FUNC(cellSysutil, cellOskDialogGetInputText); } -Module<> cellOskDialog("cellOskDialog", []() +DECLARE(ppu_module_manager::cellOskDialog)("cellOskExtUtility", []() { - // cellOskDialogExt functions: - REG_FUNC(cellOskDialog, cellOskDialogExtInputDeviceUnlock); - REG_FUNC(cellOskDialog, cellOskDialogExtRegisterKeyboardEventHookCallback); - REG_FUNC(cellOskDialog, cellOskDialogExtAddJapaneseOptionDictionary); - REG_FUNC(cellOskDialog, cellOskDialogExtEnableClipboard); - REG_FUNC(cellOskDialog, cellOskDialogExtSendFinishMessage); - REG_FUNC(cellOskDialog, cellOskDialogExtAddOptionDictionary); - REG_FUNC(cellOskDialog, cellOskDialogExtSetInitialScale); - REG_FUNC(cellOskDialog, cellOskDialogExtInputDeviceLock); - REG_FUNC(cellOskDialog, cellOskDialogExtSetBaseColor); - REG_FUNC(cellOskDialog, cellOskDialogExtRegisterConfirmWordFilterCallback); - REG_FUNC(cellOskDialog, cellOskDialogExtUpdateInputText); - REG_FUNC(cellOskDialog, cellOskDialogExtDisableHalfByteKana); - REG_FUNC(cellOskDialog, cellOskDialogExtSetPointerEnable); - REG_FUNC(cellOskDialog, cellOskDialogExtUpdatePointerDisplayPos); - REG_FUNC(cellOskDialog, cellOskDialogExtEnableHalfByteKana); - REG_FUNC(cellOskDialog, cellOskDialogExtRegisterForceFinishCallback); + REG_FUNC(cellOskExtUtility, cellOskDialogExtInputDeviceUnlock); + REG_FUNC(cellOskExtUtility, cellOskDialogExtRegisterKeyboardEventHookCallback); + REG_FUNC(cellOskExtUtility, cellOskDialogExtAddJapaneseOptionDictionary); + REG_FUNC(cellOskExtUtility, cellOskDialogExtEnableClipboard); + REG_FUNC(cellOskExtUtility, cellOskDialogExtSendFinishMessage); + REG_FUNC(cellOskExtUtility, cellOskDialogExtAddOptionDictionary); + REG_FUNC(cellOskExtUtility, cellOskDialogExtSetInitialScale); + REG_FUNC(cellOskExtUtility, cellOskDialogExtInputDeviceLock); + REG_FUNC(cellOskExtUtility, cellOskDialogExtSetBaseColor); + REG_FUNC(cellOskExtUtility, cellOskDialogExtRegisterConfirmWordFilterCallback); + REG_FUNC(cellOskExtUtility, cellOskDialogExtUpdateInputText); + REG_FUNC(cellOskExtUtility, cellOskDialogExtDisableHalfByteKana); + REG_FUNC(cellOskExtUtility, cellOskDialogExtSetPointerEnable); + REG_FUNC(cellOskExtUtility, cellOskDialogExtUpdatePointerDisplayPos); + REG_FUNC(cellOskExtUtility, cellOskDialogExtEnableHalfByteKana); + REG_FUNC(cellOskExtUtility, cellOskDialogExtRegisterForceFinishCallback); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellOvis.cpp b/rpcs3/Emu/Cell/Modules/cellOvis.cpp similarity index 82% rename from rpcs3/Emu/SysCalls/Modules/cellOvis.cpp rename to rpcs3/Emu/Cell/Modules/cellOvis.cpp index ce14d263d5..49e22da87f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellOvis.cpp +++ b/rpcs3/Emu/Cell/Modules/cellOvis.cpp @@ -1,10 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -namespace vm { using namespace ps3; } - -extern Module<> cellOvis; +LOG_CHANNEL(cellOvis); // Return Codes enum @@ -38,7 +35,7 @@ s32 cellOvisInvalidateOverlappedSegments() return CELL_OK; } -Module<> cellOvis("cellOvis", []() +DECLARE(ppu_module_manager::cellOvis)("cellOvis", []() { REG_FUNC(cellOvis, cellOvisGetOverlayTableSize); REG_FUNC(cellOvis, cellOvisInitializeOverlayTable); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp similarity index 85% rename from rpcs3/Emu/SysCalls/Modules/cellPad.cpp rename to rpcs3/Emu/Cell/Modules/cellPad.cpp index d691ff3023..f0441cc739 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -1,37 +1,37 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/IdManager.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/Io/Pad.h" +#include "Emu/Io/PadHandler.h" #include "cellPad.h" -extern Module<> sys_io; +extern _log::channel sys_io; s32 cellPadInit(u32 max_connect) { sys_io.warning("cellPadInit(max_connect=%d)", max_connect); - if (Emu.GetPadManager().IsInited()) - return CELL_PAD_ERROR_ALREADY_INITIALIZED; - if (max_connect > CELL_PAD_MAX_PORT_NUM) return CELL_PAD_ERROR_INVALID_PARAMETER; - Emu.GetPadManager().Init(max_connect); + const auto handler = fxm::import(PURE_EXPR(Emu.GetCallbacks().get_pad_handler())); + + if (!handler) + return CELL_PAD_ERROR_ALREADY_INITIALIZED; + + handler->Init(max_connect); return CELL_OK; } s32 cellPadEnd() { - sys_io.trace("cellPadEnd()"); + sys_io.notice("cellPadEnd()"); - if (!Emu.GetPadManager().IsInited()) + if (!fxm::remove()) return CELL_PAD_ERROR_UNINITIALIZED; - Emu.GetPadManager().Close(); - return CELL_OK; } @@ -39,10 +39,12 @@ s32 cellPadClearBuf(u32 port_no) { sys_io.trace("cellPadClearBuf(port_no=%d)", port_no); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; @@ -52,7 +54,7 @@ s32 cellPadClearBuf(u32 port_no) //Set 'm_buffer_cleared' to force a resend of everything //might as well also reset everything in our pad 'buffer' to nothing as well - std::vector& pads = Emu.GetPadManager().GetPads(); + std::vector& pads = handler->GetPads(); Pad& pad = pads[port_no]; pad.m_buffer_cleared = true; @@ -74,18 +76,18 @@ s32 cellPadPeriphGetInfo(vm::ptr info) { sys_io.todo("cellPadPeriphGetInfo(info=*0x%x)", info); - if (!Emu.GetPadManager().IsInited()) - { - return CELL_PAD_ERROR_UNINITIALIZED; - } + const auto handler = fxm::get(); - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + if (!handler) + return CELL_PAD_ERROR_UNINITIALIZED; + + const PadInfo& rinfo = handler->GetInfo(); info->max_connect = rinfo.max_connect; info->now_connect = rinfo.now_connect; info->system_info = rinfo.system_info; - std::vector& pads = Emu.GetPadManager().GetPads(); + std::vector& pads = handler->GetPads(); // TODO: Support other types of controllers for (u32 i = 0; i < CELL_PAD_MAX_PORT_NUM; ++i) @@ -113,12 +115,14 @@ s32 cellPadGetData(u32 port_no, vm::ptr data) { sys_io.trace("cellPadGetData(port_no=%d, data=*0x%x)", port_no, data); - std::vector& pads = Emu.GetPadManager().GetPads(); + const auto handler = fxm::get(); - if (!Emu.GetPadManager().IsInited()) + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + std::vector& pads = handler->GetPads(); + + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; @@ -297,10 +301,12 @@ s32 cellPadGetDataExtra(u32 port_no, vm::ptr device_type, vm::ptr(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; @@ -314,10 +320,12 @@ s32 cellPadSetActDirect(u32 port_no, vm::ptr param) { sys_io.trace("cellPadSetActDirect(port_no=%d, param=*0x%x)", port_no, param); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; @@ -331,16 +339,18 @@ s32 cellPadGetInfo(vm::ptr info) { sys_io.trace("cellPadGetInfo(info=*0x%x)", info); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); info->max_connect = rinfo.max_connect; info->now_connect = rinfo.now_connect; info->system_info = rinfo.system_info; //Can't have this as const, we need to reset Assign Changes Flag here - std::vector& pads = Emu.GetPadManager().GetPads(); + std::vector& pads = handler->GetPads(); for (u32 i=0; i info) { sys_io.trace("cellPadGetInfo2(info=*0x%x)", info); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); info->max_connect = rinfo.max_connect; info->now_connect = rinfo.now_connect; info->system_info = rinfo.system_info; - std::vector& pads = Emu.GetPadManager().GetPads(); + std::vector& pads = handler->GetPads(); for (u32 i=0; i info) { sys_io.trace("cellPadGetCapabilityInfo(port_no=%d, data_addr:=0x%x)", port_no, info.addr()); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; - const std::vector& pads = Emu.GetPadManager().GetPads(); + const std::vector& pads = handler->GetPads(); //Should return the same as device capability mask, psl1ght has it backwards in pad.h info->info[0] = pads[port_no].m_device_capability; @@ -411,17 +425,19 @@ s32 cellPadSetPortSetting(u32 port_no, u32 port_setting) { sys_io.trace("cellPadSetPortSetting(port_no=%d, port_setting=0x%x)", port_no, port_setting); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; - std::vector& pads = Emu.GetPadManager().GetPads(); + std::vector& pads = handler->GetPads(); pads[port_no].m_port_setting = port_setting; return CELL_OK; @@ -431,17 +447,19 @@ s32 cellPadInfoPressMode(u32 port_no) { sys_io.trace("cellPadInfoPressMode(port_no=%d)", port_no); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; - const std::vector& pads = Emu.GetPadManager().GetPads(); + const std::vector& pads = handler->GetPads(); return (pads[port_no].m_device_capability & CELL_PAD_CAPABILITY_PRESS_MODE) > 0; } @@ -450,17 +468,19 @@ s32 cellPadInfoSensorMode(u32 port_no) { sys_io.trace("cellPadInfoSensorMode(port_no=%d)", port_no); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; - const std::vector& pads = Emu.GetPadManager().GetPads(); + const std::vector& pads = handler->GetPads(); return (pads[port_no].m_device_capability & CELL_PAD_CAPABILITY_SENSOR_MODE) > 0; } @@ -469,19 +489,22 @@ s32 cellPadSetPressMode(u32 port_no, u32 mode) { sys_io.trace("cellPadSetPressMode(port_no=%d, mode=%d)", port_no, mode); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; + if (mode != 0 && mode != 1) return CELL_PAD_ERROR_INVALID_PARAMETER; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; - std::vector& pads = Emu.GetPadManager().GetPads(); + std::vector& pads = handler->GetPads(); if (mode) pads[port_no].m_port_setting |= CELL_PAD_SETTING_PRESS_ON; @@ -495,19 +518,22 @@ s32 cellPadSetSensorMode(u32 port_no, u32 mode) { sys_io.trace("cellPadSetSensorMode(port_no=%d, mode=%d)", port_no, mode); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; + if (mode != 0 && mode != 1) return CELL_PAD_ERROR_INVALID_PARAMETER; - const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + const PadInfo& rinfo = handler->GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; - std::vector& pads = Emu.GetPadManager().GetPads(); + std::vector& pads = handler->GetPads(); if (mode) pads[port_no].m_port_setting |= CELL_PAD_SETTING_SENSOR_ON; @@ -521,7 +547,9 @@ s32 cellPadLddRegisterController() { sys_io.todo("cellPadLddRegisterController()"); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; return CELL_OK; @@ -531,7 +559,9 @@ s32 cellPadLddDataInsert(s32 handle, vm::ptr data) { sys_io.todo("cellPadLddDataInsert(handle=%d, data=*0x%x)", handle, data); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; return CELL_OK; @@ -541,7 +571,9 @@ s32 cellPadLddGetPortNo(s32 handle) { sys_io.todo("cellPadLddGetPortNo(handle=%d)", handle); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; return CELL_OK; @@ -551,7 +583,9 @@ s32 cellPadLddUnregisterController(s32 handle) { sys_io.todo("cellPadLddUnregisterController(handle=%d)", handle); - if (!Emu.GetPadManager().IsInited()) + const auto handler = fxm::get(); + + if (!handler) return CELL_PAD_ERROR_UNINITIALIZED; return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/cellPad.h b/rpcs3/Emu/Cell/Modules/cellPad.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellPad.h rename to rpcs3/Emu/Cell/Modules/cellPad.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/Cell/Modules/cellPamf.cpp similarity index 95% rename from rpcs3/Emu/SysCalls/Modules/cellPamf.cpp rename to rpcs3/Emu/Cell/Modules/cellPamf.cpp index 36f26bcea9..fcd64720b6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPamf.cpp @@ -1,16 +1,23 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellPamf.h" -extern Module<> cellPamf; +const std::function SQUEUE_ALWAYS_EXIT = []() { return true; }; +const std::function SQUEUE_NEVER_EXIT = []() { return false; }; + +bool squeue_test_exit() +{ + return Emu.IsStopped(); +} + +LOG_CHANNEL(cellPamf); s32 pamfStreamTypeToEsFilterId(u8 type, u8 ch, CellCodecEsFilterId& pEsFilterId) { // convert type and ch to EsFilterId - assert(ch < 16); + Expects(ch < 16); pEsFilterId.supplementalInfo1 = type == CELL_PAMF_STREAM_TYPE_AVC; pEsFilterId.supplementalInfo2 = 0; @@ -110,7 +117,7 @@ s32 pamfStreamTypeToEsFilterId(u8 type, u8 ch, CellCodecEsFilterId& pEsFilterId) u8 pamfGetStreamType(vm::ptr pSelf, u32 stream) { // TODO: get stream type correctly - assert(stream < (u32)pSelf->pAddr->stream_count); + Expects(stream < (u32)pSelf->pAddr->stream_count); auto& header = pSelf->pAddr->stream_headers[stream]; switch (header.type) @@ -131,7 +138,7 @@ u8 pamfGetStreamType(vm::ptr pSelf, u32 stream) u8 pamfGetStreamChannel(vm::ptr pSelf, u32 stream) { // TODO: get stream channel correctly - assert(stream < (u32)pSelf->pAddr->stream_count); + Expects(stream < (u32)pSelf->pAddr->stream_count); auto& header = pSelf->pAddr->stream_headers[stream]; switch (header.type) @@ -139,29 +146,29 @@ u8 pamfGetStreamChannel(vm::ptr pSelf, u32 stream) case 0x1b: // AVC case 0x02: // M2V { - assert((header.fid_major & 0xf0) == 0xe0 && header.fid_minor == 0); + Expects((header.fid_major & 0xf0) == 0xe0 && header.fid_minor == 0); return header.fid_major % 16; } case 0xdc: // ATRAC3PLUS { - assert(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0); + Expects(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0); return header.fid_minor % 16; } case 0x80: // LPCM { - assert(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x40); + Expects(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x40); return header.fid_minor % 16; } case 0x81: // AC3 { - assert(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x30); + Expects(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x30); return header.fid_minor % 16; } case 0xdd: { - assert(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x20); + Expects(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x20); return header.fid_minor % 16; } } @@ -447,7 +454,7 @@ s32 cellPamfReaderGetEsFilterId(vm::ptr pSelf, vm::ptrstream < (u32)pSelf->pAddr->stream_count); + Expects((u32)pSelf->stream < (u32)pSelf->pAddr->stream_count); auto& header = pSelf->pAddr->stream_headers[pSelf->stream]; pEsFilterId->filterIdMajor = header.fid_major; pEsFilterId->filterIdMinor = header.fid_minor; @@ -460,7 +467,7 @@ s32 cellPamfReaderGetStreamInfo(vm::ptr pSelf, vm::ptr pIn { cellPamf.warning("cellPamfReaderGetStreamInfo(pSelf=*0x%x, pInfo=*0x%x, size=%d)", pSelf, pInfo, size); - assert((u32)pSelf->stream < (u32)pSelf->pAddr->stream_count); + Expects((u32)pSelf->stream < (u32)pSelf->pAddr->stream_count); auto& header = pSelf->pAddr->stream_headers[pSelf->stream]; const u8 type = pamfGetStreamType(pSelf, pSelf->stream); const u8 ch = pamfGetStreamChannel(pSelf, pSelf->stream); @@ -733,7 +740,7 @@ s32 cellPamfEpIteratorMove(vm::ptr pIt, s32 steps, vm::ptr cellPamf("cellPamf", []() +DECLARE(ppu_module_manager::cellPamf)("cellPamf", []() { REG_FUNC(cellPamf, cellPamfGetHeaderSize); REG_FUNC(cellPamf, cellPamfGetHeaderSize2); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.h b/rpcs3/Emu/Cell/Modules/cellPamf.h similarity index 59% rename from rpcs3/Emu/SysCalls/Modules/cellPamf.h rename to rpcs3/Emu/Cell/Modules/cellPamf.h index 823a1b564f..4dd45b3256 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.h +++ b/rpcs3/Emu/Cell/Modules/cellPamf.h @@ -399,3 +399,342 @@ struct CellPamfReader CHECK_SIZE(CellPamfReader, 128); s32 cellPamfReaderInitialize(vm::ptr pSelf, vm::cptr pAddr, u64 fileSize, u32 attribute); + + +extern const std::function SQUEUE_ALWAYS_EXIT; +extern const std::function SQUEUE_NEVER_EXIT; + +bool squeue_test_exit(); + +// TODO: eliminate this boolshit +template +class squeue_t +{ + struct alignas(8) squeue_sync_var_t + { + struct + { + u32 position : 31; + u32 pop_lock : 1; + }; + struct + { + u32 count : 31; + u32 push_lock : 1; + }; + }; + + atomic_t m_sync; + + mutable std::mutex m_rcv_mutex; + mutable std::mutex m_wcv_mutex; + mutable std::condition_variable m_rcv; + mutable std::condition_variable m_wcv; + + T m_data[sq_size]; + + enum squeue_sync_var_result : u32 + { + SQSVR_OK = 0, + SQSVR_LOCKED = 1, + SQSVR_FAILED = 2, + }; + +public: + squeue_t() + : m_sync(squeue_sync_var_t{}) + { + } + + u32 get_max_size() const + { + return sq_size; + } + + bool is_full() const + { + return m_sync.load().count == sq_size; + } + + bool push(const T& data, const std::function& test_exit) + { + u32 pos = 0; + + while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32 + { + Expects(sync.count <= sq_size); + Expects(sync.position < sq_size); + + if (sync.push_lock) + { + return SQSVR_LOCKED; + } + if (sync.count == sq_size) + { + return SQSVR_FAILED; + } + + sync.push_lock = 1; + pos = sync.position + sync.count; + return SQSVR_OK; + })) + { + if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit())) + { + return false; + } + + std::unique_lock wcv_lock(m_wcv_mutex); + m_wcv.wait_for(wcv_lock, std::chrono::milliseconds(1)); + } + + m_data[pos >= sq_size ? pos - sq_size : pos] = data; + + m_sync.atomic_op([](squeue_sync_var_t& sync) + { + Expects(sync.count <= sq_size); + Expects(sync.position < sq_size); + Expects(sync.push_lock); + sync.push_lock = 0; + sync.count++; + }); + + m_rcv.notify_one(); + m_wcv.notify_one(); + return true; + } + + bool push(const T& data, const volatile bool* do_exit) + { + return push(data, [do_exit]() { return do_exit && *do_exit; }); + } + + force_inline bool push(const T& data) + { + return push(data, SQUEUE_NEVER_EXIT); + } + + force_inline bool try_push(const T& data) + { + return push(data, SQUEUE_ALWAYS_EXIT); + } + + bool pop(T& data, const std::function& test_exit) + { + u32 pos = 0; + + while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32 + { + Expects(sync.count <= sq_size); + Expects(sync.position < sq_size); + + if (!sync.count) + { + return SQSVR_FAILED; + } + if (sync.pop_lock) + { + return SQSVR_LOCKED; + } + + sync.pop_lock = 1; + pos = sync.position; + return SQSVR_OK; + })) + { + if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit())) + { + return false; + } + + std::unique_lock rcv_lock(m_rcv_mutex); + m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1)); + } + + data = m_data[pos]; + + m_sync.atomic_op([](squeue_sync_var_t& sync) + { + Expects(sync.count <= sq_size); + Expects(sync.position < sq_size); + Expects(sync.pop_lock); + sync.pop_lock = 0; + sync.position++; + sync.count--; + if (sync.position == sq_size) + { + sync.position = 0; + } + }); + + m_rcv.notify_one(); + m_wcv.notify_one(); + return true; + } + + bool pop(T& data, const volatile bool* do_exit) + { + return pop(data, [do_exit]() { return do_exit && *do_exit; }); + } + + force_inline bool pop(T& data) + { + return pop(data, SQUEUE_NEVER_EXIT); + } + + force_inline bool try_pop(T& data) + { + return pop(data, SQUEUE_ALWAYS_EXIT); + } + + bool peek(T& data, u32 start_pos, const std::function& test_exit) + { + Expects(start_pos < sq_size); + u32 pos = 0; + + while (u32 res = m_sync.atomic_op([&pos, start_pos](squeue_sync_var_t& sync) -> u32 + { + Expects(sync.count <= sq_size); + Expects(sync.position < sq_size); + + if (sync.count <= start_pos) + { + return SQSVR_FAILED; + } + if (sync.pop_lock) + { + return SQSVR_LOCKED; + } + + sync.pop_lock = 1; + pos = sync.position + start_pos; + return SQSVR_OK; + })) + { + if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit())) + { + return false; + } + + std::unique_lock rcv_lock(m_rcv_mutex); + m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1)); + } + + data = m_data[pos >= sq_size ? pos - sq_size : pos]; + + m_sync.atomic_op([](squeue_sync_var_t& sync) + { + Expects(sync.count <= sq_size); + Expects(sync.position < sq_size); + Expects(sync.pop_lock); + sync.pop_lock = 0; + }); + + m_rcv.notify_one(); + return true; + } + + bool peek(T& data, u32 start_pos, const volatile bool* do_exit) + { + return peek(data, start_pos, [do_exit]() { return do_exit && *do_exit; }); + } + + force_inline bool peek(T& data, u32 start_pos = 0) + { + return peek(data, start_pos, SQUEUE_NEVER_EXIT); + } + + force_inline bool try_peek(T& data, u32 start_pos = 0) + { + return peek(data, start_pos, SQUEUE_ALWAYS_EXIT); + } + + class squeue_data_t + { + T* const m_data; + const u32 m_pos; + const u32 m_count; + + squeue_data_t(T* data, u32 pos, u32 count) + : m_data(data) + , m_pos(pos) + , m_count(count) + { + } + + public: + T& operator [] (u32 index) + { + Expects(index < m_count); + index += m_pos; + index = index < sq_size ? index : index - sq_size; + return m_data[index]; + } + }; + + void process(void(*proc)(squeue_data_t data)) + { + u32 pos, count; + + while (m_sync.atomic_op([&pos, &count](squeue_sync_var_t& sync) -> u32 + { + Expects(sync.count <= sq_size); + Expects(sync.position < sq_size); + + if (sync.pop_lock || sync.push_lock) + { + return SQSVR_LOCKED; + } + + pos = sync.position; + count = sync.count; + sync.pop_lock = 1; + sync.push_lock = 1; + return SQSVR_OK; + })) + { + std::unique_lock rcv_lock(m_rcv_mutex); + m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1)); + } + + proc(squeue_data_t(m_data, pos, count)); + + m_sync.atomic_op([](squeue_sync_var_t& sync) + { + Expects(sync.count <= sq_size); + Expects(sync.position < sq_size); + Expects(sync.pop_lock && sync.push_lock); + sync.pop_lock = 0; + sync.push_lock = 0; + }); + + m_wcv.notify_one(); + m_rcv.notify_one(); + } + + void clear() + { + while (m_sync.atomic_op([](squeue_sync_var_t& sync) -> u32 + { + Expects(sync.count <= sq_size); + Expects(sync.position < sq_size); + + if (sync.pop_lock || sync.push_lock) + { + return SQSVR_LOCKED; + } + + sync.pop_lock = 1; + sync.push_lock = 1; + return SQSVR_OK; + })) + { + std::unique_lock rcv_lock(m_rcv_mutex); + m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1)); + } + + m_sync.exchange({}); + m_wcv.notify_one(); + m_rcv.notify_one(); + } +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellPhotoDecode.cpp b/rpcs3/Emu/Cell/Modules/cellPhotoDecode.cpp similarity index 72% rename from rpcs3/Emu/SysCalls/Modules/cellPhotoDecode.cpp rename to rpcs3/Emu/Cell/Modules/cellPhotoDecode.cpp index 8ede8c8388..90f759f1e4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPhotoDecode.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPhotoDecode.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellPhotoDecode; +LOG_CHANNEL(cellPhotoDecode); // Return Codes enum @@ -56,10 +55,10 @@ s32 cellPhotoDecodeFromFile() return CELL_OK; } -Module<> cellPhotoDecode("cellPhotoDecode", []() +DECLARE(ppu_module_manager::cellPhotoDecode)("cellPhotoDecodeUtil", []() { - REG_FUNC(cellPhotoDecode, cellPhotoDecodeInitialize); - REG_FUNC(cellPhotoDecode, cellPhotoDecodeInitialize2); - REG_FUNC(cellPhotoDecode, cellPhotoDecodeFinalize); - REG_FUNC(cellPhotoDecode, cellPhotoDecodeFromFile); + REG_FUNC(cellPhotoDecodeUtil, cellPhotoDecodeInitialize); + REG_FUNC(cellPhotoDecodeUtil, cellPhotoDecodeInitialize2); + REG_FUNC(cellPhotoDecodeUtil, cellPhotoDecodeFinalize); + REG_FUNC(cellPhotoDecodeUtil, cellPhotoDecodeFromFile); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPhotoExport.cpp b/rpcs3/Emu/Cell/Modules/cellPhotoExport.cpp similarity index 70% rename from rpcs3/Emu/SysCalls/Modules/cellPhotoExport.cpp rename to rpcs3/Emu/Cell/Modules/cellPhotoExport.cpp index 00b88fabc3..3b9f4a6381 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPhotoExport.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPhotoExport.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellPhotoExport; +LOG_CHANNEL(cellPhotoExport); // Return Codes enum @@ -75,15 +74,15 @@ s32 cellPhotoExportProgress() return CELL_OK; } -Module<> cellPhotoExport("cellPhotoExport", []() +DECLARE(ppu_module_manager::cellPhotoExport)("cellPhotoUtility", []() { - REG_FUNC(cellPhotoExport, cellPhotoInitialize); - REG_FUNC(cellPhotoExport, cellPhotoFinalize); - REG_FUNC(cellPhotoExport, cellPhotoRegistFromFile); - REG_FUNC(cellPhotoExport, cellPhotoExportInitialize); - REG_FUNC(cellPhotoExport, cellPhotoExportInitialize2); - REG_FUNC(cellPhotoExport, cellPhotoExportFinalize); - REG_FUNC(cellPhotoExport, cellPhotoExportFromFile); - REG_FUNC(cellPhotoExport, cellPhotoExportFromFileWithCopy); - REG_FUNC(cellPhotoExport, cellPhotoExportProgress); + REG_FUNC(cellPhotoUtility, cellPhotoInitialize); + REG_FUNC(cellPhotoUtility, cellPhotoFinalize); + REG_FUNC(cellPhotoUtility, cellPhotoRegistFromFile); + REG_FUNC(cellPhotoUtility, cellPhotoExportInitialize); + REG_FUNC(cellPhotoUtility, cellPhotoExportInitialize2); + REG_FUNC(cellPhotoUtility, cellPhotoExportFinalize); + REG_FUNC(cellPhotoUtility, cellPhotoExportFromFile); + REG_FUNC(cellPhotoUtility, cellPhotoExportFromFileWithCopy); + REG_FUNC(cellPhotoUtility, cellPhotoExportProgress); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPhotoImport.cpp b/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp similarity index 89% rename from rpcs3/Emu/SysCalls/Modules/cellPhotoImport.cpp rename to rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp index cb4bddb8fb..4bb17ce497 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPhotoImport.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellPhotoImportUtil; +LOG_CHANNEL(cellPhotoImportUtil); // Return Codes enum @@ -53,7 +52,7 @@ s32 cellPhotoImport2() return CELL_OK; } -Module<> cellPhotoImportUtil("cellPhotoImport", []() +DECLARE(ppu_module_manager::cellPhotoImportUtil)("cellPhotoImportUtil", []() { REG_FUNC(cellPhotoImportUtil, cellPhotoImport); REG_FUNC(cellPhotoImportUtil, cellPhotoImport2); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPng.h b/rpcs3/Emu/Cell/Modules/cellPng.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellPng.h rename to rpcs3/Emu/Cell/Modules/cellPng.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/Cell/Modules/cellPngDec.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp rename to rpcs3/Emu/Cell/Modules/cellPngDec.cpp index 44ad101ed3..431170548e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPngDec.cpp @@ -1,16 +1,13 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" -#include "Emu/FS/VFS.h" -#include "Emu/FS/vfsFileBase.h" -#include "Emu/SysCalls/lv2/sys_fs.h" +#include "Emu/Cell/PPUModule.h" +#include "Emu/Cell/lv2/sys_fs.h" #include "png.h" #include "cellPngDec.h" -extern Module<> cellPngDec; +LOG_CHANNEL(cellPngDec); // cellPngDec aliases to improve readability using PPHandle = vm::pptr; @@ -59,7 +56,7 @@ void pngDecReadBuffer(png_structp png_ptr, png_bytep out, png_size_t length) auto file = idm::get(buffer.fd); // Read the data - file->file->Read(out, length); + file->file.read(out, length); } else { @@ -338,7 +335,7 @@ s32 pngDecOpen(PPUThread& ppu, PHandle handle, PPStream png_stream, PSrc source, if (source->srcSelect == CELL_PNGDEC_FILE) { // Open a file stream - std::shared_ptr file_stream(Emu.GetVFS().OpenFile(stream->source.fileName.get_ptr(), fom::read)); + fs::file file_stream(vfs::get(stream->source.fileName.get_ptr())); // Check if opening of the PNG file failed if (!file_stream) @@ -348,14 +345,14 @@ s32 pngDecOpen(PPUThread& ppu, PHandle handle, PPStream png_stream, PSrc source, } // Read the header - if (file_stream->Read(header, 8) != 8) + if (file_stream.read(header, 8) != 8) { cellPngDec.error("PNG header is too small."); return CELL_PNGDEC_ERROR_HEADER; } // Get the file descriptor - buffer->fd = idm::make(file_stream, 0, 0); + buffer->fd = idm::make(std::move(file_stream), 0, 0); // Indicate that we need to read from a file stream buffer->file = true; @@ -852,7 +849,7 @@ s32 cellPngDecGetTextChunk(PHandle handle, PStream stream, vm::ptr textInfo throw EXCEPTION(""); } -Module<> cellPngDec("cellPngDec", []() +DECLARE(ppu_module_manager::cellPngDec)("cellPngDec", []() { REG_FUNC(cellPngDec, cellPngDecGetUnknownChunks); REG_FUNC(cellPngDec, cellPngDecClose); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h b/rpcs3/Emu/Cell/Modules/cellPngDec.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellPngDec.h rename to rpcs3/Emu/Cell/Modules/cellPngDec.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngEnc.cpp b/rpcs3/Emu/Cell/Modules/cellPngEnc.cpp similarity index 91% rename from rpcs3/Emu/SysCalls/Modules/cellPngEnc.cpp rename to rpcs3/Emu/Cell/Modules/cellPngEnc.cpp index 5317ed0143..a1efb70795 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngEnc.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPngEnc.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellPngEnc; +LOG_CHANNEL(cellPngEnc); // Error Codes enum @@ -69,7 +68,7 @@ s32 cellPngEncReset() return CELL_OK; } -Module<> cellPngEnc("cellPngEnc", []() +DECLARE(ppu_module_manager::cellPngEnc)("cellPngEnc", []() { REG_FUNC(cellPngEnc, cellPngEncQueryAttr); REG_FUNC(cellPngEnc, cellPngEncOpen); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPrint.cpp b/rpcs3/Emu/Cell/Modules/cellPrint.cpp similarity index 66% rename from rpcs3/Emu/SysCalls/Modules/cellPrint.cpp rename to rpcs3/Emu/Cell/Modules/cellPrint.cpp index c64f0ea728..b0a37969cd 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPrint.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPrint.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellPrint; +LOG_CHANNEL(cellPrint); // Error Codes enum @@ -101,21 +100,21 @@ s32 cellPrintSendBand() return CELL_OK; } -Module<> cellPrint("cellPrint", []() +DECLARE(ppu_module_manager::cellPrint)("cellPrintUtility", []() { - REG_FUNC(cellPrint, cellSysutilPrintInit); - REG_FUNC(cellPrint, cellSysutilPrintShutdown); + REG_FUNC(cellPrintUtility, cellSysutilPrintInit); + REG_FUNC(cellPrintUtility, cellSysutilPrintShutdown); - REG_FUNC(cellPrint, cellPrintLoadAsync); - REG_FUNC(cellPrint, cellPrintLoadAsync2); - REG_FUNC(cellPrint, cellPrintUnloadAsync); - REG_FUNC(cellPrint, cellPrintGetStatus); - REG_FUNC(cellPrint, cellPrintOpenConfig); - REG_FUNC(cellPrint, cellPrintGetPrintableArea); - REG_FUNC(cellPrint, cellPrintStartJob); - REG_FUNC(cellPrint, cellPrintEndJob); - REG_FUNC(cellPrint, cellPrintCancelJob); - REG_FUNC(cellPrint, cellPrintStartPage); - REG_FUNC(cellPrint, cellPrintEndPage); - REG_FUNC(cellPrint, cellPrintSendBand); + REG_FUNC(cellPrintUtility, cellPrintLoadAsync); + REG_FUNC(cellPrintUtility, cellPrintLoadAsync2); + REG_FUNC(cellPrintUtility, cellPrintUnloadAsync); + REG_FUNC(cellPrintUtility, cellPrintGetStatus); + REG_FUNC(cellPrintUtility, cellPrintOpenConfig); + REG_FUNC(cellPrintUtility, cellPrintGetPrintableArea); + REG_FUNC(cellPrintUtility, cellPrintStartJob); + REG_FUNC(cellPrintUtility, cellPrintEndJob); + REG_FUNC(cellPrintUtility, cellPrintCancelJob); + REG_FUNC(cellPrintUtility, cellPrintStartPage); + REG_FUNC(cellPrintUtility, cellPrintEndPage); + REG_FUNC(cellPrintUtility, cellPrintSendBand); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellRec.cpp b/rpcs3/Emu/Cell/Modules/cellRec.cpp similarity index 83% rename from rpcs3/Emu/SysCalls/Modules/cellRec.cpp rename to rpcs3/Emu/Cell/Modules/cellRec.cpp index 4a53e6f145..ce3aa50e99 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellRec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellRec.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellRec; +LOG_CHANNEL(cellRec); s32 cellRecOpen() { @@ -40,7 +39,7 @@ s32 cellRecSetInfo() } -Module<> cellRec("cellRec", []() +DECLARE(ppu_module_manager::cellRec)("cellRec", []() { REG_FUNC(cellRec, cellRecOpen); REG_FUNC(cellRec, cellRecClose); diff --git a/rpcs3/Emu/SysCalls/Modules/cellRemotePlay.cpp b/rpcs3/Emu/Cell/Modules/cellRemotePlay.cpp similarity index 87% rename from rpcs3/Emu/SysCalls/Modules/cellRemotePlay.cpp rename to rpcs3/Emu/Cell/Modules/cellRemotePlay.cpp index ffc5abb825..0c7983bb12 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellRemotePlay.cpp +++ b/rpcs3/Emu/Cell/Modules/cellRemotePlay.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellRemotePlay; +LOG_CHANNEL(cellRemotePlay); s32 cellRemotePlayGetStatus() { @@ -45,7 +44,7 @@ s32 cellRemotePlayBreak() } -Module<> cellRemotePlay("cellRemotePlay", []() +DECLARE(ppu_module_manager::cellRemotePlay)("cellRemotePlay", []() { REG_FUNC(cellRemotePlay, cellRemotePlayGetStatus); REG_FUNC(cellRemotePlay, cellRemotePlaySetComparativeVolume); diff --git a/rpcs3/Emu/Cell/Modules/cellResc.cpp b/rpcs3/Emu/Cell/Modules/cellResc.cpp new file mode 100644 index 0000000000..00e1a5f8f9 --- /dev/null +++ b/rpcs3/Emu/Cell/Modules/cellResc.cpp @@ -0,0 +1,180 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/IdManager.h" +#include "Emu/Cell/PPUModule.h" + +#include "Emu/RSX/GCM.h" +#include "cellResc.h" + +LOG_CHANNEL(cellResc); + +s32 cellRescInit(vm::ptr initConfig) +{ + cellResc.todo("cellRescInit(initConfig=*0x%x)", initConfig); + + return CELL_OK; +} + +void cellRescExit() +{ + cellResc.todo("cellRescExit()"); +} + +s32 cellRescVideoOutResolutionId2RescBufferMode(u32 resolutionId, vm::ptr bufferMode) +{ + cellResc.todo("cellRescVideoOutResolutionId2RescBufferMode(resolutionId=%d, bufferMode=*0x%x)", resolutionId, bufferMode); + + return CELL_OK; +} + +s32 cellRescSetDsts(u32 dstsMode, vm::ptr dsts) +{ + cellResc.todo("cellRescSetDsts(dstsMode=%d, dsts=*0x%x)", dstsMode, dsts); + + return CELL_OK; +} + +s32 cellRescSetDisplayMode(u32 displayMode) +{ + cellResc.todo("cellRescSetDisplayMode(displayMode=%d)", displayMode); + + return CELL_OK; +} + +s32 cellRescAdjustAspectRatio(f32 horizontal, f32 vertical) +{ + cellResc.todo("cellRescAdjustAspectRatio(horizontal=%f, vertical=%f)", horizontal, vertical); + + return CELL_OK; +} + +s32 cellRescSetPalInterpolateDropFlexRatio(f32 ratio) +{ + cellResc.todo("cellRescSetPalInterpolateDropFlexRatio(ratio=%f)", ratio); + + return CELL_OK; +} + +s32 cellRescGetBufferSize(vm::ptr colorBuffers, vm::ptr vertexArray, vm::ptr fragmentShader) +{ + cellResc.todo("cellRescGetBufferSize(colorBuffers=*0x%x, vertexArray=*0x%x, fragmentShader=*0x%x)", colorBuffers, vertexArray, fragmentShader); + + return CELL_OK; +} + +s32 cellRescGetNumColorBuffers(u32 dstMode, u32 palTemporalMode, u32 reserved) +{ + cellResc.todo("cellRescGetNumColorBuffers(dstMode=%d, palTemporalMode=%d, reserved=%d)", dstMode, palTemporalMode, reserved); + + return 2; +} + +s32 cellRescGcmSurface2RescSrc(vm::ptr gcmSurface, vm::ptr rescSrc) +{ + cellResc.todo("cellRescGcmSurface2RescSrc(gcmSurface=*0x%x, rescSrc=*0x%x)", gcmSurface, rescSrc); + + return CELL_OK; +} + +s32 cellRescSetSrc(s32 idx, vm::ptr src) +{ + cellResc.todo("cellRescSetSrc(idx=0x%x, src=*0x%x)", idx, src); + + return CELL_OK; +} + +s32 cellRescSetConvertAndFlip(PPUThread& ppu, vm::ptr cntxt, s32 idx) +{ + cellResc.todo("cellRescSetConvertAndFlip(cntxt=*0x%x, idx=0x%x)", cntxt, idx); + + return CELL_OK; +} + +s32 cellRescSetWaitFlip() +{ + cellResc.todo("cellRescSetWaitFlip()"); + + return CELL_OK; +} + +s32 cellRescSetBufferAddress(vm::ptr colorBuffers, vm::ptr vertexArray, vm::ptr fragmentShader) +{ + cellResc.todo("cellRescSetBufferAddress(colorBuffers=*0x%x, vertexArray=*0x%x, fragmentShader=*0x%x)", colorBuffers, vertexArray, fragmentShader); + + return CELL_OK; +} + +void cellRescSetFlipHandler(vm::ptr handler) +{ + cellResc.todo("cellRescSetFlipHandler(handler=*0x%x)", handler); +} + +void cellRescResetFlipStatus() +{ + cellResc.todo("cellRescResetFlipStatus()"); +} + +s32 cellRescGetFlipStatus() +{ + cellResc.todo("cellRescGetFlipStatus()"); + + return 0; +} + +s32 cellRescGetRegisterCount() +{ + UNIMPLEMENTED_FUNC(cellResc); + return CELL_OK; +} + +u64 cellRescGetLastFlipTime() +{ + cellResc.todo("cellRescGetLastFlipTime()"); + + return 0; +} + +s32 cellRescSetRegisterCount() +{ + UNIMPLEMENTED_FUNC(cellResc); + return CELL_OK; +} + +void cellRescSetVBlankHandler(vm::ptr handler) +{ + cellResc.todo("cellRescSetVBlankHandler(handler=*0x%x)", handler); +} + +s32 cellRescCreateInterlaceTable(u32 ea_addr, f32 srcH, CellRescTableElement depth, s32 length) +{ + cellResc.todo("cellRescCreateInterlaceTable(ea_addr=0x%x, srcH=%f, depth=%d, length=%d)", ea_addr, srcH, depth, length); + + return CELL_OK; +} + + +DECLARE(ppu_module_manager::cellResc)("cellResc", []() +{ + REG_FUNC(cellResc, cellRescSetConvertAndFlip); + REG_FUNC(cellResc, cellRescSetWaitFlip); + REG_FUNC(cellResc, cellRescSetFlipHandler); + REG_FUNC(cellResc, cellRescGcmSurface2RescSrc); + REG_FUNC(cellResc, cellRescGetNumColorBuffers); + REG_FUNC(cellResc, cellRescSetDsts); + REG_FUNC(cellResc, cellRescResetFlipStatus); + REG_FUNC(cellResc, cellRescSetPalInterpolateDropFlexRatio); + REG_FUNC(cellResc, cellRescGetRegisterCount); + REG_FUNC(cellResc, cellRescAdjustAspectRatio); + REG_FUNC(cellResc, cellRescSetDisplayMode); + REG_FUNC(cellResc, cellRescExit); + REG_FUNC(cellResc, cellRescInit); + REG_FUNC(cellResc, cellRescGetBufferSize); + REG_FUNC(cellResc, cellRescGetLastFlipTime); + REG_FUNC(cellResc, cellRescSetSrc); + REG_FUNC(cellResc, cellRescSetRegisterCount); + REG_FUNC(cellResc, cellRescSetBufferAddress); + REG_FUNC(cellResc, cellRescGetFlipStatus); + REG_FUNC(cellResc, cellRescVideoOutResolutionId2RescBufferMode); + REG_FUNC(cellResc, cellRescSetVBlankHandler); + REG_FUNC(cellResc, cellRescCreateInterlaceTable); +}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.h b/rpcs3/Emu/Cell/Modules/cellResc.h similarity index 68% rename from rpcs3/Emu/SysCalls/Modules/cellResc.h rename to rpcs3/Emu/Cell/Modules/cellResc.h index 6fcb438ec8..a4b135d5ac 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.h +++ b/rpcs3/Emu/Cell/Modules/cellResc.h @@ -1,12 +1,7 @@ #pragma once -#define roundup(x,a) (((x)+(a)-1)&(~((a)-1))) -#define SEVIRITY 80.f - namespace vm { using namespace ps3; } -#include "Emu/RSX/GCM.h" - enum { CELL_RESC_ERROR_NOT_INITIALIZED = 0x80210301, @@ -109,41 +104,3 @@ struct CellRescSrc be_t height; be_t offset; }; - -struct RescVertex_t -{ - be_t Px, Py; - be_t u, v; - be_t u2, v2; -}; - -struct CCellRescInternal -{ - CellRescInitConfig m_initConfig; - CellRescSrc m_rescSrc[SRC_BUFFER_NUM]; - u32 m_dstMode; - CellRescDsts m_rescDsts[4], *m_pRescDsts; - CellRescTableElement m_interlaceElement; - - u32 m_colorBuffersEA, m_vertexArrayEA, m_fragmentUcodeEA; - u32 m_bufIdFront; - s32 m_dstWidth, m_dstHeight, m_dstPitch; - u16 m_srcWidthInterlace, m_srcHeightInterlace; - u32 m_dstBufInterval, m_dstOffsets[MAX_DST_BUFFER_NUM]; - s32 m_nVertex; - u32 m_bufIdFrontPrevDrop, m_bufIdPalMidPrev, m_bufIdPalMidNow; - u32 m_interlaceTableEA; - int m_interlaceTableLength; - float m_ratioAdjX, m_ratioAdjY, m_flexRatio; - bool m_bInitialized, m_bNewlyAdjustRatio; - bool m_isDummyFlipped; - u8 m_cgParamIndex[RESC_PARAM_NUM]; - u64 m_commandIdxCaF, m_rcvdCmdIdx; - vm::ptr s_applicationFlipHandler; - vm::ptr s_applicationVBlankHandler; - - CCellRescInternal() - : m_bInitialized(false) - { - } -}; diff --git a/rpcs3/Emu/Cell/Modules/cellRtc.cpp b/rpcs3/Emu/Cell/Modules/cellRtc.cpp new file mode 100644 index 0000000000..8648da34ee --- /dev/null +++ b/rpcs3/Emu/Cell/Modules/cellRtc.cpp @@ -0,0 +1,295 @@ +#include "stdafx.h" +#include "Emu/Cell/PPUModule.h" + +#include "cellRtc.h" + +LOG_CHANNEL(cellRtc); + +s64 convertToUNIXTime(u16 seconds, u16 minutes, u16 hours, u16 days, s32 years) +{ + return (s64)seconds + (s64)minutes * 60 + (s64)hours * 3600 + (s64)days * 86400 + + (s64)(years - 70) * 31536000 + (s64)((years - 69) / 4) * 86400 - + (s64)((years - 1) / 100) * 86400 + (s64)((years + 299) / 400) * 86400; +} + +u64 convertToWin32FILETIME(u16 seconds, u16 minutes, u16 hours, u16 days, s32 years) +{ + s64 unixtime = convertToUNIXTime(seconds, minutes, hours, days, years); + u64 win32time = u64(unixtime) * u64(10000000) + u64(116444736000000000); + u64 win32filetime = win32time | win32time >> 32; + return win32filetime; +} + +s32 cellRtcGetCurrentTick(vm::ptr pTick) +{ + cellRtc.todo("cellRtcGetCurrentTick(pTick=*0x%x)", pTick); + + return CELL_OK; +} + +s32 cellRtcGetCurrentClock(vm::ptr pClock, s32 iTimeZone) +{ + cellRtc.todo("cellRtcGetCurrentClock(pClock=*0x%x, time_zone=%d)", pClock, iTimeZone); + + return CELL_OK; +} + +s32 cellRtcGetCurrentClockLocalTime(vm::ptr pClock) +{ + cellRtc.todo("cellRtcGetCurrentClockLocalTime(pClock=*0x%x)", pClock); + + return CELL_OK; +} + +s32 cellRtcFormatRfc2822(vm::ptr pszDateTime, vm::ptr pUtc, s32 iTimeZone) +{ + cellRtc.todo("cellRtcFormatRfc2822(pszDateTime=*0x%x, pUtc=*0x%x, time_zone=%d)", pszDateTime, pUtc, iTimeZone); + + return CELL_OK; +} + +s32 cellRtcFormatRfc2822LocalTime(vm::ptr pszDateTime, vm::ptr pUtc) +{ + cellRtc.todo("cellRtcFormatRfc2822LocalTime(pszDateTime=*0x%x, pUtc=*0x%x)", pszDateTime, pUtc); + + return CELL_OK; +} + +s32 cellRtcFormatRfc3339(vm::ptr pszDateTime, vm::ptr pUtc, s32 iTimeZone) +{ + cellRtc.todo("cellRtcFormatRfc3339(pszDateTime=*0x%x, pUtc=*0x%x, iTimeZone=%d)", pszDateTime, pUtc, iTimeZone); + + return CELL_OK; +} + +s32 cellRtcFormatRfc3339LocalTime(vm::ptr pszDateTime, vm::ptr pUtc) +{ + cellRtc.todo("cellRtcFormatRfc3339LocalTime(pszDateTime=*0x%x, pUtc=*0x%x)", pszDateTime, pUtc); + + return CELL_OK; +} + +s32 cellRtcParseDateTime(vm::ptr pUtc, vm::cptr pszDateTime) +{ + cellRtc.todo("cellRtcParseDateTime(pUtc=*0x%x, pszDateTime=*0x%x)", pUtc, pszDateTime); + + return CELL_OK; +} + +s32 cellRtcParseRfc3339(vm::ptr pUtc, vm::cptr pszDateTime) +{ + cellRtc.todo("cellRtcParseRfc3339(pUtc=*0x%x, pszDateTime=*0x%x)", pUtc, pszDateTime); + + return CELL_OK; +} + +s32 cellRtcGetTick(vm::ptr pTime, vm::ptr pTick) +{ + cellRtc.todo("cellRtcGetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick); + + + return CELL_OK; +} + +s32 cellRtcSetTick(vm::ptr pTime, vm::ptr pTick) +{ + cellRtc.todo("cellRtcSetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick); + + return CELL_OK; +} + +s32 cellRtcTickAddTicks(vm::ptr pTick0, vm::ptr pTick1, s64 lAdd) +{ + cellRtc.todo("cellRtcTickAddTicks(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld)", pTick0, pTick1, lAdd); + + return CELL_OK; +} + +s32 cellRtcTickAddMicroseconds(vm::ptr pTick0, vm::ptr pTick1, s64 lAdd) +{ + cellRtc.todo("cellRtcTickAddMicroseconds(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld)", pTick0, pTick1, lAdd); + + return CELL_OK; +} + +s32 cellRtcTickAddSeconds(vm::ptr pTick0, vm::ptr pTick1, s64 lAdd) +{ + cellRtc.todo("cellRtcTickAddSeconds(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld)", pTick0, pTick1, lAdd); + + return CELL_OK; +} + +s32 cellRtcTickAddMinutes(vm::ptr pTick0, vm::ptr pTick1, s64 lAdd) +{ + cellRtc.todo("cellRtcTickAddMinutes(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld)", pTick0, pTick1, lAdd); + + return CELL_OK; +} + +s32 cellRtcTickAddHours(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) +{ + cellRtc.todo("cellRtcTickAddHours(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); + + return CELL_OK; +} + +s32 cellRtcTickAddDays(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) +{ + cellRtc.todo("cellRtcTickAddDays(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); + + return CELL_OK; +} + +s32 cellRtcTickAddWeeks(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) +{ + cellRtc.todo("cellRtcTickAddWeeks(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); + + return CELL_OK; +} + +s32 cellRtcTickAddMonths(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) +{ + cellRtc.todo("cellRtcTickAddMonths(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); + + return CELL_OK; +} + +s32 cellRtcTickAddYears(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) +{ + cellRtc.todo("cellRtcTickAddYears(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); + + return CELL_OK; +} + +s32 cellRtcConvertUtcToLocalTime(vm::ptr pUtc, vm::ptr pLocalTime) +{ + cellRtc.todo("cellRtcConvertUtcToLocalTime(pUtc=*0x%x, pLocalTime=*0x%x)", pUtc, pLocalTime); + + return CELL_OK; +} + +s32 cellRtcConvertLocalTimeToUtc(vm::ptr pLocalTime, vm::ptr pUtc) +{ + cellRtc.todo("cellRtcConvertLocalTimeToUtc(pLocalTime=*0x%x, pUtc=*0x%x)", pLocalTime, pUtc); + + return CELL_OK; +} + +s32 cellRtcGetDosTime(vm::ptr pDateTime, vm::ptr puiDosTime) +{ + cellRtc.todo("cellRtcGetDosTime(pDateTime=*0x%x, puiDosTime=*0x%x)", pDateTime, puiDosTime); + + return CELL_OK; +} + +s32 cellRtcGetTime_t(vm::ptr pDateTime, vm::ptr piTime) +{ + cellRtc.todo("cellRtcGetTime_t(pDateTime=*0x%x, piTime=*0x%x)", pDateTime, piTime); + + return CELL_OK; +} + +s32 cellRtcGetWin32FileTime(vm::ptr pDateTime, vm::ptr pulWin32FileTime) +{ + cellRtc.todo("cellRtcGetWin32FileTime(pDateTime=*0x%x, pulWin32FileTime=*0x%x)", pDateTime, pulWin32FileTime); + + return CELL_OK; +} + +s32 cellRtcSetDosTime(vm::ptr pDateTime, u32 uiDosTime) +{ + cellRtc.todo("cellRtcSetDosTime(pDateTime=*0x%x, uiDosTime=0x%x)", pDateTime, uiDosTime); + + return CELL_OK; +} + +s32 cellRtcSetTime_t(vm::ptr pDateTime, u64 iTime) +{ + cellRtc.todo("cellRtcSetTime_t(pDateTime=*0x%x, iTime=0x%llx)", pDateTime, iTime); + + return CELL_OK; +} + +s32 cellRtcSetWin32FileTime(vm::ptr pDateTime, u64 ulWin32FileTime) +{ + cellRtc.todo("cellRtcSetWin32FileTime(pDateTime=*0x%x, ulWin32FileTime=0x%llx)", pDateTime, ulWin32FileTime); + + return CELL_OK; +} + +s32 cellRtcIsLeapYear(s32 year) +{ + cellRtc.todo("cellRtcIsLeapYear(year=%d)", year); + + return 0; +} + +s32 cellRtcGetDaysInMonth(s32 year, s32 month) +{ + cellRtc.todo("cellRtcGetDaysInMonth(year=%d, month=%d)", year, month); + + return 0; +} + +s32 cellRtcGetDayOfWeek(s32 year, s32 month, s32 day) +{ + cellRtc.todo("cellRtcGetDayOfWeek(year=%d, month=%d, day=%d)", year, month, day); + + return 0; +} + +s32 cellRtcCheckValid(vm::ptr pTime) +{ + cellRtc.todo("cellRtcCheckValid(pTime=*0x%x)", pTime); + + return CELL_OK; +} + +s32 cellRtcCompareTick(vm::ptr pTick0, vm::ptr pTick1) +{ + cellRtc.todo("cellRtcCompareTick(pTick0=*0x%x, pTick1=*0x%x)", pTick0, pTick1); + + return CELL_OK; +} + +DECLARE(ppu_module_manager::cellRtc)("cellRtc", []() +{ + REG_FUNC(cellRtc, cellRtcGetCurrentTick); + REG_FUNC(cellRtc, cellRtcGetCurrentClock); + REG_FUNC(cellRtc, cellRtcGetCurrentClockLocalTime); + + REG_FUNC(cellRtc, cellRtcFormatRfc2822); + REG_FUNC(cellRtc, cellRtcFormatRfc2822LocalTime); + REG_FUNC(cellRtc, cellRtcFormatRfc3339); + REG_FUNC(cellRtc, cellRtcFormatRfc3339LocalTime); + REG_FUNC(cellRtc, cellRtcParseDateTime); + REG_FUNC(cellRtc, cellRtcParseRfc3339); + + REG_FUNC(cellRtc, cellRtcGetTick); + REG_FUNC(cellRtc, cellRtcSetTick); + REG_FUNC(cellRtc, cellRtcTickAddTicks); + REG_FUNC(cellRtc, cellRtcTickAddMicroseconds); + REG_FUNC(cellRtc, cellRtcTickAddSeconds); + REG_FUNC(cellRtc, cellRtcTickAddMinutes); + REG_FUNC(cellRtc, cellRtcTickAddHours); + REG_FUNC(cellRtc, cellRtcTickAddDays); + REG_FUNC(cellRtc, cellRtcTickAddWeeks); + REG_FUNC(cellRtc, cellRtcTickAddMonths); + REG_FUNC(cellRtc, cellRtcTickAddYears); + REG_FUNC(cellRtc, cellRtcConvertUtcToLocalTime); + REG_FUNC(cellRtc, cellRtcConvertLocalTimeToUtc); + + REG_FUNC(cellRtc, cellRtcGetDosTime); + REG_FUNC(cellRtc, cellRtcGetTime_t); + REG_FUNC(cellRtc, cellRtcGetWin32FileTime); + REG_FUNC(cellRtc, cellRtcSetDosTime); + REG_FUNC(cellRtc, cellRtcSetTime_t); + REG_FUNC(cellRtc, cellRtcSetWin32FileTime); + + REG_FUNC(cellRtc, cellRtcIsLeapYear); + REG_FUNC(cellRtc, cellRtcGetDaysInMonth); + REG_FUNC(cellRtc, cellRtcGetDayOfWeek); + REG_FUNC(cellRtc, cellRtcCheckValid); + + REG_FUNC(cellRtc, cellRtcCompareTick); +}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellRtc.h b/rpcs3/Emu/Cell/Modules/cellRtc.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellRtc.h rename to rpcs3/Emu/Cell/Modules/cellRtc.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellRudp.cpp b/rpcs3/Emu/Cell/Modules/cellRudp.cpp similarity index 97% rename from rpcs3/Emu/SysCalls/Modules/cellRudp.cpp rename to rpcs3/Emu/Cell/Modules/cellRudp.cpp index f9f22f9710..f72f07fa01 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellRudp.cpp +++ b/rpcs3/Emu/Cell/Modules/cellRudp.cpp @@ -1,12 +1,11 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/IdManager.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/IdManager.h" +#include "Emu/Cell/PPUModule.h" #include "cellRudp.h" -extern Module<> cellRudp; +LOG_CHANNEL(cellRudp); struct rudp_t { @@ -239,7 +238,7 @@ s32 cellRudpProcessEvents() return CELL_OK; } -Module<> cellRudp("cellRudp", []() +DECLARE(ppu_module_manager::cellRudp)("cellRudp", []() { REG_FUNC(cellRudp, cellRudpInit); REG_FUNC(cellRudp, cellRudpEnd); diff --git a/rpcs3/Emu/SysCalls/Modules/cellRudp.h b/rpcs3/Emu/Cell/Modules/cellRudp.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellRudp.h rename to rpcs3/Emu/Cell/Modules/cellRudp.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp b/rpcs3/Emu/Cell/Modules/cellSail.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellSail.cpp rename to rpcs3/Emu/Cell/Modules/cellSail.cpp index bce818099c..8193c663ff 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSail.cpp @@ -1,14 +1,11 @@ #include "stdafx.h" #include "Emu/System.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Callback.h" -#include "Emu/SysCalls/Modules.h" -#include "Emu/FS/vfsFile.h" +#include "Emu/Cell/PPUModule.h" #include "cellSail.h" #include "cellPamf.h" -extern Module<> cellSail; +LOG_CHANNEL(cellSail); void playerBoot(vm::ptr pSelf, u64 userParam) { @@ -815,15 +812,13 @@ s32 cellSailPlayerCreateDescriptor(vm::ptr pSelf, s32 streamType std::string uri = pUri.get_ptr(); if (uri.substr(0, 12) == "x-cell-fs://") { - std::string path = uri.substr(12); - vfsFile f; - if (f.Open(path)) + if (fs::file f{ vfs::get(uri.substr(12)) }) { - u64 size = f.GetSize(); + u64 size = f.size(); u32 buffer = vm::alloc(size, vm::main); auto bufPtr = vm::cptr::make(buffer); PamfHeader *buf = const_cast(bufPtr.get_ptr()); - assert(f.Read(buf, size) == size); + ASSERT(f.read(buf, size) == size); u32 sp_ = vm::alloc(sizeof(CellPamfReader), vm::main); auto sp = vm::ptr::make(sp_); u32 reader = cellPamfReaderInitialize(sp, bufPtr, size, 0); @@ -1043,7 +1038,7 @@ s32 cellSailPlayerUnregisterSource() return CELL_OK; } -Module<> cellSail("cellSail", []() +DECLARE(ppu_module_manager::cellSail)("cellSail", []() { REG_FUNC(cellSail, cellSailMemAllocatorInitialize); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSail.h b/rpcs3/Emu/Cell/Modules/cellSail.h similarity index 99% rename from rpcs3/Emu/SysCalls/Modules/cellSail.h rename to rpcs3/Emu/Cell/Modules/cellSail.h index 9bfd158f74..2ba84d26ae 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSail.h +++ b/rpcs3/Emu/Cell/Modules/cellSail.h @@ -674,11 +674,13 @@ union CellSailEvent be_t value; }; -template struct cast_ppu_gpr; +template +struct ppu_gpr_cast_impl; -template<> struct cast_ppu_gpr +template<> +struct ppu_gpr_cast_impl { - static inline u64 to_gpr(const CellSailEvent& event) + static inline u64 to(const CellSailEvent& event) { return event.value; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSailRec.cpp b/rpcs3/Emu/Cell/Modules/cellSailRec.cpp similarity index 97% rename from rpcs3/Emu/SysCalls/Modules/cellSailRec.cpp rename to rpcs3/Emu/Cell/Modules/cellSailRec.cpp index 2777d8d0c9..7840bc8461 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSailRec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSailRec.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellSailRec; +LOG_CHANNEL(cellSailRec); // Error Codes enum @@ -255,7 +254,7 @@ s32 cellSailRecorderDumpImage() return CELL_OK; } -Module<> cellSailRec("cellSailRec", []() +DECLARE(ppu_module_manager::cellSailRec)("cellSailRec", []() { REG_FUNC(cellSailRec, cellSailProfileSetEsAudioParameter); REG_FUNC(cellSailRec, cellSailProfileSetEsVideoParameter); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp similarity index 80% rename from rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp rename to rpcs3/Emu/Cell/Modules/cellSaveData.cpp index 677097c3a3..333b4e86c6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp @@ -1,17 +1,10 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/FS/VFS.h" -#include "Emu/FS/vfsFile.h" -#include "Emu/FS/vfsDir.h" -#include "Loader/PSF.h" #include "cellSaveData.h" -extern Module<> cellSysutil; -extern Module<> cellSaveData; -extern Module<> cellMinisSaveData; +LOG_CHANNEL(cellSaveData); // cellSaveData aliases (only for cellSaveData.cpp) using PSetList = vm::ptr; @@ -38,7 +31,7 @@ enum : u32 std::mutex g_savedata_mutex; -never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cptr dirName, +static never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cptr dirName, u32 errDialog, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, u32 unknown, vm::ptr userdata, u32 userId, PFuncDone funcDone) { @@ -61,7 +54,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt vm::var fileSet; // path of the specified user (00000001 by default) - const std::string base_dir = fmt::format("/dev_hdd0/home/%08u/savedata/", userId ? userId : 1u); + const std::string& base_dir = vfs::get(fmt::format("/dev_hdd0/home/%08u/savedata/", userId ? userId : 1u)); result->userdata = userdata; // probably should be assigned only once (allows the callback to change it) @@ -78,16 +71,16 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt const auto prefix_list = fmt::split(setList->dirNamePrefix.get_ptr(), { "|" }); - for (const auto entry : vfsDir(base_dir)) + for (const auto& entry : fs::dir(base_dir)) { - if (entry->flags & DirEntry_TypeFile) + if (entry.is_directory) { continue; } for (const auto& prefix : prefix_list) { - if (entry->name.substr(0, prefix.size()) == prefix) + if (entry.name.substr(0, prefix.size()) == prefix) { // Count the amount of matches and the amount of listed directories if (listGet->dirListNum++ < setBuf->dirListMax) @@ -95,7 +88,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt listGet->dirNum++; // PSF parameters - const auto& psf = psf::load(vfsFile(base_dir + entry->name + "/PARAM.SFO").VRead()); + const auto& psf = psf::load_object(fs::file(base_dir + entry.name + "/PARAM.SFO")); if (psf.empty()) { @@ -111,14 +104,14 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt save_entry2.size = 0; - for (const auto entry2 : vfsDir(base_dir + entry->name)) + for (const auto entry2 : fs::dir(base_dir + entry.name)) { - save_entry2.size += entry2->size; + save_entry2.size += entry2.size; } - save_entry2.atime = entry->access_time; - save_entry2.mtime = entry->modify_time; - save_entry2.ctime = entry->create_time; + save_entry2.atime = entry.atime; + save_entry2.mtime = entry.mtime; + save_entry2.ctime = entry.ctime; //save_entry2.iconBuf = NULL; // TODO: Here should be the PNG buffer //save_entry2.iconBufSize = 0; // TODO: Size of the PNG file save_entry2.isNew = false; @@ -184,7 +177,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt if (result->result < 0) { - cellSysutil.warning("savedata_op(): funcList returned < 0."); + cellSaveData.warning("savedata_op(): funcList returned < 0."); return CELL_SAVEDATA_ERROR_CBRESULT; } @@ -266,7 +259,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt } default: { - cellSysutil.error("savedata_op(): unknown listSet->focusPosition (0x%x)", pos_type); + cellSaveData.error("savedata_op(): unknown listSet->focusPosition (0x%x)", pos_type); return CELL_SAVEDATA_ERROR_PARAM; } } @@ -294,7 +287,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt if (result->result < 0) { - cellSysutil.warning("savedata_op(): funcFixed returned < 0."); + cellSaveData.warning("savedata_op(): funcFixed returned < 0."); return CELL_SAVEDATA_ERROR_CBRESULT; } @@ -339,16 +332,12 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt std::string dir_path = base_dir + save_entry.dirName + "/"; std::string sfo_path = dir_path + "PARAM.SFO"; - auto&& psf = psf::load(vfsFile(sfo_path).VRead()); + auto&& psf = psf::load_object(fs::file(sfo_path)); // Get save stats { - std::string dir_local_path; - - Emu.GetVFS().GetDevice(dir_path, dir_local_path); - - fs::stat_t dir_info; - if (!fs::stat(dir_local_path, dir_info)) + fs::stat_t dir_info{}; + if (!fs::stat(dir_path, dir_info)) { // error } @@ -381,32 +370,32 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt auto file_list = statGet->fileList.get_ptr(); - for (const auto entry : vfsDir(dir_path)) + for (const auto& entry : fs::dir(dir_path)) { // only files, system files ignored, fileNum is limited by setBuf->fileListMax - if (entry->flags & DirEntry_TypeFile && entry->name != "PARAM.SFO" && statGet->fileListNum++ < setBuf->fileListMax) + if (!entry.is_directory && entry.name != "PARAM.SFO" && statGet->fileListNum++ < setBuf->fileListMax) { statGet->fileNum++; auto& file = *file_list++; - if (entry->name == "ICON0.PNG") + if (entry.name == "ICON0.PNG") { file.fileType = CELL_SAVEDATA_FILETYPE_CONTENT_ICON0; } - else if (entry->name == "ICON1.PAM") + else if (entry.name == "ICON1.PAM") { file.fileType = CELL_SAVEDATA_FILETYPE_CONTENT_ICON1; } - else if (entry->name == "PIC1.PNG") + else if (entry.name == "PIC1.PNG") { file.fileType = CELL_SAVEDATA_FILETYPE_CONTENT_PIC1; } - else if (entry->name == "SND0.AT3") + else if (entry.name == "SND0.AT3") { file.fileType = CELL_SAVEDATA_FILETYPE_CONTENT_SND0; } - else if (psf::get_integer(psf, "*" + entry->name)) // let's put the list of protected files in PARAM.SFO (int param = 1 if protected) + else if (psf::get_integer(psf, "*" + entry.name)) // let's put the list of protected files in PARAM.SFO (int param = 1 if protected) { file.fileType = CELL_SAVEDATA_FILETYPE_SECUREFILE; } @@ -415,11 +404,11 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt file.fileType = CELL_SAVEDATA_FILETYPE_NORMALFILE; } - file.size = entry->size; - file.atime = entry->access_time; - file.mtime = entry->modify_time; - file.ctime = entry->create_time; - strcpy_trunc(file.fileName, entry->name); + file.size = entry.size; + file.atime = entry.atime; + file.mtime = entry.mtime; + file.ctime = entry.ctime; + strcpy_trunc(file.fileName, entry.name); } } @@ -428,7 +417,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt if (result->result < 0) { - cellSysutil.warning("savedata_op(): funcStat returned < 0."); + cellSaveData.warning("savedata_op(): funcStat returned 0x%x", result->result); return CELL_SAVEDATA_ERROR_CBRESULT; } @@ -473,19 +462,19 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt case CELL_SAVEDATA_RECREATE_YES: case CELL_SAVEDATA_RECREATE_YES_RESET_OWNER: { - // kill it with fire - for (const auto entry : vfsDir(dir_path)) + // TODO? + for (const auto& entry : fs::dir(dir_path)) { - if (entry->flags & DirEntry_TypeFile) + if (!entry.is_directory) { - Emu.GetVFS().RemoveFile(dir_path + entry->name); + fs::remove_file(dir_path + entry.name); } } if (!statSet->setParam) { // Savedata deleted and setParam is NULL: delete directory and abort operation - if (Emu.GetVFS().RemoveDir(dir_path)) cellSysutil.error("savedata_op(): savedata directory %s deleted", save_entry.dirName); + if (fs::remove_dir(dir_path)) cellSaveData.error("savedata_op(): savedata directory %s deleted", save_entry.dirName); return CELL_OK; } @@ -495,16 +484,17 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt default: { - cellSysutil.error("savedata_op(): unknown statSet->reCreateMode (0x%x)", statSet->reCreateMode); + cellSaveData.error("savedata_op(): unknown statSet->reCreateMode (0x%x)", statSet->reCreateMode); return CELL_SAVEDATA_ERROR_PARAM; } } } // Create save directory if necessary - if (psf.size() && save_entry.isNew && !Emu.GetVFS().CreateDir(dir_path)) + if (psf.size() && save_entry.isNew && !fs::create_dir(dir_path)) { // Let's ignore this error for now + cellSaveData.warning("savedata_op(): failed to create %s", dir_path); } // Enter the loop where the save files are read/created/deleted @@ -518,7 +508,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt if (result->result < 0) { - cellSysutil.warning("savedata_op(): funcFile returned < 0."); + cellSaveData.warning("savedata_op(): funcFile returned < 0."); return CELL_SAVEDATA_ERROR_CBRESULT; } @@ -564,22 +554,18 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt default: { - cellSysutil.error("savedata_op(): unknown fileSet->fileType (0x%x)", type); + cellSaveData.error("savedata_op(): unknown fileSet->fileType (0x%x)", type); return CELL_SAVEDATA_ERROR_PARAM; } } psf.emplace("*" + file_path, fileSet->fileType == CELL_SAVEDATA_FILETYPE_SECUREFILE); - std::string local_path; - - Emu.GetVFS().GetDevice(dir_path + file_path, local_path); - switch (const u32 op = fileSet->fileOperation) { case CELL_SAVEDATA_FILEOP_READ: { - fs::file file(local_path, fom::read); + fs::file file(dir_path + file_path, fs::read); file.seek(fileSet->fileOffset); fileGet->excSize = static_cast(file.read(fileSet->fileBuf.get_ptr(), std::min(fileSet->fileSize, fileSet->fileBufSize))); break; @@ -587,23 +573,23 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt case CELL_SAVEDATA_FILEOP_WRITE: { - fs::file file(local_path, fom::write | fom::create); + fs::file file(dir_path + file_path, fs::write + fs::create); file.seek(fileSet->fileOffset); fileGet->excSize = static_cast(file.write(fileSet->fileBuf.get_ptr(), std::min(fileSet->fileSize, fileSet->fileBufSize))); - file.trunc(file.seek(0, fs::seek_cur)); // truncate + file.trunc(file.pos()); // truncate break; } case CELL_SAVEDATA_FILEOP_DELETE: { - fs::remove_file(local_path); + fs::remove_file(dir_path + file_path); fileGet->excSize = 0; break; } case CELL_SAVEDATA_FILEOP_WRITE_NOTRUNC: { - fs::file file(local_path, fom::write | fom::create); + fs::file file(dir_path + file_path, fs::write + fs::create); file.seek(fileSet->fileOffset); fileGet->excSize = static_cast(file.write(fileSet->fileBuf.get_ptr(), std::min(fileSet->fileSize, fileSet->fileBufSize))); break; @@ -611,7 +597,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt default: { - cellSysutil.error("savedata_op(): unknown fileSet->fileOperation (0x%x)", op); + cellSaveData.error("savedata_op(): unknown fileSet->fileOperation (0x%x)", op); return CELL_SAVEDATA_ERROR_PARAM; } } @@ -620,7 +606,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt // Write PARAM.SFO if (psf.size()) { - vfsFile(sfo_path, fom::rewrite).VWrite(psf::save(psf)); + fs::file(sfo_path, fs::rewrite).write(psf::save_object(psf)); } return CELL_OK; @@ -630,7 +616,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt s32 cellSaveDataListSave2(PPUThread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.warning("cellSaveDataListSave2(version=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.warning("cellSaveDataListSave2(version=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, setList, setBuf, funcList, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_LIST_SAVE, version, vm::null, 1, setList, setBuf, funcList, vm::null, funcStat, funcFile, container, 2, userdata, 0, vm::null); @@ -639,7 +625,7 @@ s32 cellSaveDataListSave2(PPUThread& ppu, u32 version, PSetList setList, PSetBuf s32 cellSaveDataListLoad2(PPUThread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.warning("cellSaveDataListLoad2(version=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.warning("cellSaveDataListLoad2(version=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, setList, setBuf, funcList, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_LIST_LOAD, version, vm::null, 1, setList, setBuf, funcList, vm::null, funcStat, funcFile, container, 2, userdata, 0, vm::null); @@ -648,7 +634,7 @@ s32 cellSaveDataListLoad2(PPUThread& ppu, u32 version, PSetList setList, PSetBuf s32 cellSaveDataListSave(PPUThread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncStat funcStat, PFuncFile funcFile, u32 container) { - cellSysutil.warning("cellSaveDataListSave(version=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", + cellSaveData.warning("cellSaveDataListSave(version=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", version, setList, setBuf, funcList, funcStat, funcFile, container); return savedata_op(ppu, SAVEDATA_OP_LIST_SAVE, version, vm::null, 1, setList, setBuf, funcList, vm::null, funcStat, funcFile, container, 2, vm::null, 0, vm::null); @@ -657,7 +643,7 @@ s32 cellSaveDataListSave(PPUThread& ppu, u32 version, PSetList setList, PSetBuf s32 cellSaveDataListLoad(PPUThread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncStat funcStat, PFuncFile funcFile, u32 container) { - cellSysutil.warning("cellSaveDataListLoad(version=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", + cellSaveData.warning("cellSaveDataListLoad(version=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", version, setList, setBuf, funcList, funcStat, funcFile, container); return savedata_op(ppu, SAVEDATA_OP_LIST_LOAD, version, vm::null, 1, setList, setBuf, funcList, vm::null, funcStat, funcFile, container, 2, vm::null, 0, vm::null); @@ -667,7 +653,7 @@ s32 cellSaveDataListLoad(PPUThread& ppu, u32 version, PSetList setList, PSetBuf s32 cellSaveDataFixedSave2(PPUThread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.warning("cellSaveDataFixedSave2(version=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.warning("cellSaveDataFixedSave2(version=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_FIXED_SAVE, version, vm::null, 1, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 2, userdata, 0, vm::null); @@ -676,7 +662,7 @@ s32 cellSaveDataFixedSave2(PPUThread& ppu, u32 version, PSetList setList, PSetBu s32 cellSaveDataFixedLoad2(PPUThread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.warning("cellSaveDataFixedLoad2(version=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.warning("cellSaveDataFixedLoad2(version=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_FIXED_LOAD, version, vm::null, 1, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 2, userdata, 0, vm::null); @@ -685,7 +671,7 @@ s32 cellSaveDataFixedLoad2(PPUThread& ppu, u32 version, PSetList setList, PSetBu s32 cellSaveDataFixedSave(PPUThread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container) { - cellSysutil.warning("cellSaveDataFixedSave(version=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", + cellSaveData.warning("cellSaveDataFixedSave(version=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", version, setList, setBuf, funcFixed, funcStat, funcFile, container); return savedata_op(ppu, SAVEDATA_OP_FIXED_SAVE, version, vm::null, 1, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 2, vm::null, 0, vm::null); @@ -695,7 +681,7 @@ s32 cellSaveDataFixedSave(PPUThread& ppu, u32 version, PSetList setList, PSetBuf s32 cellSaveDataFixedLoad(PPUThread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container) { - cellSysutil.warning("cellSaveDataFixedLoad(version=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", + cellSaveData.warning("cellSaveDataFixedLoad(version=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", version, setList, setBuf, funcFixed, funcStat, funcFile, container); return savedata_op(ppu, SAVEDATA_OP_FIXED_LOAD, version, vm::null, 1, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 2, vm::null, 0, vm::null); @@ -704,7 +690,7 @@ s32 cellSaveDataFixedLoad(PPUThread& ppu, u32 version, PSetList setList, PSetBuf s32 cellSaveDataAutoSave2(PPUThread& ppu, u32 version, vm::cptr dirName, u32 errDialog, PSetBuf setBuf, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.warning("cellSaveDataAutoSave2(version=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.warning("cellSaveDataAutoSave2(version=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, dirName, errDialog, setBuf, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_AUTO_SAVE, version, dirName, errDialog, vm::null, setBuf, vm::null, vm::null, funcStat, funcFile, container, 2, userdata, 0, vm::null); @@ -713,7 +699,7 @@ s32 cellSaveDataAutoSave2(PPUThread& ppu, u32 version, vm::cptr dirName, u s32 cellSaveDataAutoLoad2(PPUThread& ppu, u32 version, vm::cptr dirName, u32 errDialog, PSetBuf setBuf, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.warning("cellSaveDataAutoLoad2(version=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.warning("cellSaveDataAutoLoad2(version=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, dirName, errDialog, setBuf, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_AUTO_LOAD, version, dirName, errDialog, vm::null, setBuf, vm::null, vm::null, funcStat, funcFile, container, 2, userdata, 0, vm::null); @@ -722,7 +708,7 @@ s32 cellSaveDataAutoLoad2(PPUThread& ppu, u32 version, vm::cptr dirName, u s32 cellSaveDataAutoSave(PPUThread& ppu, u32 version, vm::cptr dirName, u32 errDialog, PSetBuf setBuf, PFuncStat funcStat, PFuncFile funcFile, u32 container) { - cellSysutil.warning("cellSaveDataAutoSave(version=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", + cellSaveData.warning("cellSaveDataAutoSave(version=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", version, dirName, errDialog, setBuf, funcStat, funcFile, container); return savedata_op(ppu, SAVEDATA_OP_AUTO_SAVE, version, dirName, errDialog, vm::null, setBuf, vm::null, vm::null, funcStat, funcFile, container, 2, vm::null, 0, vm::null); @@ -731,7 +717,7 @@ s32 cellSaveDataAutoSave(PPUThread& ppu, u32 version, vm::cptr dirName, u3 s32 cellSaveDataAutoLoad(PPUThread& ppu, u32 version, vm::cptr dirName, u32 errDialog, PSetBuf setBuf, PFuncStat funcStat, PFuncFile funcFile, u32 container) { - cellSysutil.warning("cellSaveDataAutoLoad(version=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", + cellSaveData.warning("cellSaveDataAutoLoad(version=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)", version, dirName, errDialog, setBuf, funcStat, funcFile, container); return savedata_op(ppu, SAVEDATA_OP_AUTO_LOAD, version, dirName, errDialog, vm::null, setBuf, vm::null, vm::null, funcStat, funcFile, container, 2, vm::null, 0, vm::null); @@ -739,7 +725,7 @@ s32 cellSaveDataAutoLoad(PPUThread& ppu, u32 version, vm::cptr dirName, u3 s32 cellSaveDataListAutoSave(PPUThread& ppu, u32 version, u32 errDialog, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.warning("cellSaveDataListAutoSave(version=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.warning("cellSaveDataListAutoSave(version=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, errDialog, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_LIST_AUTO_SAVE, version, vm::null, errDialog, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 0, userdata, 0, vm::null); @@ -747,7 +733,7 @@ s32 cellSaveDataListAutoSave(PPUThread& ppu, u32 version, u32 errDialog, PSetLis s32 cellSaveDataListAutoLoad(PPUThread& ppu, u32 version, u32 errDialog, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.warning("cellSaveDataListAutoLoad(version=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.warning("cellSaveDataListAutoLoad(version=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, errDialog, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_LIST_AUTO_LOAD, version, vm::null, errDialog, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 0, userdata, 0, vm::null); @@ -755,21 +741,21 @@ s32 cellSaveDataListAutoLoad(PPUThread& ppu, u32 version, u32 errDialog, PSetLis s32 cellSaveDataDelete2(u32 container) { - cellSysutil.todo("cellSaveDataDelete2(container=0x%x)", container); + cellSaveData.todo("cellSaveDataDelete2(container=0x%x)", container); return CELL_SAVEDATA_RET_CANCEL; } s32 cellSaveDataDelete(u32 container) { - cellSysutil.todo("cellSaveDataDelete(container=0x%x)", container); + cellSaveData.todo("cellSaveDataDelete(container=0x%x)", container); return CELL_SAVEDATA_RET_CANCEL; } s32 cellSaveDataFixedDelete(PPUThread& ppu, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncDone funcDone, u32 container, vm::ptr userdata) { - cellSysutil.todo("cellSaveDataFixedDelete(setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.todo("cellSaveDataFixedDelete(setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", setList, setBuf, funcFixed, funcDone, container, userdata); return CELL_OK; @@ -777,7 +763,7 @@ s32 cellSaveDataFixedDelete(PPUThread& ppu, PSetList setList, PSetBuf setBuf, PF s32 cellSaveDataUserListSave(PPUThread& ppu, u32 version, u32 userId, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.error("cellSaveDataUserListSave(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.error("cellSaveDataUserListSave(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, setList, setBuf, funcList, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_LIST_SAVE, version, vm::null, 0, setList, setBuf, funcList, vm::null, funcStat, funcFile, container, 6, userdata, userId, vm::null); @@ -785,7 +771,7 @@ s32 cellSaveDataUserListSave(PPUThread& ppu, u32 version, u32 userId, PSetList s s32 cellSaveDataUserListLoad(PPUThread& ppu, u32 version, u32 userId, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.error("cellSaveDataUserListLoad(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.error("cellSaveDataUserListLoad(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, setList, setBuf, funcList, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_LIST_LOAD, version, vm::null, 0, setList, setBuf, funcList, vm::null, funcStat, funcFile, container, 6, userdata, userId, vm::null); @@ -793,7 +779,7 @@ s32 cellSaveDataUserListLoad(PPUThread& ppu, u32 version, u32 userId, PSetList s s32 cellSaveDataUserFixedSave(PPUThread& ppu, u32 version, u32 userId, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.error("cellSaveDataUserFixedSave(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.error("cellSaveDataUserFixedSave(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_FIXED_SAVE, version, vm::null, 0, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); @@ -801,7 +787,7 @@ s32 cellSaveDataUserFixedSave(PPUThread& ppu, u32 version, u32 userId, PSetList s32 cellSaveDataUserFixedLoad(PPUThread& ppu, u32 version, u32 userId, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.error("cellSaveDataUserFixedLoad(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.error("cellSaveDataUserFixedLoad(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_FIXED_LOAD, version, vm::null, 0, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); @@ -809,7 +795,7 @@ s32 cellSaveDataUserFixedLoad(PPUThread& ppu, u32 version, u32 userId, PSetList s32 cellSaveDataUserAutoSave(PPUThread& ppu, u32 version, u32 userId, vm::cptr dirName, u32 errDialog, PSetBuf setBuf, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.error("cellSaveDataUserAutoSave(version=%d, userId=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.error("cellSaveDataUserAutoSave(version=%d, userId=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, dirName, errDialog, setBuf, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_AUTO_SAVE, version, dirName, errDialog, vm::null, setBuf, vm::null, vm::null, funcStat, funcFile, container, 6, userdata, userId, vm::null); @@ -817,7 +803,7 @@ s32 cellSaveDataUserAutoSave(PPUThread& ppu, u32 version, u32 userId, vm::cptr dirName, u32 errDialog, PSetBuf setBuf, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.error("cellSaveDataUserAutoLoad(version=%d, userId=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.error("cellSaveDataUserAutoLoad(version=%d, userId=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, dirName, errDialog, setBuf, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_AUTO_LOAD, version, dirName, errDialog, vm::null, setBuf, vm::null, vm::null, funcStat, funcFile, container, 6, userdata, userId, vm::null); @@ -825,7 +811,7 @@ s32 cellSaveDataUserAutoLoad(PPUThread& ppu, u32 version, u32 userId, vm::cptr userdata) { - cellSysutil.error("cellSaveDataUserListAutoSave(version=%d, userId=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.error("cellSaveDataUserListAutoSave(version=%d, userId=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, errDialog, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_LIST_AUTO_SAVE, version, vm::null, errDialog, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); @@ -833,7 +819,7 @@ s32 cellSaveDataUserListAutoSave(PPUThread& ppu, u32 version, u32 userId, u32 er s32 cellSaveDataUserListAutoLoad(PPUThread& ppu, u32 version, u32 userId, u32 errDialog, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr userdata) { - cellSysutil.error("cellSaveDataUserListAutoLoad(version=%d, userId=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.error("cellSaveDataUserListAutoLoad(version=%d, userId=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, errDialog, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_LIST_AUTO_LOAD, version, vm::null, errDialog, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); @@ -841,7 +827,7 @@ s32 cellSaveDataUserListAutoLoad(PPUThread& ppu, u32 version, u32 userId, u32 er s32 cellSaveDataUserFixedDelete(PPUThread& ppu, u32 userId, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncDone funcDone, u32 container, vm::ptr userdata) { - cellSysutil.todo("cellSaveDataUserFixedDelete(userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", + cellSaveData.todo("cellSaveDataUserFixedDelete(userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", userId, setList, setBuf, funcFixed, funcDone, container, userdata); return CELL_OK; @@ -849,7 +835,7 @@ s32 cellSaveDataUserFixedDelete(PPUThread& ppu, u32 userId, PSetList setList, PS void cellSaveDataEnableOverlay(s32 enable) { - cellSysutil.error("cellSaveDataEnableOverlay(enable=%d)", enable); + cellSaveData.error("cellSaveDataEnableOverlay(enable=%d)", enable); return; } @@ -977,7 +963,7 @@ void cellSysutil_SaveData_init() REG_FUNC(cellSysutil, cellSaveDataAutoSave); } -Module<> cellSaveData("cellSaveData", []() +DECLARE(ppu_module_manager::cellSaveData)("cellSaveData", []() { // libsysutil_savedata functions: REG_FUNC(cellSaveData, cellSaveDataUserGetListItem); @@ -994,7 +980,7 @@ Module<> cellSaveData("cellSaveData", []() REG_FUNC(cellSaveData, cellSaveDataListImport); }); -Module<> cellMinisSaveData("cellMinisSaveData", []() +DECLARE(ppu_module_manager::cellMinisSaveData)("cellMinisSaveData", []() { // libsysutil_savedata_psp functions: //REG_FUNC(cellMinisSaveData, cellMinisSaveDataDelete); // 0x6eb168b3 diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.h b/rpcs3/Emu/Cell/Modules/cellSaveData.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellSaveData.h rename to rpcs3/Emu/Cell/Modules/cellSaveData.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellScreenshot.cpp b/rpcs3/Emu/Cell/Modules/cellScreenshot.cpp similarity index 59% rename from rpcs3/Emu/SysCalls/Modules/cellScreenshot.cpp rename to rpcs3/Emu/Cell/Modules/cellScreenshot.cpp index 95b8e15a40..b062a1d5e8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellScreenshot.cpp +++ b/rpcs3/Emu/Cell/Modules/cellScreenshot.cpp @@ -1,10 +1,10 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" + #include "cellScreenshot.h" -extern Module<> cellScreenshot; +LOG_CHANNEL(cellScreenshot); s32 cellScreenShotSetParameter() //const CellScreenShotSetParam *param { @@ -30,10 +30,10 @@ s32 cellScreenShotDisable() return CELL_OK; } -Module<> cellScreenshot("cellScreenshot", []() +DECLARE(ppu_module_manager::cellScreenShot)("cellScreenShotUtility", []() { - REG_FUNC(cellScreenshot, cellScreenShotSetParameter); - REG_FUNC(cellScreenshot, cellScreenShotSetOverlayImage); - REG_FUNC(cellScreenshot, cellScreenShotEnable); - REG_FUNC(cellScreenshot, cellScreenShotDisable); + REG_FUNC(cellScreenShotUtility, cellScreenShotSetParameter); + REG_FUNC(cellScreenShotUtility, cellScreenShotSetOverlayImage); + REG_FUNC(cellScreenShotUtility, cellScreenShotEnable); + REG_FUNC(cellScreenShotUtility, cellScreenShotDisable); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellScreenshot.h b/rpcs3/Emu/Cell/Modules/cellScreenshot.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellScreenshot.h rename to rpcs3/Emu/Cell/Modules/cellScreenshot.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellSearch.cpp b/rpcs3/Emu/Cell/Modules/cellSearch.cpp similarity index 60% rename from rpcs3/Emu/SysCalls/Modules/cellSearch.cpp rename to rpcs3/Emu/Cell/Modules/cellSearch.cpp index 90f264f3f6..6c9e43fc6c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSearch.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSearch.cpp @@ -1,10 +1,10 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" + #include "cellSearch.h" -extern Module<> cellSearch; +LOG_CHANNEL(cellSearch); s32 cellSearchInitialize(CellSearchMode mode, u32 container, vm::ptr func, vm::ptr userData) { @@ -130,26 +130,26 @@ s32 cellSearchEnd() return CELL_OK; } -Module<> cellSearch("cellSearch", []() +DECLARE(ppu_module_manager::cellSearch)("cellSearchUtility", []() { - REG_FUNC(cellSearch, cellSearchInitialize); - REG_FUNC(cellSearch, cellSearchFinalize); - REG_FUNC(cellSearch, cellSearchStartListSearch); - REG_FUNC(cellSearch, cellSearchStartContentSearchInList); - REG_FUNC(cellSearch, cellSearchStartContentSearch); - REG_FUNC(cellSearch, cellSearchStartSceneSearchInVideo); - REG_FUNC(cellSearch, cellSearchStartSceneSearch); - REG_FUNC(cellSearch, cellSearchGetContentInfoByOffset); - REG_FUNC(cellSearch, cellSearchGetContentInfoByContentId); - REG_FUNC(cellSearch, cellSearchGetOffsetByContentId); - REG_FUNC(cellSearch, cellSearchGetContentIdByOffset); - REG_FUNC(cellSearch, cellSearchGetContentInfoGameComment); - REG_FUNC(cellSearch, cellSearchGetMusicSelectionContext); - REG_FUNC(cellSearch, cellSearchGetMusicSelectionContextOfSingleTrack); - REG_FUNC(cellSearch, cellSearchGetContentInfoPath); - REG_FUNC(cellSearch, cellSearchGetContentInfoPathMovieThumb); - REG_FUNC(cellSearch, cellSearchPrepareFile); - REG_FUNC(cellSearch, cellSearchGetContentInfoDeveloperData); - REG_FUNC(cellSearch, cellSearchCancel); - REG_FUNC(cellSearch, cellSearchEnd); + REG_FUNC(cellSearchUtility, cellSearchInitialize); + REG_FUNC(cellSearchUtility, cellSearchFinalize); + REG_FUNC(cellSearchUtility, cellSearchStartListSearch); + REG_FUNC(cellSearchUtility, cellSearchStartContentSearchInList); + REG_FUNC(cellSearchUtility, cellSearchStartContentSearch); + REG_FUNC(cellSearchUtility, cellSearchStartSceneSearchInVideo); + REG_FUNC(cellSearchUtility, cellSearchStartSceneSearch); + REG_FUNC(cellSearchUtility, cellSearchGetContentInfoByOffset); + REG_FUNC(cellSearchUtility, cellSearchGetContentInfoByContentId); + REG_FUNC(cellSearchUtility, cellSearchGetOffsetByContentId); + REG_FUNC(cellSearchUtility, cellSearchGetContentIdByOffset); + REG_FUNC(cellSearchUtility, cellSearchGetContentInfoGameComment); + REG_FUNC(cellSearchUtility, cellSearchGetMusicSelectionContext); + REG_FUNC(cellSearchUtility, cellSearchGetMusicSelectionContextOfSingleTrack); + REG_FUNC(cellSearchUtility, cellSearchGetContentInfoPath); + REG_FUNC(cellSearchUtility, cellSearchGetContentInfoPathMovieThumb); + REG_FUNC(cellSearchUtility, cellSearchPrepareFile); + REG_FUNC(cellSearchUtility, cellSearchGetContentInfoDeveloperData); + REG_FUNC(cellSearchUtility, cellSearchCancel); + REG_FUNC(cellSearchUtility, cellSearchEnd); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSearch.h b/rpcs3/Emu/Cell/Modules/cellSearch.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellSearch.h rename to rpcs3/Emu/Cell/Modules/cellSearch.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellSheap.cpp b/rpcs3/Emu/Cell/Modules/cellSheap.cpp similarity index 95% rename from rpcs3/Emu/SysCalls/Modules/cellSheap.cpp rename to rpcs3/Emu/Cell/Modules/cellSheap.cpp index b8bd086ac8..fe8ac83558 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSheap.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSheap.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellSheap; +LOG_CHANNEL(cellSheap); // Return Codes enum @@ -121,7 +120,7 @@ s32 cellKeySheapQueueDelete() return CELL_OK; } -Module<> cellSheap("cellSheap", []() +DECLARE(ppu_module_manager::cellSheap)("cellSheap", []() { REG_FUNC(cellSheap, cellSheapInitialize); REG_FUNC(cellSheap, cellSheapAllocate); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpudll.cpp b/rpcs3/Emu/Cell/Modules/cellSpudll.cpp similarity index 75% rename from rpcs3/Emu/SysCalls/Modules/cellSpudll.cpp rename to rpcs3/Emu/Cell/Modules/cellSpudll.cpp index 026b5be393..5aeaa9ae77 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpudll.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSpudll.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellSpudll; +LOG_CHANNEL(cellSpudll); s32 cellSpudllGetImageSize(vm::ptr psize, vm::cptr so_elf, vm::cptr config) { @@ -14,7 +13,7 @@ s32 cellSpudllHandleConfigSetDefaultValues(vm::ptr cellSpudll("cellSpudll", []() +DECLARE(ppu_module_manager::cellSpudll)("cellSpudll", []() { REG_FUNC(cellSpudll, cellSpudllGetImageSize); REG_FUNC(cellSpudll, cellSpudllHandleConfigSetDefaultValues); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp rename to rpcs3/Emu/Cell/Modules/cellSpurs.cpp index d94ffa27c0..d20b448ce4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp @@ -1,28 +1,34 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" #include "Emu/IdManager.h" -#include "Emu/Event.h" +#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/SPUThread.h" -#include "Emu/SysCalls/lv2/sys_sync.h" -#include "Emu/SysCalls/lv2/sys_lwmutex.h" -#include "Emu/SysCalls/lv2/sys_lwcond.h" -#include "Emu/SysCalls/lv2/sys_spu.h" -#include "Emu/SysCalls/lv2/sys_ppu_thread.h" -#include "Emu/SysCalls/lv2/sys_memory.h" -#include "Emu/SysCalls/lv2/sys_process.h" -#include "Emu/SysCalls/lv2/sys_semaphore.h" -#include "Emu/SysCalls/lv2/sys_event.h" +#include "Emu/Cell/lv2/sys_lwmutex.h" +#include "Emu/Cell/lv2/sys_lwcond.h" +#include "Emu/Cell/lv2/sys_spu.h" +#include "Emu/Cell/lv2/sys_ppu_thread.h" +#include "Emu/Cell/lv2/sys_memory.h" +#include "Emu/Cell/lv2/sys_process.h" +#include "Emu/Cell/lv2/sys_semaphore.h" +#include "Emu/Cell/lv2/sys_event.h" #include "sysPrxForUser.h" #include "cellSpurs.h" -//---------------------------------------------------------------------------- -// Externs -//---------------------------------------------------------------------------- +LOG_CHANNEL(cellSpurs); -extern Module<> cellSpurs; +// TODO +struct cell_error_t +{ + s32 value; + + explicit operator bool() const + { + return (value < 0); + } +}; + +#define CHECK_SUCCESS(expr) if (cell_error_t error{expr}) throw fmt::exception("Failure: %s -> 0x%x" HERE, #expr, error.value) //---------------------------------------------------------------------------- // Function prototypes @@ -582,7 +588,7 @@ void _spurs::handler_entry(PPUThread& ppu, vm::ptr spurs) if ((spurs->flags1 & SF1_EXIT_IF_NO_WORK) == 0) { - CHECK_ASSERTION(spurs->handlerExiting == 1); + ASSERT(spurs->handlerExiting == 1); return sys_ppu_thread_exit(ppu, 0); } @@ -645,16 +651,16 @@ s32 _spurs::wakeup_shutdown_completion_waiter(PPUThread& ppu, vm::ptr { wklF->hook(ppu, spurs, wid, wklF->hookArg); - CHECK_ASSERTION(wklEvent->load() & 0x01); - CHECK_ASSERTION(wklEvent->load() & 0x02); - CHECK_ASSERTION((wklEvent->load() & 0x20) == 0); - *wklEvent |= 0x20; + ASSERT(wklEvent->load() & 0x01); + ASSERT(wklEvent->load() & 0x02); + ASSERT((wklEvent->load() & 0x20) == 0); + wklEvent->fetch_or(0x20); } s32 rc = CELL_OK; if (!wklF->hook || wklEvent->load() & 0x10) { - CHECK_ASSERTION(wklF->x28 == 2); + ASSERT(wklF->x28 == 2); rc = sys_semaphore_post((u32)wklF->sem, 1); } @@ -665,8 +671,8 @@ void _spurs::event_helper_entry(PPUThread& ppu, vm::ptr spurs) { bool terminate = false; - vm::var events; - vm::var count; + vm::var events(8); + vm::var count; while (!terminate) { @@ -738,7 +744,7 @@ void _spurs::event_helper_entry(PPUThread& ppu, vm::ptr spurs) } else { - CHECK_SUCCESS(data0); + throw fmt::exception("data0=0x%x" HERE, data0); } } } @@ -1021,7 +1027,7 @@ s32 _spurs::initialize(PPUThread& ppu, vm::ptr spurs, u32 revision, u // Import SPURS kernel spurs->spuImg.type = SYS_SPU_IMAGE_TYPE_USER; - spurs->spuImg.addr = vm::alloc(0x40000, vm::main); + spurs->spuImg.segs = { vm::alloc(0x40000, vm::main), vm::addr }; spurs->spuImg.entry_point = isSecond ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR; spurs->spuImg.nsegs = 1; @@ -2111,8 +2117,8 @@ s32 _spurs::add_workload(vm::ptr spurs, vm::ptr wid, vm::cptrwklCurrentContention[wnum] & 0xf) == 0); - CHECK_ASSERTION((spurs->wklPendingContention[wnum] & 0xf) == 0); + ASSERT((spurs->wklCurrentContention[wnum] & 0xf) == 0); + ASSERT((spurs->wklPendingContention[wnum] & 0xf) == 0); spurs->wklState1[wnum] = 1; spurs->wklStatus1[wnum] = 0; spurs->wklEvent1[wnum] = 0; @@ -2147,8 +2153,8 @@ s32 _spurs::add_workload(vm::ptr spurs, vm::ptr wid, vm::cptrwklCurrentContention[index] & 0xf0) == 0); - CHECK_ASSERTION((spurs->wklPendingContention[index] & 0xf0) == 0); + ASSERT((spurs->wklCurrentContention[index] & 0xf0) == 0); + ASSERT((spurs->wklPendingContention[index] & 0xf0) == 0); spurs->wklState2[index] = 1; spurs->wklStatus2[index] = 0; spurs->wklEvent2[index] = 0; @@ -2183,7 +2189,7 @@ s32 _spurs::add_workload(vm::ptr spurs, vm::ptr wid, vm::cptr 8 ? 8 : maxContention); }); - spurs->wklSignal1._and_not(0x8000 >> index); // clear bit in wklFlag1 + spurs->wklSignal1.fetch_and(~(0x8000 >> index)); // clear bit in wklFlag1 } else { @@ -2192,7 +2198,7 @@ s32 _spurs::add_workload(vm::ptr spurs, vm::ptr wid, vm::cptr 8 ? 8 : maxContention) << 4; }); - spurs->wklSignal2._and_not(0x8000 >> index); // clear bit in wklFlag2 + spurs->wklSignal2.fetch_and(~(0x8000 >> index)); // clear bit in wklFlag2 } spurs->wklFlagReceiver.compare_and_swap(wnum, 0xff); @@ -2227,7 +2233,7 @@ s32 _spurs::add_workload(vm::ptr spurs, vm::ptr wid, vm::cptr> wnum); }); - CHECK_ASSERTION(res_wkl <= 31); + ASSERT(res_wkl <= 31); spurs->wklState(wnum).exchange(2); spurs->sysSrvMsgUpdateWorkload.exchange(0xff); spurs->sysSrvMessage.exchange(0xff); @@ -3160,10 +3166,15 @@ s32 cellSpursEventFlagGetTasksetAddress(vm::ptr eventFlag, v return CELL_SPURS_TASK_ERROR_ALIGN; } - taskset->set(eventFlag->isIwl ? 0u : VM_CAST(eventFlag->addr)); + taskset->set(eventFlag->isIwl ? 0u : vm::cast(eventFlag->addr, HERE)); return CELL_OK; } +static inline s32 SyncErrorToSpursError(const ppu_error_code& res) +{ + return res.value < 0 ? 0x80410900 | (res.value & 0xff) : res.value; +} + s32 _cellSpursLFQueueInitialize(vm::ptr pTasksetOrSpurs, vm::ptr pQueue, vm::cptr buffer, u32 size, u32 depth, u32 direction) { cellSpurs.todo("_cellSpursLFQueueInitialize(pTasksetOrSpurs=*0x%x, pQueue=*0x%x, buffer=*0x%x, size=0x%x, depth=0x%x, direction=%d)", pTasksetOrSpurs, pQueue, buffer, size, depth, direction); @@ -4094,7 +4105,7 @@ s32 cellSpursSemaphoreGetTasksetAddress() return CELL_OK; } -Module<> cellSpurs("cellSpurs", []() +DECLARE(ppu_module_manager::cellSpurs)("cellSpurs", []() { // Core REG_FUNC(cellSpurs, cellSpursInitialize); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/Cell/Modules/cellSpurs.h similarity index 96% rename from rpcs3/Emu/SysCalls/Modules/cellSpurs.h rename to rpcs3/Emu/Cell/Modules/cellSpurs.h index e7698fa9fa..b82f239201 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/Cell/Modules/cellSpurs.h @@ -1,921 +1,916 @@ -#pragma once - -#include "cellSync.h" - -namespace vm { using namespace ps3; } - -struct CellSpurs; -struct CellSpursTaskset; - -// Core return codes. -enum -{ - CELL_SPURS_CORE_ERROR_AGAIN = 0x80410701, - CELL_SPURS_CORE_ERROR_INVAL = 0x80410702, - CELL_SPURS_CORE_ERROR_NOMEM = 0x80410704, - CELL_SPURS_CORE_ERROR_SRCH = 0x80410705, - CELL_SPURS_CORE_ERROR_PERM = 0x80410709, - CELL_SPURS_CORE_ERROR_BUSY = 0x8041070A, - CELL_SPURS_CORE_ERROR_STAT = 0x8041070F, - CELL_SPURS_CORE_ERROR_ALIGN = 0x80410710, - CELL_SPURS_CORE_ERROR_NULL_POINTER = 0x80410711, -}; - -// -enum -{ - CELL_SPURS_POLICY_MODULE_ERROR_AGAIN = 0x80410801, - CELL_SPURS_POLICY_MODULE_ERROR_INVAL = 0x80410802, - CELL_SPURS_POLICY_MODULE_ERROR_NOSYS = 0x80410803, - CELL_SPURS_POLICY_MODULE_ERROR_NOMEM = 0x80410804, - CELL_SPURS_POLICY_MODULE_ERROR_SRCH = 0x80410805, - CELL_SPURS_POLICY_MODULE_ERROR_NOENT = 0x80410806, - CELL_SPURS_POLICY_MODULE_ERROR_NOEXEC = 0x80410807, - CELL_SPURS_POLICY_MODULE_ERROR_DEADLK = 0x80410808, - CELL_SPURS_POLICY_MODULE_ERROR_PERM = 0x80410809, - CELL_SPURS_POLICY_MODULE_ERROR_BUSY = 0x8041080A, - CELL_SPURS_POLICY_MODULE_ERROR_ABORT = 0x8041080C, - CELL_SPURS_POLICY_MODULE_ERROR_FAULT = 0x8041080D, - CELL_SPURS_POLICY_MODULE_ERROR_CHILD = 0x8041080E, - CELL_SPURS_POLICY_MODULE_ERROR_STAT = 0x8041080F, - CELL_SPURS_POLICY_MODULE_ERROR_ALIGN = 0x80410810, - CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER = 0x80410811, -}; - -// Task return codes. -enum -{ - CELL_SPURS_TASK_ERROR_AGAIN = 0x80410901, - CELL_SPURS_TASK_ERROR_INVAL = 0x80410902, - CELL_SPURS_TASK_ERROR_NOSYS = 0x80410903, - CELL_SPURS_TASK_ERROR_NOMEM = 0x80410904, - CELL_SPURS_TASK_ERROR_SRCH = 0x80410905, - CELL_SPURS_TASK_ERROR_NOEXEC = 0x80410907, - CELL_SPURS_TASK_ERROR_PERM = 0x80410909, - CELL_SPURS_TASK_ERROR_BUSY = 0x8041090A, - CELL_SPURS_TASK_ERROR_FAULT = 0x8041090D, - CELL_SPURS_TASK_ERROR_ALIGN = 0x80410910, - CELL_SPURS_TASK_ERROR_STAT = 0x8041090F, - CELL_SPURS_TASK_ERROR_NULL_POINTER = 0x80410911, - CELL_SPURS_TASK_ERROR_FATAL = 0x80410914, - CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920, -}; - -enum -{ - CELL_SPURS_JOB_ERROR_AGAIN = 0x80410A01, - CELL_SPURS_JOB_ERROR_INVAL = 0x80410A02, - CELL_SPURS_JOB_ERROR_NOSYS = 0x80410A03, - CELL_SPURS_JOB_ERROR_NOMEM = 0x80410A04, - CELL_SPURS_JOB_ERROR_SRCH = 0x80410A05, - CELL_SPURS_JOB_ERROR_NOENT = 0x80410A06, - CELL_SPURS_JOB_ERROR_NOEXEC = 0x80410A07, - CELL_SPURS_JOB_ERROR_DEADLK = 0x80410A08, - CELL_SPURS_JOB_ERROR_PERM = 0x80410A09, - CELL_SPURS_JOB_ERROR_BUSY = 0x80410A0A, - CELL_SPURS_JOB_ERROR_JOB_DESCRIPTOR = 0x80410A0B, - CELL_SPURS_JOB_ERROR_JOB_DESCRIPTOR_SIZE = 0x80410A0C, - CELL_SPURS_JOB_ERROR_FAULT = 0x80410A0D, - CELL_SPURS_JOB_ERROR_CHILD = 0x80410A0E, - CELL_SPURS_JOB_ERROR_STAT = 0x80410A0F, - CELL_SPURS_JOB_ERROR_ALIGN = 0x80410A10, - CELL_SPURS_JOB_ERROR_NULL_POINTER = 0x80410A11, - CELL_SPURS_JOB_ERROR_MEMORY_CORRUPTED = 0x80410A12, - - CELL_SPURS_JOB_ERROR_MEMORY_SIZE = 0x80410A17, - CELL_SPURS_JOB_ERROR_UNKNOWN_COMMAND = 0x80410A18, - CELL_SPURS_JOB_ERROR_JOBLIST_ALIGNMENT = 0x80410A19, - CELL_SPURS_JOB_ERROR_JOB_ALIGNMENT = 0x80410A1a, - CELL_SPURS_JOB_ERROR_CALL_OVERFLOW = 0x80410A1b, - CELL_SPURS_JOB_ERROR_ABORT = 0x80410A1c, - CELL_SPURS_JOB_ERROR_DMALIST_ELEMENT = 0x80410A1d, - CELL_SPURS_JOB_ERROR_NUM_CACHE = 0x80410A1e, - CELL_SPURS_JOB_ERROR_INVALID_BINARY = 0x80410A1f, -}; - -// SPURS defines. -enum SPURSKernelInterfaces : u32 -{ - CELL_SPURS_MAX_SPU = 8, - CELL_SPURS_MAX_WORKLOAD = 16, - CELL_SPURS_MAX_WORKLOAD2 = 32, - CELL_SPURS_SYS_SERVICE_WORKLOAD_ID = 32, - CELL_SPURS_MAX_PRIORITY = 16, - CELL_SPURS_NAME_MAX_LENGTH = 15, - CELL_SPURS_SIZE = 4096, - CELL_SPURS_SIZE2 = 8192, - CELL_SPURS_INTERRUPT_VECTOR = 0x0, - CELL_SPURS_LOCK_LINE = 0x80, - CELL_SPURS_KERNEL_DMA_TAG_ID = 31, - CELL_SPURS_KERNEL1_ENTRY_ADDR = 0x818, - CELL_SPURS_KERNEL2_ENTRY_ADDR = 0x848, - CELL_SPURS_KERNEL1_EXIT_ADDR = 0x808, - CELL_SPURS_KERNEL2_EXIT_ADDR = 0x838, - CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR = 0x290, - CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR = 0x290, -}; - -enum RangeofEventQueuePortNumbers -{ - CELL_SPURS_STATIC_PORT_RANGE_BOTTOM = 15, - CELL_SPURS_DYNAMIC_PORT_RANGE_TOP = 16, - CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63, -}; - -enum SpursAttrFlags : u32 -{ - SAF_NONE = 0x00000000, - SAF_EXIT_IF_NO_WORK = 0x00000001, - SAF_UNKNOWN_FLAG_30 = 0x00000002, - SAF_SECOND_VERSION = 0x00000004, - SAF_UNKNOWN_FLAG_9 = 0x00400000, - SAF_UNKNOWN_FLAG_8 = 0x00800000, - SAF_UNKNOWN_FLAG_7 = 0x01000000, - SAF_SYSTEM_WORKLOAD_ENABLED = 0x02000000, - SAF_SPU_PRINTF_ENABLED = 0x10000000, - SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT = 0x20000000, - SAF_SPU_MEMORY_CONTAINER_SET = 0x40000000, - SAF_UNKNOWN_FLAG_0 = 0x80000000, -}; - -enum SpursFlags1 : u8 -{ - SF1_NONE = 0x00, - SF1_32_WORKLOADS = 0x40, - SF1_EXIT_IF_NO_WORK = 0x80, -}; - -enum SpursWorkloadConstants : u32 -{ - // Workload states - SPURS_WKL_STATE_NON_EXISTENT = 0, - SPURS_WKL_STATE_PREPARING = 1, - SPURS_WKL_STATE_RUNNABLE = 2, - SPURS_WKL_STATE_SHUTTING_DOWN = 3, - SPURS_WKL_STATE_REMOVABLE = 4, - SPURS_WKL_STATE_INVALID = 5, - - // Image addresses - SPURS_IMG_ADDR_SYS_SRV_WORKLOAD = 0x100, - SPURS_IMG_ADDR_TASKSET_PM = 0x200, -}; - -enum SpursWorkloadGUIDs : u64 -{ - // GUID - SPURS_GUID_SYS_WKL = 0x1BB841BF38F89D33ull, - SPURS_GUID_TASKSET_PM = 0x836E915B2E654143ull, -}; - -enum CellSpursModulePollStatus -{ - CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT = 1, - CELL_SPURS_MODULE_POLL_STATUS_SIGNAL = 2, - CELL_SPURS_MODULE_POLL_STATUS_FLAG = 4 -}; - -enum SpursTraceConstants -{ - // Trace tag types - CELL_SPURS_TRACE_TAG_KERNEL = 0x20, - CELL_SPURS_TRACE_TAG_SERVICE = 0x21, - CELL_SPURS_TRACE_TAG_TASK = 0x22, - CELL_SPURS_TRACE_TAG_JOB = 0x23, - CELL_SPURS_TRACE_TAG_OVIS = 0x24, - CELL_SPURS_TRACE_TAG_LOAD = 0x2a, - CELL_SPURS_TRACE_TAG_MAP = 0x2b, - CELL_SPURS_TRACE_TAG_START = 0x2c, - CELL_SPURS_TRACE_TAG_STOP = 0x2d, - CELL_SPURS_TRACE_TAG_USER = 0x2e, - CELL_SPURS_TRACE_TAG_GUID = 0x2f, - - // Service incident - CELL_SPURS_TRACE_SERVICE_INIT = 0x01, - CELL_SPURS_TRACE_SERVICE_WAIT = 0x02, - CELL_SPURS_TRACE_SERVICE_EXIT = 0x03, - - // Task incident - CELL_SPURS_TRACE_TASK_DISPATCH = 0x01, - CELL_SPURS_TRACE_TASK_YIELD = 0x03, - CELL_SPURS_TRACE_TASK_WAIT = 0x04, - CELL_SPURS_TRACE_TASK_EXIT = 0x05, - - // Trace mode flags - CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER = 0x1, - CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP = 0x2, - CELL_SPURS_TRACE_MODE_FLAG_MASK = 0x3, -}; - -// SPURS task constants -enum SpursTaskConstants -{ - CELL_SPURS_MAX_TASK = 128, - CELL_SPURS_TASK_TOP = 0x3000, - CELL_SPURS_TASK_BOTTOM = 0x40000, - CELL_SPURS_MAX_TASK_NAME_LENGTH = 32, - CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1, - CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1, - CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024, - CELL_SPURS_TASKSET_PM_ENTRY_ADDR = 0xA00, - CELL_SPURS_TASKSET_PM_SYSCALL_ADDR = 0xA70, - - // Task syscall numbers - CELL_SPURS_TASK_SYSCALL_EXIT = 0, - CELL_SPURS_TASK_SYSCALL_YIELD = 1, - CELL_SPURS_TASK_SYSCALL_WAIT_SIGNAL = 2, - CELL_SPURS_TASK_SYSCALL_POLL = 3, - CELL_SPURS_TASK_SYSCALL_RECV_WKL_FLAG = 4, - - // Task poll status - CELL_SPURS_TASK_POLL_FOUND_TASK = 1, - CELL_SPURS_TASK_POLL_FOUND_WORKLOAD = 2, -}; - -enum CellSpursEventFlagWaitMode -{ - CELL_SPURS_EVENT_FLAG_OR = 0, - CELL_SPURS_EVENT_FLAG_AND = 1, - CELL_SPURS_EVENT_FLAG_WAIT_MODE_LAST = CELL_SPURS_EVENT_FLAG_AND, -}; - -enum CellSpursEventFlagClearMode -{ - CELL_SPURS_EVENT_FLAG_CLEAR_AUTO = 0, - CELL_SPURS_EVENT_FLAG_CLEAR_MANUAL = 1, - CELL_SPURS_EVENT_FLAG_CLEAR_LAST = CELL_SPURS_EVENT_FLAG_CLEAR_MANUAL, -}; - -enum CellSpursEventFlagDirection -{ - CELL_SPURS_EVENT_FLAG_SPU2SPU, - CELL_SPURS_EVENT_FLAG_SPU2PPU, - CELL_SPURS_EVENT_FLAG_PPU2SPU, - CELL_SPURS_EVENT_FLAG_ANY2ANY, - CELL_SPURS_EVENT_FLAG_LAST = CELL_SPURS_EVENT_FLAG_ANY2ANY, -}; - -// Event flag constants -enum SpursEventFlagConstants -{ - CELL_SPURS_EVENT_FLAG_MAX_WAIT_SLOTS = 16, - CELL_SPURS_EVENT_FLAG_INVALID_SPU_PORT = 0xFF, -}; - -struct alignas(16) CellSpursWorkloadFlag -{ - be_t unused0; - be_t unused1; - atomic_be_t flag; -}; - -CHECK_SIZE_ALIGN(CellSpursWorkloadFlag, 16, 16); - -struct CellSpursInfo -{ - be_t nSpus; - be_t spuThreadGroupPriority; - be_t ppuThreadPriority; - bool exitIfNoWork; - bool spurs2; - u8 padding24[2]; - vm::bptr traceBuffer; - be_t padding32; - be_t traceBufferSize; - be_t traceMode; - be_t spuThreadGroup; - be_t spuThreads[8]; - be_t spursHandlerThread0; - be_t spursHandlerThread1; - char namePrefix[16]; - be_t namePrefixLength; - be_t deadlineMissCounter; - be_t deadlineMeetCounter; - u8 padding[164]; -}; - -CHECK_SIZE(CellSpursInfo, 280); - -struct alignas(8) CellSpursAttribute -{ - be_t revision; // 0x0 - be_t sdkVersion; // 0x4 - be_t nSpus; // 0x8 - be_t spuPriority; // 0xC - be_t ppuPriority; // 0x10 - bool exitIfNoWork; // 0x14 - char prefix[15]; // 0x15 (not a NTS) - be_t prefixSize; // 0x24 - be_t flags; // 0x28 (SpursAttrFlags) - be_t container; // 0x2C - be_t unk0; // 0x30 - be_t unk1; // 0x34 - u8 swlPriority[8]; // 0x38 - be_t swlMaxSpu; // 0x40 - be_t swlIsPreem; // 0x44 - u8 padding[440]; -}; - -CHECK_SIZE_ALIGN(CellSpursAttribute, 512, 8); - -using CellSpursShutdownCompletionEventHook = void(vm::ptr spurs, u32 wid, vm::ptr arg); - -struct alignas(16) CellSpursTraceInfo -{ - be_t spuThread[8]; // 0x00 - be_t count[8]; // 0x20 - be_t spuThreadGroup; // 0x40 - be_t numSpus; // 0x44 - u8 padding[56]; -}; - -CHECK_SIZE_ALIGN(CellSpursTraceInfo, 128, 16); - -struct CellSpursTraceHeader -{ - u8 tag; - u8 length; - u8 spu; - u8 workload; - be_t time; -}; - -struct CellSpursTraceControlData -{ - be_t incident; - be_t reserved; -}; - -struct CellSpursTraceServiceData -{ - be_t incident; - be_t reserved; -}; - -struct CellSpursTraceTaskData -{ - be_t incident; - be_t taskId; -}; - -struct CellSpursTraceJobData -{ - u8 reserved[3]; - u8 binLSAhigh8; - be_t jobDescriptor; -}; - -struct CellSpursTraceLoadData -{ - be_t ea; - be_t ls; - be_t size; -}; - -struct CellSpursTraceMapData -{ - be_t offset; - be_t ls; - be_t size; -}; - -struct CellSpursTraceStartData -{ - char module[4]; - be_t level; - be_t ls; -}; - -struct alignas(16) CellSpursTracePacket -{ - CellSpursTraceHeader header; - - union - { - CellSpursTraceControlData control; - CellSpursTraceServiceData service; - CellSpursTraceTaskData task; - CellSpursTraceJobData job; - - CellSpursTraceLoadData load; - CellSpursTraceMapData map; - CellSpursTraceStartData start; - - be_t stop; - be_t user; - be_t guid; - be_t raw; - } - data; -}; - -CHECK_SIZE_ALIGN(CellSpursTracePacket, 16, 16); - -// Core CellSpurs structures -struct alignas(128) CellSpurs -{ - struct _sub_str1 - { - u8 unk0[0x20]; // 0x00 - SPU exception handler 0x08 - SPU exception handler args - be_t sem; // 0x20 - be_t x28; // 0x28 - be_t x2C; // 0x2C - vm::bptr hook; // 0x30 - vm::bptr hookArg; // 0x38 - u8 unk2[0x40]; - }; - - CHECK_SIZE(_sub_str1, 128); - - struct EventPortMux; - - using EventHandlerCallback = void(vm::ptr, u64 data); - - struct EventHandlerListNode - { - vm::bptr next; - be_t data; - vm::bptr handler; - }; - - struct EventPortMux - { - atomic_be_t reqPending; // 0x00 - be_t spuPort; // 0x04 - be_t x08; // 0x08 - be_t x0C; // 0x0C - be_t eventPort; // 0x10 - atomic_t> handlerList; // 0x18 - u8 x20[0x80 - 0x20]; // 0x20 - }; - - CHECK_SIZE(EventPortMux, 128); - - struct WorkloadInfo - { - vm::bcptr addr; // 0x00 Address of the executable - be_t arg; // 0x08 Argument - be_t size; // 0x10 Size of the executable - atomic_t uniqueId; // 0x14 Unique id of the workload. It is the same for all workloads with the same addr. - u8 pad[3]; - u8 priority[8]; // 0x18 Priority of the workload on each SPU - }; - - CHECK_SIZE(WorkloadInfo, 32); - - struct _sub_str4 - { - vm::bcptr nameClass; - vm::bcptr nameInstance; - }; - - atomic_t wklReadyCount1[0x10]; // 0x00 Number of SPUs requested by each workload (0..15 wids). - atomic_t wklIdleSpuCountOrReadyCount2[0x10]; // 0x10 SPURS1: Number of idle SPUs requested by each workload (0..15 wids). SPURS2: Number of SPUs requested by each workload (16..31 wids). - u8 wklCurrentContention[0x10]; // 0x20 Number of SPUs used by each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. - u8 wklPendingContention[0x10]; // 0x30 Number of SPUs that are pending to context switch to the workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. - u8 wklMinContention[0x10]; // 0x40 Min SPUs required for each workload. SPURS1: index = wid. SPURS2: Unused. - atomic_t wklMaxContention[0x10]; // 0x50 Max SPUs that may be allocated to each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. - CellSpursWorkloadFlag wklFlag; // 0x60 - atomic_be_t wklSignal1; // 0x70 Bitset for 0..15 wids - atomic_t sysSrvMessage; // 0x72 - u8 spuIdling; // 0x73 - u8 flags1; // 0x74 Type is SpursFlags1 - u8 sysSrvTraceControl; // 0x75 - u8 nSpus; // 0x76 - atomic_t wklFlagReceiver; // 0x77 - atomic_be_t wklSignal2; // 0x78 Bitset for 16..32 wids - u8 x7A[6]; // 0x7A - atomic_t wklState1[0x10]; // 0x80 SPURS_WKL_STATE_* - u8 wklStatus1[0x10]; // 0x90 - atomic_t wklEvent1[0x10]; // 0xA0 - atomic_be_t wklEnabled; // 0xB0 - atomic_be_t wklMskB; // 0xB4 - System service - Available module id - u32 xB8; // 0xB8 - u8 sysSrvExitBarrier; // 0xBC - atomic_t sysSrvMsgUpdateWorkload; // 0xBD - u8 xBE; // 0xBE - u8 sysSrvMsgTerminate; // 0xBF - u8 sysSrvPreemptWklId[8]; // 0xC0 Id of the workload that was preempted by the system workload on each SPU - u8 sysSrvOnSpu; // 0xC8 - u8 spuPort; // 0xC9 - u8 xCA; // 0xCA - u8 xCB; // 0xCB - - struct SrvTraceSyncVar - { - u8 sysSrvTraceInitialised; // 0xCC - u8 sysSrvNotifyUpdateTraceComplete; // 0xCD - u8 sysSrvMsgUpdateTrace; // 0xCE - u8 xCF; - }; - - atomic_t sysSrvTrace; // 0xCC - - atomic_t wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_* - u8 wklStatus2[0x10]; // 0xE0 - atomic_t wklEvent2[0x10]; // 0xF0 - _sub_str1 wklF1[0x10]; // 0x100 - vm::bptr traceBuffer; // 0x900 - be_t traceStartIndex[6]; // 0x908 - u8 unknown7[0x948 - 0x920]; // 0x920 - be_t traceDataSize; // 0x948 - be_t traceMode; // 0x950 - u8 unknown8[0x980 - 0x954]; // 0x954 - be_t semPrv; // 0x980 - be_t unk11; // 0x988 - be_t unk12; // 0x98C - be_t unk13; // 0x990 - u8 unknown4[0xB00 - 0x998]; - WorkloadInfo wklInfo1[0x10]; // 0xB00 - WorkloadInfo wklInfoSysSrv; // 0xD00 - be_t ppu0; // 0xD20 Handler thread - be_t ppu1; // 0xD28 - be_t spuTG; // 0xD30 SPU thread group - be_t spus[8]; // 0xD34 - u8 unknown3[0xD5C - 0xD54]; - be_t eventQueue; // 0xD5C - be_t eventPort; // 0xD60 - atomic_t handlerDirty; // 0xD64 - atomic_t handlerWaiting; // 0xD65 - atomic_t handlerExiting; // 0xD66 - atomic_be_t enableEH; // 0xD68 - be_t exception; // 0xD6C - sys_spu_image spuImg; // 0xD70 - be_t flags; // 0xD80 - be_t spuPriority; // 0xD84 - be_t ppuPriority; // 0xD88 - char prefix[0x0f]; // 0xD8C - u8 prefixSize; // 0xD9B - be_t unk5; // 0xD9C - be_t revision; // 0xDA0 - be_t sdkVersion; // 0xDA4 - atomic_be_t spuPortBits; // 0xDA8 - sys_lwmutex_t mutex; // 0xDB0 - sys_lwcond_t cond; // 0xDC8 - u8 unknown9[0xE00 - 0xDD0]; - _sub_str4 wklH1[0x10]; // 0xE00 - EventPortMux eventPortMux; // 0xF00 - atomic_be_t globalSpuExceptionHandler; // 0xF80 - be_t globalSpuExceptionHandlerArgs; // 0xF88 - u8 unknown6[0x1000 - 0xF90]; - WorkloadInfo wklInfo2[0x10]; // 0x1000 - _sub_str1 wklF2[0x10]; // 0x1200 - _sub_str4 wklH2[0x10]; // 0x1A00 - u8 unknown_[0x2000 - 0x1B00]; - - force_inline atomic_t& wklState(const u32 wid) - { - if (wid & 0x10) - { - return wklState2[wid & 0xf]; - } - else - { - return wklState1[wid & 0xf]; - } - } -}; - -CHECK_SIZE_ALIGN(CellSpurs, 0x2000, 128); - -using CellSpurs2 = CellSpurs; - -struct CellSpursExceptionInfo -{ - be_t spu_thread; - be_t spu_npc; - be_t cause; - be_t option; -}; - -// Exception handler -using CellSpursGlobalExceptionEventHandler = void(vm::ptr spurs, vm::cptr info, u32 id, vm::ptr arg); - -struct CellSpursWorkloadAttribute -{ - be_t revision; - be_t sdkVersion; - vm::bcptr pm; - be_t size; - be_t data; - u8 priority[8]; - be_t minContention; - be_t maxContention; - vm::bcptr nameClass; - vm::bcptr nameInstance; - vm::bptr hook; - vm::bptr hookArg; - u8 padding[456]; -}; - -CHECK_SIZE_ALIGN(CellSpursWorkloadAttribute, 512, 8); - -struct alignas(128) CellSpursEventFlag -{ - struct ControlSyncVar - { - be_t events; // 0x00 Event bits - be_t spuTaskPendingRecv; // 0x02 A bit is set to 1 when the condition of the SPU task using the slot are met and back to 0 when the SPU task unblocks - be_t ppuWaitMask; // 0x04 Wait mask for blocked PPU thread - u8 ppuWaitSlotAndMode; // 0x06 Top 4 bits: Wait slot number of the blocked PPU threa, Bottom 4 bits: Wait mode of the blocked PPU thread - u8 ppuPendingRecv; // 0x07 Set to 1 when the blocked PPU thread's conditions are met and back to 0 when the PPU thread is unblocked - }; - - union - { - atomic_t ctrl; // 0x00 - atomic_be_t events; // 0x00 - }; - - be_t spuTaskUsedWaitSlots; // 0x08 A bit is set to 1 if the wait slot corresponding to the bit is used by an SPU task and 0 otherwise - be_t spuTaskWaitMode; // 0x0A A bit is set to 1 if the wait mode for the SPU task corresponding to the bit is AND and 0 otherwise - u8 spuPort; // 0x0C - u8 isIwl; // 0x0D - u8 direction; // 0x0E - u8 clearMode; // 0x0F - be_t spuTaskWaitMask[16]; // 0x10 Wait mask for blocked SPU tasks - be_t pendingRecvTaskEvents[16]; // 0x30 The value of event flag when the wait condition for the thread/task was met - u8 waitingTaskId[16]; // 0x50 Task id of waiting SPU threads - u8 waitingTaskWklId[16]; // 0x60 Workload id of waiting SPU threads - be_t addr; // 0x70 - be_t eventPortId; // 0x78 - be_t eventQueueId; // 0x7C -}; - -CHECK_SIZE_ALIGN(CellSpursEventFlag, 128, 128); - -using CellSpursLFQueue = CellSyncLFQueue; - -union CellSpursTaskArgument -{ - be_t _u32[4]; - be_t _u64[2]; -}; - -union CellSpursTaskLsPattern -{ - be_t _u32[4]; - be_t _u64[2]; -}; - -struct alignas(16) CellSpursTaskAttribute -{ - u8 reserved[256]; -}; - -CHECK_SIZE_ALIGN(CellSpursTaskAttribute, 256, 16); - -struct alignas(16) CellSpursTaskAttribute2 -{ - be_t revision; - be_t sizeContext; - be_t eaContext; - CellSpursTaskLsPattern lsPattern; - vm::bcptr name; - - u8 reserved[220]; -}; - -CHECK_SIZE_ALIGN(CellSpursTaskAttribute2, 256, 16); - -// Exception handler -using CellSpursTasksetExceptionEventHandler = void(vm::ptr spurs, vm::ptr taskset, u32 idTask, vm::cptr info, vm::ptr arg); - -struct alignas(128) CellSpursTaskExitCode -{ - u8 skip[128]; -}; - -CHECK_SIZE_ALIGN(CellSpursTaskExitCode, 128, 128); - -struct CellSpursTaskInfo -{ - CellSpursTaskLsPattern lsPattern; - CellSpursTaskArgument argument; - vm::bptr eaElf; - vm::bptr eaContext; - be_t sizeContext; - u8 state; - u8 hasSignal; - u8 padding[2]; - vm::bcptr eaTaskExitCode; - u8 guid[8]; - u8 reserved[12]; -}; - -CHECK_SIZE(CellSpursTaskInfo, 72); - -struct CellSpursTasksetInfo -{ - CellSpursTaskInfo taskInfo[CELL_SPURS_MAX_TASK]; - be_t argument; - be_t idWorkload; - be_t idLastScheduledTask; - vm::bcptr name; - vm::bptr exceptionEventHandler; - vm::bptr exceptionEventHandlerArgument; - be_t sizeTaskset; - u8 reserved[112]; -}; - -CHECK_SIZE(CellSpursTasksetInfo, 9360); - -struct alignas(8) CellSpursTasksetAttribute -{ - be_t revision; // 0x00 - be_t sdk_version; // 0x04 - be_t args; // 0x08 - u8 priority[8]; // 0x10 - be_t max_contention; // 0x18 - vm::bcptr name; // 0x1C - be_t taskset_size; // 0x20 - be_t enable_clear_ls; // 0x24 - u8 reserved[472]; -}; - -CHECK_SIZE_ALIGN(CellSpursTasksetAttribute, 512, 8); - -struct alignas(128) CellSpursTaskset -{ - struct TaskInfo - { - CellSpursTaskArgument args; // 0x00 - vm::bcptr elf; // 0x10 - be_t context_save_storage_and_alloc_ls_blocks; // 0x18 This is (context_save_storage_addr | allocated_ls_blocks) - CellSpursTaskLsPattern ls_pattern; // 0x20 - }; - - CHECK_SIZE(TaskInfo, 48); - - be_t running; // 0x00 - be_t ready; // 0x10 - be_t pending_ready; // 0x20 - be_t enabled; // 0x30 - be_t signalled; // 0x40 - be_t waiting; // 0x50 - vm::bptr spurs; // 0x60 - be_t args; // 0x68 - u8 enable_clear_ls; // 0x70 - u8 x71; // 0x71 - u8 wkl_flag_wait_task; // 0x72 - u8 last_scheduled_task; // 0x73 - be_t wid; // 0x74 - be_t x78; // 0x78 - TaskInfo task_info[128]; // 0x80 - vm::bptr exception_handler; // 0x1880 - vm::bptr exception_handler_arg; // 0x1888 - be_t size; // 0x1890 - u32 unk2; // 0x1894 - u32 event_flag_id1; // 0x1898 - u32 event_flag_id2; // 0x189C - u8 unk3[0x60]; // 0x18A0 -}; - -CHECK_SIZE_ALIGN(CellSpursTaskset, 128 * 50, 128); - -struct alignas(128) CellSpursTaskset2 -{ - struct TaskInfo - { - CellSpursTaskArgument args; - vm::bptr elf_addr; - vm::bptr context_save_storage; // This is (context_save_storage_addr | allocated_ls_blocks) - CellSpursTaskLsPattern ls_pattern; - }; - - CHECK_SIZE(TaskInfo, 48); - - be_t running_set[4]; // 0x00 - be_t ready_set[4]; // 0x10 - be_t ready2_set[4]; // 0x20 - TODO: Find out what this is - be_t enabled_set[4]; // 0x30 - be_t signal_received_set[4]; // 0x40 - be_t waiting_set[4]; // 0x50 - vm::bptr spurs; // 0x60 - be_t args; // 0x68 - u8 enable_clear_ls; // 0x70 - u8 x71; // 0x71 - u8 x72; // 0x72 - u8 last_scheduled_task; // 0x73 - be_t wid; // 0x74 - be_t x78; // 0x78 - TaskInfo task_info[128]; // 0x80 - vm::bptr exception_handler; // 0x1880 - vm::bptr exception_handler_arg; // 0x1888 - be_t size; // 0x1890 - u32 unk2; // 0x1894 - u32 event_flag_id1; // 0x1898 - u32 event_flag_id2; // 0x189C - u8 unk3[0x1980 - 0x18A0]; // 0x18A0 - be_t task_exit_code[128]; // 0x1980 - u8 unk4[0x2900 - 0x2180]; // 0x2180 -}; - -CHECK_SIZE_ALIGN(CellSpursTaskset2, 128 * 82, 128); - -struct alignas(16) CellSpursTaskNameBuffer -{ - char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH]; -}; - -struct alignas(8) CellSpursTasksetAttribute2 -{ - be_t revision; // 0x00 - vm::bcptr name; // 0x04 - be_t args; // 0x08 - u8 priority[8]; // 0x10 - be_t max_contention; // 0x18 - be_t enable_clear_ls; // 0x1C - vm::bptr task_name_buffer; // 0x20 - u8 reserved[472]; -}; - -CHECK_SIZE_ALIGN(CellSpursTasksetAttribute2, 512, 8); - -struct alignas(16) CellSpursTaskBinInfo -{ - be_t eaElf; - be_t sizeContext; - be_t reserved; - CellSpursTaskLsPattern lsPattern; -}; - -// The SPURS kernel context. This resides at 0x100 of the LS. -struct SpursKernelContext -{ - u8 tempArea[0x80]; // 0x100 - u8 wklLocContention[0x10]; // 0x180 - u8 wklLocPendingContention[0x10]; // 0x190 - u8 priority[0x10]; // 0x1A0 - u8 x1B0[0x10]; // 0x1B0 - vm::bptr spurs; // 0x1C0 - be_t spuNum; // 0x1C8 - be_t dmaTagId; // 0x1CC - vm::bcptr wklCurrentAddr; // 0x1D0 - be_t wklCurrentUniqueId; // 0x1D8 - be_t wklCurrentId; // 0x1DC - be_t exitToKernelAddr; // 0x1E0 - be_t selectWorkloadAddr; // 0x1E4 - u8 moduleId[2]; // 0x1E8 - u8 sysSrvInitialised; // 0x1EA - u8 spuIdling; // 0x1EB - be_t wklRunnable1; // 0x1EC - be_t wklRunnable2; // 0x1EE - be_t x1F0; // 0x1F0 - be_t x1F4; // 0x1F4 - be_t x1F8; // 0x1F8 - be_t x1FC; // 0x1FC - be_t x200; // 0x200 - be_t x204; // 0x204 - be_t x208; // 0x208 - be_t x20C; // 0x20C - be_t traceBuffer; // 0x210 - be_t traceMsgCount; // 0x218 - be_t traceMaxCount; // 0x21C - u8 wklUniqueId[0x10]; // 0x220 - u8 x230[0x280 - 0x230]; // 0x230 - be_t guid[4]; // 0x280 -}; - -CHECK_SIZE(SpursKernelContext, 0x190); - -// The SPURS taskset policy module context. This resides at 0x2700 of the LS. -struct SpursTasksetContext -{ - u8 tempAreaTaskset[0x80]; // 0x2700 - u8 tempAreaTaskInfo[0x30]; // 0x2780 - be_t x27B0; // 0x27B0 - vm::bptr taskset; // 0x27B8 - be_t kernelMgmtAddr; // 0x27C0 - be_t syscallAddr; // 0x27C4 - be_t x27C8; // 0x27C8 - be_t spuNum; // 0x27CC - be_t dmaTagId; // 0x27D0 - be_t taskId; // 0x27D4 - u8 x27D8[0x2840 - 0x27D8]; // 0x27D8 - u8 moduleId[16]; // 0x2840 - u8 stackArea[0x2C80 - 0x2850]; // 0x2850 - be_t savedContextLr; // 0x2C80 - be_t savedContextSp; // 0x2C90 - be_t savedContextR80ToR127[48]; // 0x2CA0 - be_t savedContextFpscr; // 0x2FA0 - be_t savedWriteTagGroupQueryMask; // 0x2FB0 - be_t savedSpuWriteEventMask; // 0x2FB4 - be_t tasksetMgmtAddr; // 0x2FB8 - be_t guidAddr; // 0x2FBC - be_t x2FC0; // 0x2FC0 - be_t x2FC8; // 0x2FC8 - be_t taskExitCode; // 0x2FD0 - be_t x2FD4; // 0x2FD4 - u8 x2FD8[0x3000 - 0x2FD8]; // 0x2FD8 -}; - -CHECK_SIZE(SpursTasksetContext, 0x900); - -class SpursModuleExit -{ -}; - -inline static s32 SyncErrorToSpursError(s32 res) -{ - return res < 0 ? 0x80410900 | (res & 0xff) : res; -} +#pragma once + +#include "cellSync.h" + +namespace vm { using namespace ps3; } + +struct CellSpurs; +struct CellSpursTaskset; + +// Core return codes. +enum +{ + CELL_SPURS_CORE_ERROR_AGAIN = 0x80410701, + CELL_SPURS_CORE_ERROR_INVAL = 0x80410702, + CELL_SPURS_CORE_ERROR_NOMEM = 0x80410704, + CELL_SPURS_CORE_ERROR_SRCH = 0x80410705, + CELL_SPURS_CORE_ERROR_PERM = 0x80410709, + CELL_SPURS_CORE_ERROR_BUSY = 0x8041070A, + CELL_SPURS_CORE_ERROR_STAT = 0x8041070F, + CELL_SPURS_CORE_ERROR_ALIGN = 0x80410710, + CELL_SPURS_CORE_ERROR_NULL_POINTER = 0x80410711, +}; + +// +enum +{ + CELL_SPURS_POLICY_MODULE_ERROR_AGAIN = 0x80410801, + CELL_SPURS_POLICY_MODULE_ERROR_INVAL = 0x80410802, + CELL_SPURS_POLICY_MODULE_ERROR_NOSYS = 0x80410803, + CELL_SPURS_POLICY_MODULE_ERROR_NOMEM = 0x80410804, + CELL_SPURS_POLICY_MODULE_ERROR_SRCH = 0x80410805, + CELL_SPURS_POLICY_MODULE_ERROR_NOENT = 0x80410806, + CELL_SPURS_POLICY_MODULE_ERROR_NOEXEC = 0x80410807, + CELL_SPURS_POLICY_MODULE_ERROR_DEADLK = 0x80410808, + CELL_SPURS_POLICY_MODULE_ERROR_PERM = 0x80410809, + CELL_SPURS_POLICY_MODULE_ERROR_BUSY = 0x8041080A, + CELL_SPURS_POLICY_MODULE_ERROR_ABORT = 0x8041080C, + CELL_SPURS_POLICY_MODULE_ERROR_FAULT = 0x8041080D, + CELL_SPURS_POLICY_MODULE_ERROR_CHILD = 0x8041080E, + CELL_SPURS_POLICY_MODULE_ERROR_STAT = 0x8041080F, + CELL_SPURS_POLICY_MODULE_ERROR_ALIGN = 0x80410810, + CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER = 0x80410811, +}; + +// Task return codes. +enum +{ + CELL_SPURS_TASK_ERROR_AGAIN = 0x80410901, + CELL_SPURS_TASK_ERROR_INVAL = 0x80410902, + CELL_SPURS_TASK_ERROR_NOSYS = 0x80410903, + CELL_SPURS_TASK_ERROR_NOMEM = 0x80410904, + CELL_SPURS_TASK_ERROR_SRCH = 0x80410905, + CELL_SPURS_TASK_ERROR_NOEXEC = 0x80410907, + CELL_SPURS_TASK_ERROR_PERM = 0x80410909, + CELL_SPURS_TASK_ERROR_BUSY = 0x8041090A, + CELL_SPURS_TASK_ERROR_FAULT = 0x8041090D, + CELL_SPURS_TASK_ERROR_ALIGN = 0x80410910, + CELL_SPURS_TASK_ERROR_STAT = 0x8041090F, + CELL_SPURS_TASK_ERROR_NULL_POINTER = 0x80410911, + CELL_SPURS_TASK_ERROR_FATAL = 0x80410914, + CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920, +}; + +enum +{ + CELL_SPURS_JOB_ERROR_AGAIN = 0x80410A01, + CELL_SPURS_JOB_ERROR_INVAL = 0x80410A02, + CELL_SPURS_JOB_ERROR_NOSYS = 0x80410A03, + CELL_SPURS_JOB_ERROR_NOMEM = 0x80410A04, + CELL_SPURS_JOB_ERROR_SRCH = 0x80410A05, + CELL_SPURS_JOB_ERROR_NOENT = 0x80410A06, + CELL_SPURS_JOB_ERROR_NOEXEC = 0x80410A07, + CELL_SPURS_JOB_ERROR_DEADLK = 0x80410A08, + CELL_SPURS_JOB_ERROR_PERM = 0x80410A09, + CELL_SPURS_JOB_ERROR_BUSY = 0x80410A0A, + CELL_SPURS_JOB_ERROR_JOB_DESCRIPTOR = 0x80410A0B, + CELL_SPURS_JOB_ERROR_JOB_DESCRIPTOR_SIZE = 0x80410A0C, + CELL_SPURS_JOB_ERROR_FAULT = 0x80410A0D, + CELL_SPURS_JOB_ERROR_CHILD = 0x80410A0E, + CELL_SPURS_JOB_ERROR_STAT = 0x80410A0F, + CELL_SPURS_JOB_ERROR_ALIGN = 0x80410A10, + CELL_SPURS_JOB_ERROR_NULL_POINTER = 0x80410A11, + CELL_SPURS_JOB_ERROR_MEMORY_CORRUPTED = 0x80410A12, + + CELL_SPURS_JOB_ERROR_MEMORY_SIZE = 0x80410A17, + CELL_SPURS_JOB_ERROR_UNKNOWN_COMMAND = 0x80410A18, + CELL_SPURS_JOB_ERROR_JOBLIST_ALIGNMENT = 0x80410A19, + CELL_SPURS_JOB_ERROR_JOB_ALIGNMENT = 0x80410A1a, + CELL_SPURS_JOB_ERROR_CALL_OVERFLOW = 0x80410A1b, + CELL_SPURS_JOB_ERROR_ABORT = 0x80410A1c, + CELL_SPURS_JOB_ERROR_DMALIST_ELEMENT = 0x80410A1d, + CELL_SPURS_JOB_ERROR_NUM_CACHE = 0x80410A1e, + CELL_SPURS_JOB_ERROR_INVALID_BINARY = 0x80410A1f, +}; + +// SPURS defines. +enum SPURSKernelInterfaces : u32 +{ + CELL_SPURS_MAX_SPU = 8, + CELL_SPURS_MAX_WORKLOAD = 16, + CELL_SPURS_MAX_WORKLOAD2 = 32, + CELL_SPURS_SYS_SERVICE_WORKLOAD_ID = 32, + CELL_SPURS_MAX_PRIORITY = 16, + CELL_SPURS_NAME_MAX_LENGTH = 15, + CELL_SPURS_SIZE = 4096, + CELL_SPURS_SIZE2 = 8192, + CELL_SPURS_INTERRUPT_VECTOR = 0x0, + CELL_SPURS_LOCK_LINE = 0x80, + CELL_SPURS_KERNEL_DMA_TAG_ID = 31, + CELL_SPURS_KERNEL1_ENTRY_ADDR = 0x818, + CELL_SPURS_KERNEL2_ENTRY_ADDR = 0x848, + CELL_SPURS_KERNEL1_EXIT_ADDR = 0x808, + CELL_SPURS_KERNEL2_EXIT_ADDR = 0x838, + CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR = 0x290, + CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR = 0x290, +}; + +enum RangeofEventQueuePortNumbers +{ + CELL_SPURS_STATIC_PORT_RANGE_BOTTOM = 15, + CELL_SPURS_DYNAMIC_PORT_RANGE_TOP = 16, + CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63, +}; + +enum SpursAttrFlags : u32 +{ + SAF_NONE = 0x00000000, + SAF_EXIT_IF_NO_WORK = 0x00000001, + SAF_UNKNOWN_FLAG_30 = 0x00000002, + SAF_SECOND_VERSION = 0x00000004, + SAF_UNKNOWN_FLAG_9 = 0x00400000, + SAF_UNKNOWN_FLAG_8 = 0x00800000, + SAF_UNKNOWN_FLAG_7 = 0x01000000, + SAF_SYSTEM_WORKLOAD_ENABLED = 0x02000000, + SAF_SPU_PRINTF_ENABLED = 0x10000000, + SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT = 0x20000000, + SAF_SPU_MEMORY_CONTAINER_SET = 0x40000000, + SAF_UNKNOWN_FLAG_0 = 0x80000000, +}; + +enum SpursFlags1 : u8 +{ + SF1_NONE = 0x00, + SF1_32_WORKLOADS = 0x40, + SF1_EXIT_IF_NO_WORK = 0x80, +}; + +enum SpursWorkloadConstants : u32 +{ + // Workload states + SPURS_WKL_STATE_NON_EXISTENT = 0, + SPURS_WKL_STATE_PREPARING = 1, + SPURS_WKL_STATE_RUNNABLE = 2, + SPURS_WKL_STATE_SHUTTING_DOWN = 3, + SPURS_WKL_STATE_REMOVABLE = 4, + SPURS_WKL_STATE_INVALID = 5, + + // Image addresses + SPURS_IMG_ADDR_SYS_SRV_WORKLOAD = 0x100, + SPURS_IMG_ADDR_TASKSET_PM = 0x200, +}; + +enum SpursWorkloadGUIDs : u64 +{ + // GUID + SPURS_GUID_SYS_WKL = 0x1BB841BF38F89D33ull, + SPURS_GUID_TASKSET_PM = 0x836E915B2E654143ull, +}; + +enum CellSpursModulePollStatus +{ + CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT = 1, + CELL_SPURS_MODULE_POLL_STATUS_SIGNAL = 2, + CELL_SPURS_MODULE_POLL_STATUS_FLAG = 4 +}; + +enum SpursTraceConstants +{ + // Trace tag types + CELL_SPURS_TRACE_TAG_KERNEL = 0x20, + CELL_SPURS_TRACE_TAG_SERVICE = 0x21, + CELL_SPURS_TRACE_TAG_TASK = 0x22, + CELL_SPURS_TRACE_TAG_JOB = 0x23, + CELL_SPURS_TRACE_TAG_OVIS = 0x24, + CELL_SPURS_TRACE_TAG_LOAD = 0x2a, + CELL_SPURS_TRACE_TAG_MAP = 0x2b, + CELL_SPURS_TRACE_TAG_START = 0x2c, + CELL_SPURS_TRACE_TAG_STOP = 0x2d, + CELL_SPURS_TRACE_TAG_USER = 0x2e, + CELL_SPURS_TRACE_TAG_GUID = 0x2f, + + // Service incident + CELL_SPURS_TRACE_SERVICE_INIT = 0x01, + CELL_SPURS_TRACE_SERVICE_WAIT = 0x02, + CELL_SPURS_TRACE_SERVICE_EXIT = 0x03, + + // Task incident + CELL_SPURS_TRACE_TASK_DISPATCH = 0x01, + CELL_SPURS_TRACE_TASK_YIELD = 0x03, + CELL_SPURS_TRACE_TASK_WAIT = 0x04, + CELL_SPURS_TRACE_TASK_EXIT = 0x05, + + // Trace mode flags + CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER = 0x1, + CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP = 0x2, + CELL_SPURS_TRACE_MODE_FLAG_MASK = 0x3, +}; + +// SPURS task constants +enum SpursTaskConstants +{ + CELL_SPURS_MAX_TASK = 128, + CELL_SPURS_TASK_TOP = 0x3000, + CELL_SPURS_TASK_BOTTOM = 0x40000, + CELL_SPURS_MAX_TASK_NAME_LENGTH = 32, + CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1, + CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1, + CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024, + CELL_SPURS_TASKSET_PM_ENTRY_ADDR = 0xA00, + CELL_SPURS_TASKSET_PM_SYSCALL_ADDR = 0xA70, + + // Task syscall numbers + CELL_SPURS_TASK_SYSCALL_EXIT = 0, + CELL_SPURS_TASK_SYSCALL_YIELD = 1, + CELL_SPURS_TASK_SYSCALL_WAIT_SIGNAL = 2, + CELL_SPURS_TASK_SYSCALL_POLL = 3, + CELL_SPURS_TASK_SYSCALL_RECV_WKL_FLAG = 4, + + // Task poll status + CELL_SPURS_TASK_POLL_FOUND_TASK = 1, + CELL_SPURS_TASK_POLL_FOUND_WORKLOAD = 2, +}; + +enum CellSpursEventFlagWaitMode +{ + CELL_SPURS_EVENT_FLAG_OR = 0, + CELL_SPURS_EVENT_FLAG_AND = 1, + CELL_SPURS_EVENT_FLAG_WAIT_MODE_LAST = CELL_SPURS_EVENT_FLAG_AND, +}; + +enum CellSpursEventFlagClearMode +{ + CELL_SPURS_EVENT_FLAG_CLEAR_AUTO = 0, + CELL_SPURS_EVENT_FLAG_CLEAR_MANUAL = 1, + CELL_SPURS_EVENT_FLAG_CLEAR_LAST = CELL_SPURS_EVENT_FLAG_CLEAR_MANUAL, +}; + +enum CellSpursEventFlagDirection +{ + CELL_SPURS_EVENT_FLAG_SPU2SPU, + CELL_SPURS_EVENT_FLAG_SPU2PPU, + CELL_SPURS_EVENT_FLAG_PPU2SPU, + CELL_SPURS_EVENT_FLAG_ANY2ANY, + CELL_SPURS_EVENT_FLAG_LAST = CELL_SPURS_EVENT_FLAG_ANY2ANY, +}; + +// Event flag constants +enum SpursEventFlagConstants +{ + CELL_SPURS_EVENT_FLAG_MAX_WAIT_SLOTS = 16, + CELL_SPURS_EVENT_FLAG_INVALID_SPU_PORT = 0xFF, +}; + +struct alignas(16) CellSpursWorkloadFlag +{ + be_t unused0; + be_t unused1; + atomic_be_t flag; +}; + +CHECK_SIZE_ALIGN(CellSpursWorkloadFlag, 16, 16); + +struct CellSpursInfo +{ + be_t nSpus; + be_t spuThreadGroupPriority; + be_t ppuThreadPriority; + bool exitIfNoWork; + bool spurs2; + u8 padding24[2]; + vm::bptr traceBuffer; + be_t padding32; + be_t traceBufferSize; + be_t traceMode; + be_t spuThreadGroup; + be_t spuThreads[8]; + be_t spursHandlerThread0; + be_t spursHandlerThread1; + char namePrefix[16]; + be_t namePrefixLength; + be_t deadlineMissCounter; + be_t deadlineMeetCounter; + u8 padding[164]; +}; + +CHECK_SIZE(CellSpursInfo, 280); + +struct alignas(8) CellSpursAttribute +{ + be_t revision; // 0x0 + be_t sdkVersion; // 0x4 + be_t nSpus; // 0x8 + be_t spuPriority; // 0xC + be_t ppuPriority; // 0x10 + bool exitIfNoWork; // 0x14 + char prefix[15]; // 0x15 (not a NTS) + be_t prefixSize; // 0x24 + be_t flags; // 0x28 (SpursAttrFlags) + be_t container; // 0x2C + be_t unk0; // 0x30 + be_t unk1; // 0x34 + u8 swlPriority[8]; // 0x38 + be_t swlMaxSpu; // 0x40 + be_t swlIsPreem; // 0x44 + u8 padding[440]; +}; + +CHECK_SIZE_ALIGN(CellSpursAttribute, 512, 8); + +using CellSpursShutdownCompletionEventHook = void(vm::ptr spurs, u32 wid, vm::ptr arg); + +struct alignas(16) CellSpursTraceInfo +{ + be_t spuThread[8]; // 0x00 + be_t count[8]; // 0x20 + be_t spuThreadGroup; // 0x40 + be_t numSpus; // 0x44 + u8 padding[56]; +}; + +CHECK_SIZE_ALIGN(CellSpursTraceInfo, 128, 16); + +struct CellSpursTraceHeader +{ + u8 tag; + u8 length; + u8 spu; + u8 workload; + be_t time; +}; + +struct CellSpursTraceControlData +{ + be_t incident; + be_t reserved; +}; + +struct CellSpursTraceServiceData +{ + be_t incident; + be_t reserved; +}; + +struct CellSpursTraceTaskData +{ + be_t incident; + be_t taskId; +}; + +struct CellSpursTraceJobData +{ + u8 reserved[3]; + u8 binLSAhigh8; + be_t jobDescriptor; +}; + +struct CellSpursTraceLoadData +{ + be_t ea; + be_t ls; + be_t size; +}; + +struct CellSpursTraceMapData +{ + be_t offset; + be_t ls; + be_t size; +}; + +struct CellSpursTraceStartData +{ + char module[4]; + be_t level; + be_t ls; +}; + +struct alignas(16) CellSpursTracePacket +{ + CellSpursTraceHeader header; + + union + { + CellSpursTraceControlData control; + CellSpursTraceServiceData service; + CellSpursTraceTaskData task; + CellSpursTraceJobData job; + + CellSpursTraceLoadData load; + CellSpursTraceMapData map; + CellSpursTraceStartData start; + + be_t stop; + be_t user; + be_t guid; + be_t raw; + } + data; +}; + +CHECK_SIZE_ALIGN(CellSpursTracePacket, 16, 16); + +// Core CellSpurs structures +struct alignas(128) CellSpurs +{ + struct _sub_str1 + { + u8 unk0[0x20]; // 0x00 - SPU exception handler 0x08 - SPU exception handler args + be_t sem; // 0x20 + be_t x28; // 0x28 + be_t x2C; // 0x2C + vm::bptr hook; // 0x30 + vm::bptr hookArg; // 0x38 + u8 unk2[0x40]; + }; + + CHECK_SIZE(_sub_str1, 128); + + struct EventPortMux; + + using EventHandlerCallback = void(vm::ptr, u64 data); + + struct EventHandlerListNode + { + vm::bptr next; + be_t data; + vm::bptr handler; + }; + + struct EventPortMux + { + atomic_be_t reqPending; // 0x00 + be_t spuPort; // 0x04 + be_t x08; // 0x08 + be_t x0C; // 0x0C + be_t eventPort; // 0x10 + atomic_t> handlerList; // 0x18 + u8 x20[0x80 - 0x20]; // 0x20 + }; + + CHECK_SIZE(EventPortMux, 128); + + struct WorkloadInfo + { + vm::bcptr addr; // 0x00 Address of the executable + be_t arg; // 0x08 Argument + be_t size; // 0x10 Size of the executable + atomic_t uniqueId; // 0x14 Unique id of the workload. It is the same for all workloads with the same addr. + u8 pad[3]; + u8 priority[8]; // 0x18 Priority of the workload on each SPU + }; + + CHECK_SIZE(WorkloadInfo, 32); + + struct _sub_str4 + { + vm::bcptr nameClass; + vm::bcptr nameInstance; + }; + + atomic_t wklReadyCount1[0x10]; // 0x00 Number of SPUs requested by each workload (0..15 wids). + atomic_t wklIdleSpuCountOrReadyCount2[0x10]; // 0x10 SPURS1: Number of idle SPUs requested by each workload (0..15 wids). SPURS2: Number of SPUs requested by each workload (16..31 wids). + u8 wklCurrentContention[0x10]; // 0x20 Number of SPUs used by each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. + u8 wklPendingContention[0x10]; // 0x30 Number of SPUs that are pending to context switch to the workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. + u8 wklMinContention[0x10]; // 0x40 Min SPUs required for each workload. SPURS1: index = wid. SPURS2: Unused. + atomic_t wklMaxContention[0x10]; // 0x50 Max SPUs that may be allocated to each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. + CellSpursWorkloadFlag wklFlag; // 0x60 + atomic_be_t wklSignal1; // 0x70 Bitset for 0..15 wids + atomic_t sysSrvMessage; // 0x72 + u8 spuIdling; // 0x73 + u8 flags1; // 0x74 Type is SpursFlags1 + u8 sysSrvTraceControl; // 0x75 + u8 nSpus; // 0x76 + atomic_t wklFlagReceiver; // 0x77 + atomic_be_t wklSignal2; // 0x78 Bitset for 16..32 wids + u8 x7A[6]; // 0x7A + atomic_t wklState1[0x10]; // 0x80 SPURS_WKL_STATE_* + u8 wklStatus1[0x10]; // 0x90 + atomic_t wklEvent1[0x10]; // 0xA0 + atomic_be_t wklEnabled; // 0xB0 + atomic_be_t wklMskB; // 0xB4 - System service - Available module id + u32 xB8; // 0xB8 + u8 sysSrvExitBarrier; // 0xBC + atomic_t sysSrvMsgUpdateWorkload; // 0xBD + u8 xBE; // 0xBE + u8 sysSrvMsgTerminate; // 0xBF + u8 sysSrvPreemptWklId[8]; // 0xC0 Id of the workload that was preempted by the system workload on each SPU + u8 sysSrvOnSpu; // 0xC8 + u8 spuPort; // 0xC9 + u8 xCA; // 0xCA + u8 xCB; // 0xCB + + struct alignas(4) SrvTraceSyncVar + { + u8 sysSrvTraceInitialised; // 0xCC + u8 sysSrvNotifyUpdateTraceComplete; // 0xCD + u8 sysSrvMsgUpdateTrace; // 0xCE + u8 xCF; + }; + + atomic_t sysSrvTrace; // 0xCC + + atomic_t wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_* + u8 wklStatus2[0x10]; // 0xE0 + atomic_t wklEvent2[0x10]; // 0xF0 + _sub_str1 wklF1[0x10]; // 0x100 + vm::bptr traceBuffer; // 0x900 + be_t traceStartIndex[6]; // 0x908 + u8 unknown7[0x948 - 0x920]; // 0x920 + be_t traceDataSize; // 0x948 + be_t traceMode; // 0x950 + u8 unknown8[0x980 - 0x954]; // 0x954 + be_t semPrv; // 0x980 + be_t unk11; // 0x988 + be_t unk12; // 0x98C + be_t unk13; // 0x990 + u8 unknown4[0xB00 - 0x998]; + WorkloadInfo wklInfo1[0x10]; // 0xB00 + WorkloadInfo wklInfoSysSrv; // 0xD00 + be_t ppu0; // 0xD20 Handler thread + be_t ppu1; // 0xD28 + be_t spuTG; // 0xD30 SPU thread group + be_t spus[8]; // 0xD34 + u8 unknown3[0xD5C - 0xD54]; + be_t eventQueue; // 0xD5C + be_t eventPort; // 0xD60 + atomic_t handlerDirty; // 0xD64 + atomic_t handlerWaiting; // 0xD65 + atomic_t handlerExiting; // 0xD66 + atomic_be_t enableEH; // 0xD68 + be_t exception; // 0xD6C + sys_spu_image_t spuImg; // 0xD70 + be_t flags; // 0xD80 + be_t spuPriority; // 0xD84 + be_t ppuPriority; // 0xD88 + char prefix[0x0f]; // 0xD8C + u8 prefixSize; // 0xD9B + be_t unk5; // 0xD9C + be_t revision; // 0xDA0 + be_t sdkVersion; // 0xDA4 + atomic_be_t spuPortBits; // 0xDA8 + sys_lwmutex_t mutex; // 0xDB0 + sys_lwcond_t cond; // 0xDC8 + u8 unknown9[0xE00 - 0xDD0]; + _sub_str4 wklH1[0x10]; // 0xE00 + EventPortMux eventPortMux; // 0xF00 + atomic_be_t globalSpuExceptionHandler; // 0xF80 + be_t globalSpuExceptionHandlerArgs; // 0xF88 + u8 unknown6[0x1000 - 0xF90]; + WorkloadInfo wklInfo2[0x10]; // 0x1000 + _sub_str1 wklF2[0x10]; // 0x1200 + _sub_str4 wklH2[0x10]; // 0x1A00 + u8 unknown_[0x2000 - 0x1B00]; + + force_inline atomic_t& wklState(const u32 wid) + { + if (wid & 0x10) + { + return wklState2[wid & 0xf]; + } + else + { + return wklState1[wid & 0xf]; + } + } +}; + +CHECK_SIZE_ALIGN(CellSpurs, 0x2000, 128); + +using CellSpurs2 = CellSpurs; + +struct CellSpursExceptionInfo +{ + be_t spu_thread; + be_t spu_npc; + be_t cause; + be_t option; +}; + +// Exception handler +using CellSpursGlobalExceptionEventHandler = void(vm::ptr spurs, vm::cptr info, u32 id, vm::ptr arg); + +struct CellSpursWorkloadAttribute +{ + be_t revision; + be_t sdkVersion; + vm::bcptr pm; + be_t size; + be_t data; + u8 priority[8]; + be_t minContention; + be_t maxContention; + vm::bcptr nameClass; + vm::bcptr nameInstance; + vm::bptr hook; + vm::bptr hookArg; + u8 padding[456]; +}; + +CHECK_SIZE_ALIGN(CellSpursWorkloadAttribute, 512, 8); + +struct alignas(128) CellSpursEventFlag +{ + struct alignas(8) ControlSyncVar + { + be_t events; // 0x00 Event bits + be_t spuTaskPendingRecv; // 0x02 A bit is set to 1 when the condition of the SPU task using the slot are met and back to 0 when the SPU task unblocks + be_t ppuWaitMask; // 0x04 Wait mask for blocked PPU thread + u8 ppuWaitSlotAndMode; // 0x06 Top 4 bits: Wait slot number of the blocked PPU threa, Bottom 4 bits: Wait mode of the blocked PPU thread + u8 ppuPendingRecv; // 0x07 Set to 1 when the blocked PPU thread's conditions are met and back to 0 when the PPU thread is unblocked + }; + + union + { + atomic_t ctrl; // 0x00 + atomic_be_t events; // 0x00 + }; + + be_t spuTaskUsedWaitSlots; // 0x08 A bit is set to 1 if the wait slot corresponding to the bit is used by an SPU task and 0 otherwise + be_t spuTaskWaitMode; // 0x0A A bit is set to 1 if the wait mode for the SPU task corresponding to the bit is AND and 0 otherwise + u8 spuPort; // 0x0C + u8 isIwl; // 0x0D + u8 direction; // 0x0E + u8 clearMode; // 0x0F + be_t spuTaskWaitMask[16]; // 0x10 Wait mask for blocked SPU tasks + be_t pendingRecvTaskEvents[16]; // 0x30 The value of event flag when the wait condition for the thread/task was met + u8 waitingTaskId[16]; // 0x50 Task id of waiting SPU threads + u8 waitingTaskWklId[16]; // 0x60 Workload id of waiting SPU threads + be_t addr; // 0x70 + be_t eventPortId; // 0x78 + be_t eventQueueId; // 0x7C +}; + +CHECK_SIZE_ALIGN(CellSpursEventFlag, 128, 128); + +using CellSpursLFQueue = CellSyncLFQueue; + +union CellSpursTaskArgument +{ + be_t _u32[4]; + be_t _u64[2]; +}; + +union CellSpursTaskLsPattern +{ + be_t _u32[4]; + be_t _u64[2]; +}; + +struct alignas(16) CellSpursTaskAttribute +{ + u8 reserved[256]; +}; + +CHECK_SIZE_ALIGN(CellSpursTaskAttribute, 256, 16); + +struct alignas(16) CellSpursTaskAttribute2 +{ + be_t revision; + be_t sizeContext; + be_t eaContext; + CellSpursTaskLsPattern lsPattern; + vm::bcptr name; + + u8 reserved[220]; +}; + +CHECK_SIZE_ALIGN(CellSpursTaskAttribute2, 256, 16); + +// Exception handler +using CellSpursTasksetExceptionEventHandler = void(vm::ptr spurs, vm::ptr taskset, u32 idTask, vm::cptr info, vm::ptr arg); + +struct alignas(128) CellSpursTaskExitCode +{ + u8 skip[128]; +}; + +CHECK_SIZE_ALIGN(CellSpursTaskExitCode, 128, 128); + +struct CellSpursTaskInfo +{ + CellSpursTaskLsPattern lsPattern; + CellSpursTaskArgument argument; + vm::bptr eaElf; + vm::bptr eaContext; + be_t sizeContext; + u8 state; + u8 hasSignal; + u8 padding[2]; + vm::bcptr eaTaskExitCode; + u8 guid[8]; + u8 reserved[12]; +}; + +CHECK_SIZE(CellSpursTaskInfo, 72); + +struct CellSpursTasksetInfo +{ + CellSpursTaskInfo taskInfo[CELL_SPURS_MAX_TASK]; + be_t argument; + be_t idWorkload; + be_t idLastScheduledTask; + vm::bcptr name; + vm::bptr exceptionEventHandler; + vm::bptr exceptionEventHandlerArgument; + be_t sizeTaskset; + u8 reserved[112]; +}; + +CHECK_SIZE(CellSpursTasksetInfo, 9360); + +struct alignas(8) CellSpursTasksetAttribute +{ + be_t revision; // 0x00 + be_t sdk_version; // 0x04 + be_t args; // 0x08 + u8 priority[8]; // 0x10 + be_t max_contention; // 0x18 + vm::bcptr name; // 0x1C + be_t taskset_size; // 0x20 + be_t enable_clear_ls; // 0x24 + u8 reserved[472]; +}; + +CHECK_SIZE_ALIGN(CellSpursTasksetAttribute, 512, 8); + +struct alignas(128) CellSpursTaskset +{ + struct TaskInfo + { + CellSpursTaskArgument args; // 0x00 + vm::bcptr elf; // 0x10 + be_t context_save_storage_and_alloc_ls_blocks; // 0x18 This is (context_save_storage_addr | allocated_ls_blocks) + CellSpursTaskLsPattern ls_pattern; // 0x20 + }; + + CHECK_SIZE(TaskInfo, 48); + + be_t running; // 0x00 + be_t ready; // 0x10 + be_t pending_ready; // 0x20 + be_t enabled; // 0x30 + be_t signalled; // 0x40 + be_t waiting; // 0x50 + vm::bptr spurs; // 0x60 + be_t args; // 0x68 + u8 enable_clear_ls; // 0x70 + u8 x71; // 0x71 + u8 wkl_flag_wait_task; // 0x72 + u8 last_scheduled_task; // 0x73 + be_t wid; // 0x74 + be_t x78; // 0x78 + TaskInfo task_info[128]; // 0x80 + vm::bptr exception_handler; // 0x1880 + vm::bptr exception_handler_arg; // 0x1888 + be_t size; // 0x1890 + u32 unk2; // 0x1894 + u32 event_flag_id1; // 0x1898 + u32 event_flag_id2; // 0x189C + u8 unk3[0x60]; // 0x18A0 +}; + +CHECK_SIZE_ALIGN(CellSpursTaskset, 128 * 50, 128); + +struct alignas(128) CellSpursTaskset2 +{ + struct TaskInfo + { + CellSpursTaskArgument args; + vm::bptr elf_addr; + vm::bptr context_save_storage; // This is (context_save_storage_addr | allocated_ls_blocks) + CellSpursTaskLsPattern ls_pattern; + }; + + CHECK_SIZE(TaskInfo, 48); + + be_t running_set[4]; // 0x00 + be_t ready_set[4]; // 0x10 + be_t ready2_set[4]; // 0x20 - TODO: Find out what this is + be_t enabled_set[4]; // 0x30 + be_t signal_received_set[4]; // 0x40 + be_t waiting_set[4]; // 0x50 + vm::bptr spurs; // 0x60 + be_t args; // 0x68 + u8 enable_clear_ls; // 0x70 + u8 x71; // 0x71 + u8 x72; // 0x72 + u8 last_scheduled_task; // 0x73 + be_t wid; // 0x74 + be_t x78; // 0x78 + TaskInfo task_info[128]; // 0x80 + vm::bptr exception_handler; // 0x1880 + vm::bptr exception_handler_arg; // 0x1888 + be_t size; // 0x1890 + u32 unk2; // 0x1894 + u32 event_flag_id1; // 0x1898 + u32 event_flag_id2; // 0x189C + u8 unk3[0x1980 - 0x18A0]; // 0x18A0 + be_t task_exit_code[128]; // 0x1980 + u8 unk4[0x2900 - 0x2180]; // 0x2180 +}; + +CHECK_SIZE_ALIGN(CellSpursTaskset2, 128 * 82, 128); + +struct alignas(16) CellSpursTaskNameBuffer +{ + char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH]; +}; + +struct alignas(8) CellSpursTasksetAttribute2 +{ + be_t revision; // 0x00 + vm::bcptr name; // 0x04 + be_t args; // 0x08 + u8 priority[8]; // 0x10 + be_t max_contention; // 0x18 + be_t enable_clear_ls; // 0x1C + vm::bptr task_name_buffer; // 0x20 + u8 reserved[472]; +}; + +CHECK_SIZE_ALIGN(CellSpursTasksetAttribute2, 512, 8); + +struct alignas(16) CellSpursTaskBinInfo +{ + be_t eaElf; + be_t sizeContext; + be_t reserved; + CellSpursTaskLsPattern lsPattern; +}; + +// The SPURS kernel context. This resides at 0x100 of the LS. +struct SpursKernelContext +{ + u8 tempArea[0x80]; // 0x100 + u8 wklLocContention[0x10]; // 0x180 + u8 wklLocPendingContention[0x10]; // 0x190 + u8 priority[0x10]; // 0x1A0 + u8 x1B0[0x10]; // 0x1B0 + vm::bptr spurs; // 0x1C0 + be_t spuNum; // 0x1C8 + be_t dmaTagId; // 0x1CC + vm::bcptr wklCurrentAddr; // 0x1D0 + be_t wklCurrentUniqueId; // 0x1D8 + be_t wklCurrentId; // 0x1DC + be_t exitToKernelAddr; // 0x1E0 + be_t selectWorkloadAddr; // 0x1E4 + u8 moduleId[2]; // 0x1E8 + u8 sysSrvInitialised; // 0x1EA + u8 spuIdling; // 0x1EB + be_t wklRunnable1; // 0x1EC + be_t wklRunnable2; // 0x1EE + be_t x1F0; // 0x1F0 + be_t x1F4; // 0x1F4 + be_t x1F8; // 0x1F8 + be_t x1FC; // 0x1FC + be_t x200; // 0x200 + be_t x204; // 0x204 + be_t x208; // 0x208 + be_t x20C; // 0x20C + be_t traceBuffer; // 0x210 + be_t traceMsgCount; // 0x218 + be_t traceMaxCount; // 0x21C + u8 wklUniqueId[0x10]; // 0x220 + u8 x230[0x280 - 0x230]; // 0x230 + be_t guid[4]; // 0x280 +}; + +CHECK_SIZE(SpursKernelContext, 0x190); + +// The SPURS taskset policy module context. This resides at 0x2700 of the LS. +struct SpursTasksetContext +{ + u8 tempAreaTaskset[0x80]; // 0x2700 + u8 tempAreaTaskInfo[0x30]; // 0x2780 + be_t x27B0; // 0x27B0 + vm::bptr taskset; // 0x27B8 + be_t kernelMgmtAddr; // 0x27C0 + be_t syscallAddr; // 0x27C4 + be_t x27C8; // 0x27C8 + be_t spuNum; // 0x27CC + be_t dmaTagId; // 0x27D0 + be_t taskId; // 0x27D4 + u8 x27D8[0x2840 - 0x27D8]; // 0x27D8 + u8 moduleId[16]; // 0x2840 + u8 stackArea[0x2C80 - 0x2850]; // 0x2850 + be_t savedContextLr; // 0x2C80 + be_t savedContextSp; // 0x2C90 + be_t savedContextR80ToR127[48]; // 0x2CA0 + be_t savedContextFpscr; // 0x2FA0 + be_t savedWriteTagGroupQueryMask; // 0x2FB0 + be_t savedSpuWriteEventMask; // 0x2FB4 + be_t tasksetMgmtAddr; // 0x2FB8 + be_t guidAddr; // 0x2FBC + be_t x2FC0; // 0x2FC0 + be_t x2FC8; // 0x2FC8 + be_t taskExitCode; // 0x2FD0 + be_t x2FD4; // 0x2FD4 + u8 x2FD8[0x3000 - 0x2FD8]; // 0x2FD8 +}; + +CHECK_SIZE(SpursTasksetContext, 0x900); + +class SpursModuleExit +{ +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursJq.cpp b/rpcs3/Emu/Cell/Modules/cellSpursJq.cpp similarity index 97% rename from rpcs3/Emu/SysCalls/Modules/cellSpursJq.cpp rename to rpcs3/Emu/Cell/Modules/cellSpursJq.cpp index 1a943ebccc..b5d85f2d5c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursJq.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSpursJq.cpp @@ -1,16 +1,14 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/SysCalls/lv2/sys_sync.h" -#include "Emu/SysCalls/lv2/sys_lwmutex.h" -#include "Emu/SysCalls/lv2/sys_lwcond.h" -#include "Emu/SysCalls/lv2/sys_spu.h" +#include "Emu/Cell/lv2/sys_lwmutex.h" +#include "Emu/Cell/lv2/sys_lwcond.h" +#include "Emu/Cell/lv2/sys_spu.h" #include "cellSpurs.h" #include "cellSpursJq.h" -extern Module<> cellSpursJq; +LOG_CHANNEL(cellSpursJq); s32 cellSpursJobQueueAttributeInitialize() { @@ -390,7 +388,7 @@ s32 cellSpursJobQueueUnsetExceptionEventHandler() return CELL_OK; } -Module<> cellSpursJq("cellSpursJq", []() +DECLARE(ppu_module_manager::cellSpursJq)("cellSpursJq", []() { REG_FUNC(cellSpursJq, cellSpursJobQueueAttributeInitialize); REG_FUNC(cellSpursJq, cellSpursJobQueueAttributeSetMaxGrab); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursJq.h b/rpcs3/Emu/Cell/Modules/cellSpursJq.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellSpursJq.h rename to rpcs3/Emu/Cell/Modules/cellSpursJq.h diff --git a/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp b/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp new file mode 100644 index 0000000000..eb56cdd302 --- /dev/null +++ b/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp @@ -0,0 +1,1986 @@ +#include "stdafx.h" +#include "Loader/ELF.h" +#include "Emu/System.h" +#include "Emu/Cell/PPUModule.h" + +#include "Emu/Cell/SPUThread.h" +#include "Emu/Cell/lv2/sys_lwmutex.h" +#include "Emu/Cell/lv2/sys_lwcond.h" +#include "Emu/Cell/lv2/sys_spu.h" +#include "cellSpurs.h" + +//---------------------------------------------------------------------------- +// Externs +//---------------------------------------------------------------------------- + +extern _log::channel cellSpurs; + +//---------------------------------------------------------------------------- +// Function prototypes +//---------------------------------------------------------------------------- + +// +// SPURS utility functions +// +static void cellSpursModulePutTrace(CellSpursTracePacket* packet, u32 dmaTagId); +static u32 cellSpursModulePollStatus(SPUThread& spu, u32* status); +static void cellSpursModuleExit(SPUThread& spu); + +static bool spursDma(SPUThread& spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag); +static u32 spursDmaGetCompletionStatus(SPUThread& spu, u32 tagMask); +static u32 spursDmaWaitForCompletion(SPUThread& spu, u32 tagMask, bool waitForAll = true); +static void spursHalt(SPUThread& spu); + +// +// SPURS kernel functions +// +static bool spursKernel1SelectWorkload(SPUThread& spu); +static bool spursKernel2SelectWorkload(SPUThread& spu); +static void spursKernelDispatchWorkload(SPUThread& spu, u64 widAndPollStatus); +static bool spursKernelWorkloadExit(SPUThread& spu); +bool spursKernelEntry(SPUThread& spu); + +// +// SPURS system workload functions +// +static bool spursSysServiceEntry(SPUThread& spu); +// TODO: Exit +static void spursSysServiceIdleHandler(SPUThread& spu, SpursKernelContext* ctxt); +static void spursSysServiceMain(SPUThread& spu, u32 pollStatus); +static void spursSysServiceProcessRequests(SPUThread& spu, SpursKernelContext* ctxt); +static void spursSysServiceActivateWorkload(SPUThread& spu, SpursKernelContext* ctxt); +// TODO: Deactivate workload +static void spursSysServiceUpdateShutdownCompletionEvents(SPUThread& spu, SpursKernelContext* ctxt, u32 wklShutdownBitSet); +static void spursSysServiceTraceSaveCount(SPUThread& spu, SpursKernelContext* ctxt); +static void spursSysServiceTraceUpdate(SPUThread& spu, SpursKernelContext* ctxt, u32 arg2, u32 arg3, u32 forceNotify); +// TODO: Deactivate trace +// TODO: System workload entry +static void spursSysServiceCleanupAfterSystemWorkload(SPUThread& spu, SpursKernelContext* ctxt); + +// +// SPURS taskset policy module functions +// +static bool spursTasksetEntry(SPUThread& spu); +static bool spursTasksetSyscallEntry(SPUThread& spu); +static void spursTasksetResumeTask(SPUThread& spu); +static void spursTasksetStartTask(SPUThread& spu, CellSpursTaskArgument& taskArgs); +static s32 spursTasksetProcessRequest(SPUThread& spu, s32 request, u32* taskId, u32* isWaiting); +static void spursTasksetProcessPollStatus(SPUThread& spu, u32 pollStatus); +static bool spursTasksetPollStatus(SPUThread& spu); +static void spursTasksetExit(SPUThread& spu); +static void spursTasksetOnTaskExit(SPUThread& spu, u64 addr, u32 taskId, s32 exitCode, u64 args); +static s32 spursTasketSaveTaskContext(SPUThread& spu); +static void spursTasksetDispatch(SPUThread& spu); +static s32 spursTasksetProcessSyscall(SPUThread& spu, u32 syscallNum, u32 args); +static void spursTasksetInit(SPUThread& spu, u32 pollStatus); +static s32 spursTasksetLoadElf(SPUThread& spu, u32* entryPoint, u32* lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments); + +//---------------------------------------------------------------------------- +// SPURS utility functions +//---------------------------------------------------------------------------- + +// Output trace information +void cellSpursModulePutTrace(CellSpursTracePacket* packet, u32 dmaTagId) +{ + // TODO: Implement this +} + +// Check for execution right requests +u32 cellSpursModulePollStatus(SPUThread& spu, u32* status) +{ + auto ctxt = vm::_ptr(spu.offset + 0x100); + + spu.gpr[3]._u32[3] = 1; + if (ctxt->spurs->flags1 & SF1_32_WORKLOADS) + { + spursKernel2SelectWorkload(spu); + } + else + { + spursKernel1SelectWorkload(spu); + } + + auto result = spu.gpr[3]._u64[1]; + if (status) + { + *status = (u32)result; + } + + u32 wklId = result >> 32; + return wklId == ctxt->wklCurrentId ? 0 : 1; +} + +// Exit current workload +void cellSpursModuleExit(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x100); + spu.pc = ctxt->exitToKernelAddr - 4; + throw SpursModuleExit(); +} + +// Execute a DMA operation +bool spursDma(SPUThread& spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag) +{ + spu.set_ch_value(MFC_LSA, lsa); + spu.set_ch_value(MFC_EAH, (u32)(ea >> 32)); + spu.set_ch_value(MFC_EAL, (u32)(ea)); + spu.set_ch_value(MFC_Size, size); + spu.set_ch_value(MFC_TagID, tag); + spu.set_ch_value(MFC_Cmd, cmd); + + if (cmd == MFC_GETLLAR_CMD || cmd == MFC_PUTLLC_CMD || cmd == MFC_PUTLLUC_CMD) + { + u32 rv; + + rv = spu.get_ch_value(MFC_RdAtomicStat); + auto success = rv ? true : false; + success = cmd == MFC_PUTLLC_CMD ? !success : success; + return success; + } + + return true; +} + +// Get the status of DMA operations +u32 spursDmaGetCompletionStatus(SPUThread& spu, u32 tagMask) +{ + spu.set_ch_value(MFC_WrTagMask, tagMask); + spu.set_ch_value(MFC_WrTagUpdate, MFC_TAG_UPDATE_IMMEDIATE); + return spu.get_ch_value(MFC_RdTagStat); +} + +// Wait for DMA operations to complete +u32 spursDmaWaitForCompletion(SPUThread& spu, u32 tagMask, bool waitForAll) +{ + spu.set_ch_value(MFC_WrTagMask, tagMask); + spu.set_ch_value(MFC_WrTagUpdate, waitForAll ? MFC_TAG_UPDATE_ALL : MFC_TAG_UPDATE_ANY); + return spu.get_ch_value(MFC_RdTagStat); +} + +// Halt the SPU +void spursHalt(SPUThread& spu) +{ + spu.halt(); +} + +//---------------------------------------------------------------------------- +// SPURS kernel functions +//---------------------------------------------------------------------------- + +// Select a workload to run +bool spursKernel1SelectWorkload(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x100); + + // The first and only argument to this function is a boolean that is set to false if the function + // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. + // If the first argument is true then the shared data is not updated with the result. + const auto isPoll = spu.gpr[3]._u32[3]; + + u32 wklSelectedId; + u32 pollStatus; + + vm::reservation_op(vm::cast(ctxt->spurs.addr(), HERE), 128, [&]() + { + // lock the first 0x80 bytes of spurs + auto spurs = ctxt->spurs.get_ptr_priv(); + + // Calculate the contention (number of SPUs used) for each workload + u8 contention[CELL_SPURS_MAX_WORKLOAD]; + u8 pendingContention[CELL_SPURS_MAX_WORKLOAD]; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + contention[i] = spurs->wklCurrentContention[i] - ctxt->wklLocContention[i]; + + // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably + // to prevent unnecessary jumps to the kernel + if (isPoll) + { + pendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; + if (i != ctxt->wklCurrentId) + { + contention[i] += pendingContention[i]; + } + } + } + + wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + pollStatus = 0; + + // The system service has the highest priority. Select the system service if + // the system service message bit for this SPU is set. + if (spurs->sysSrvMessage & (1 << ctxt->spuNum)) + { + ctxt->spuIdling = 0; + if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + // Clear the message bit + spurs->sysSrvMessage.raw() &= ~(1 << ctxt->spuNum); + } + } + else + { + // Caclulate the scheduling weight for each workload + u16 maxWeight = 0; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i); + u16 wklSignal = spurs->wklSignal1.load() & (0x8000 >> i); + u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver == i ? 1 : 0 : 0; + u8 readyCount = spurs->wklReadyCount1[i] > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].load(); + u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i] > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].load(); + u8 requestCount = readyCount + idleSpuCount; + + // For a workload to be considered for scheduling: + // 1. Its priority must not be 0 + // 2. The number of SPUs used by it must be less than the max contention for that workload + // 3. The workload should be in runnable state + // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) + // OR the workload must be signalled + // OR the workload flag is 0 and the workload is configured as the wokload flag receiver + if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i] > contention[i]) + { + if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) + { + // The scheduling weight of the workload is formed from the following parameters in decreasing order of priority: + // 1. Wokload signal set or workload flag or ready count > contention + // 2. Priority of the workload on the SPU + // 3. Is the workload the last selected workload + // 4. Minimum contention of the workload + // 5. Number of SPUs that are being used by the workload (lesser the number, more the weight) + // 6. Is the workload executable same as the currently loaded executable + // 7. The workload id (lesser the number, more the weight) + u16 weight = (wklFlag || wklSignal || (readyCount > contention[i])) ? 0x8000 : 0; + weight |= (u16)(ctxt->priority[i] & 0x7F) << 16; + weight |= i == ctxt->wklCurrentId ? 0x80 : 0x00; + weight |= (contention[i] > 0 && spurs->wklMinContention[i] > contention[i]) ? 0x40 : 0x00; + weight |= ((CELL_SPURS_MAX_SPU - contention[i]) & 0x0F) << 2; + weight |= ctxt->wklUniqueId[i] == ctxt->wklCurrentId ? 0x02 : 0x00; + weight |= 0x01; + + // In case of a tie the lower numbered workload is chosen + if (weight > maxWeight) + { + wklSelectedId = i; + maxWeight = weight; + pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; + pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; + pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; + } + } + } + } + + // Not sure what this does. Possibly mark the SPU as idle/in use. + ctxt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + + if (!isPoll || wklSelectedId == ctxt->wklCurrentId) + { + // Clear workload signal for the selected workload + spurs->wklSignal1.raw() &= ~(0x8000 >> wklSelectedId); + spurs->wklSignal2.raw() &= ~(0x80000000u >> wklSelectedId); + + // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s + if (wklSelectedId == spurs->wklFlagReceiver) + { + spurs->wklFlag.flag = -1; + } + } + } + + if (!isPoll) + { + // Called by kernel + // Increment the contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + contention[wklSelectedId]++; + } + + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + spurs->wklCurrentContention[i] = contention[i]; + spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; + ctxt->wklLocContention[i] = 0; + ctxt->wklLocPendingContention[i] = 0; + } + + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + ctxt->wklLocContention[wklSelectedId] = 1; + } + + ctxt->wklCurrentId = wklSelectedId; + } + else if (wklSelectedId != ctxt->wklCurrentId) + { + // Not called by kernel but a context switch is required + // Increment the pending contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + pendingContention[wklSelectedId]++; + } + + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + spurs->wklPendingContention[i] = pendingContention[i]; + ctxt->wklLocPendingContention[i] = 0; + } + + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + ctxt->wklLocPendingContention[wklSelectedId] = 1; + } + } + else + { + // Not called by kernel and no context switch is required + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; + ctxt->wklLocPendingContention[i] = 0; + } + } + + std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); + }); + + u64 result = (u64)wklSelectedId << 32; + result |= pollStatus; + spu.gpr[3]._u64[1] = result; + return true; +} + +// Select a workload to run +bool spursKernel2SelectWorkload(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x100); + + // The first and only argument to this function is a boolean that is set to false if the function + // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. + // If the first argument is true then the shared data is not updated with the result. + const auto isPoll = spu.gpr[3]._u32[3]; + + u32 wklSelectedId; + u32 pollStatus; + + vm::reservation_op(vm::cast(ctxt->spurs.addr(), HERE), 128, [&]() + { + // lock the first 0x80 bytes of spurs + auto spurs = ctxt->spurs.get_ptr_priv(); + + // Calculate the contention (number of SPUs used) for each workload + u8 contention[CELL_SPURS_MAX_WORKLOAD2]; + u8 pendingContention[CELL_SPURS_MAX_WORKLOAD2]; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) + { + contention[i] = spurs->wklCurrentContention[i & 0x0F] - ctxt->wklLocContention[i & 0x0F]; + contention[i] = i < CELL_SPURS_MAX_WORKLOAD ? contention[i] & 0x0F : contention[i] >> 4; + + // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably + // to prevent unnecessary jumps to the kernel + if (isPoll) + { + pendingContention[i] = spurs->wklPendingContention[i & 0x0F] - ctxt->wklLocPendingContention[i & 0x0F]; + pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4; + if (i != ctxt->wklCurrentId) + { + contention[i] += pendingContention[i]; + } + } + } + + wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + pollStatus = 0; + + // The system service has the highest priority. Select the system service if + // the system service message bit for this SPU is set. + if (spurs->sysSrvMessage & (1 << ctxt->spuNum)) + { + // Not sure what this does. Possibly Mark the SPU as in use. + ctxt->spuIdling = 0; + if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + // Clear the message bit + spurs->sysSrvMessage.raw() &= ~(1 << ctxt->spuNum); + } + } + else + { + // Caclulate the scheduling weight for each workload + u8 maxWeight = 0; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) + { + auto j = i & 0x0F; + u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); + u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4; + u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j] & 0x0F : spurs->wklMaxContention[j] >> 4; + u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.load() & (0x8000 >> j) : spurs->wklSignal2.load() & (0x8000 >> j); + u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver == i ? 1 : 0 : 0; + u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j] : spurs->wklIdleSpuCountOrReadyCount2[j]; + + // For a workload to be considered for scheduling: + // 1. Its priority must be greater than 0 + // 2. The number of SPUs used by it must be less than the max contention for that workload + // 3. The workload should be in runnable state + // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) + // OR the workload must be signalled + // OR the workload flag is 0 and the workload is configured as the wokload receiver + if (runnable && priority > 0 && maxContention > contention[i]) + { + if (wklFlag || wklSignal || readyCount > contention[i]) + { + // The scheduling weight of the workload is equal to the priority of the workload for the SPU. + // The current workload is given a sligtly higher weight presumably to reduce the number of context switches. + // In case of a tie the lower numbered workload is chosen. + u8 weight = priority << 4; + if (ctxt->wklCurrentId == i) + { + weight |= 0x04; + } + + if (weight > maxWeight) + { + wklSelectedId = i; + maxWeight = weight; + pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; + pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; + pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; + } + } + } + } + + // Not sure what this does. Possibly mark the SPU as idle/in use. + ctxt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + + if (!isPoll || wklSelectedId == ctxt->wklCurrentId) + { + // Clear workload signal for the selected workload + spurs->wklSignal1.raw() &= ~(0x8000 >> wklSelectedId); + spurs->wklSignal2.raw() &= ~(0x80000000u >> wklSelectedId); + + // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s + if (wklSelectedId == spurs->wklFlagReceiver) + { + spurs->wklFlag.flag = -1; + } + } + } + + if (!isPoll) + { + // Called by kernel + // Increment the contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + contention[wklSelectedId]++; + } + + for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) + { + spurs->wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4); + spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; + ctxt->wklLocContention[i] = 0; + ctxt->wklLocPendingContention[i] = 0; + } + + ctxt->wklLocContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; + ctxt->wklCurrentId = wklSelectedId; + } + else if (wklSelectedId != ctxt->wklCurrentId) + { + // Not called by kernel but a context switch is required + // Increment the pending contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + pendingContention[wklSelectedId]++; + } + + for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) + { + spurs->wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4); + ctxt->wklLocPendingContention[i] = 0; + } + + ctxt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; + } + else + { + // Not called by kernel and no context switch is required + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; + ctxt->wklLocPendingContention[i] = 0; + } + } + + std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); + }); + + u64 result = (u64)wklSelectedId << 32; + result |= pollStatus; + spu.gpr[3]._u64[1] = result; + return true; +} + +// SPURS kernel dispatch workload +void spursKernelDispatchWorkload(SPUThread& spu, u64 widAndPollStatus) +{ + auto ctxt = vm::_ptr(spu.offset + 0x100); + auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false; + + auto pollStatus = (u32)widAndPollStatus; + auto wid = (u32)(widAndPollStatus >> 32); + + // DMA in the workload info for the selected workload + auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? &ctxt->spurs->wklInfo1[wid] : + wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &ctxt->spurs->wklInfo2[wid & 0xf] : + &ctxt->spurs->wklInfoSysSrv; + + std::memcpy(vm::base(spu.offset + 0x3FFE0), wklInfoOffset, 0x20); + + // Load the workload to LS + auto wklInfo = vm::_ptr(spu.offset + 0x3FFE0); + if (ctxt->wklCurrentAddr != wklInfo->addr) + { + switch (wklInfo->addr.addr()) + { + case SPURS_IMG_ADDR_SYS_SRV_WORKLOAD: + spu.RegisterHleFunction(0xA00, spursSysServiceEntry); + break; + case SPURS_IMG_ADDR_TASKSET_PM: + spu.RegisterHleFunction(0xA00, spursTasksetEntry); + break; + default: + std::memcpy(vm::base(spu.offset + 0xA00), wklInfo->addr.get_ptr(), wklInfo->size); + break; + } + + ctxt->wklCurrentAddr = wklInfo->addr; + ctxt->wklCurrentUniqueId = wklInfo->uniqueId; + } + + if (!isKernel2) + { + ctxt->moduleId[0] = 0; + ctxt->moduleId[1] = 0; + } + + // Run workload + spu.gpr[0]._u32[3] = ctxt->exitToKernelAddr; + spu.gpr[1]._u32[3] = 0x3FFB0; + spu.gpr[3]._u32[3] = 0x100; + spu.gpr[4]._u64[1] = wklInfo->arg; + spu.gpr[5]._u32[3] = pollStatus; + spu.pc = 0xA00 - 4; +} + +// SPURS kernel workload exit +bool spursKernelWorkloadExit(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x100); + auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false; + + // Select next workload to run + spu.gpr[3].clear(); + if (isKernel2) + { + spursKernel2SelectWorkload(spu); + } + else + { + spursKernel1SelectWorkload(spu); + } + + spursKernelDispatchWorkload(spu, spu.gpr[3]._u64[1]); + return false; +} + +// SPURS kernel entry point +bool spursKernelEntry(SPUThread& spu) +{ + while (true) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + CHECK_EMU_STATUS; + } + + auto ctxt = vm::_ptr(spu.offset + 0x100); + memset(ctxt, 0, sizeof(SpursKernelContext)); + + // Save arguments + ctxt->spuNum = spu.gpr[3]._u32[3]; + ctxt->spurs.set(spu.gpr[4]._u64[1]); + + auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false; + + // Initialise the SPURS context to its initial values + ctxt->dmaTagId = CELL_SPURS_KERNEL_DMA_TAG_ID; + ctxt->wklCurrentUniqueId = 0x20; + ctxt->wklCurrentId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + ctxt->exitToKernelAddr = isKernel2 ? CELL_SPURS_KERNEL2_EXIT_ADDR : CELL_SPURS_KERNEL1_EXIT_ADDR; + ctxt->selectWorkloadAddr = isKernel2 ? CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR : CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR; + if (!isKernel2) + { + ctxt->x1F0 = 0xF0020000; + ctxt->x200 = 0x20000; + ctxt->guid[0] = 0x423A3A02; + ctxt->guid[1] = 0x43F43A82; + ctxt->guid[2] = 0x43F26502; + ctxt->guid[3] = 0x420EB382; + } + else + { + ctxt->guid[0] = 0x43A08402; + ctxt->guid[1] = 0x43FB0A82; + ctxt->guid[2] = 0x435E9302; + ctxt->guid[3] = 0x43A3C982; + } + + // Register SPURS kernel HLE functions + spu.UnregisterHleFunctions(0, 0x40000/*LS_BOTTOM*/); + spu.RegisterHleFunction(isKernel2 ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR, spursKernelEntry); + spu.RegisterHleFunction(ctxt->exitToKernelAddr, spursKernelWorkloadExit); + spu.RegisterHleFunction(ctxt->selectWorkloadAddr, isKernel2 ? spursKernel2SelectWorkload : spursKernel1SelectWorkload); + + // Start the system service + spursKernelDispatchWorkload(spu, ((u64)CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) << 32); + return false; +} + +//---------------------------------------------------------------------------- +// SPURS system workload functions +//---------------------------------------------------------------------------- + +// Entry point of the system service +bool spursSysServiceEntry(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + spu.gpr[3]._u32[3]); + auto arg = spu.gpr[4]._u64[1]; + auto pollStatus = spu.gpr[5]._u32[3]; + + try + { + if (ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + spursSysServiceMain(spu, pollStatus); + } + else + { + // TODO: If we reach here it means the current workload was preempted to start the + // system workload. Need to implement this. + } + + cellSpursModuleExit(spu); + } + + catch (SpursModuleExit) + { + } + + return false; +} + +// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled +void spursSysServiceIdleHandler(SPUThread& spu, SpursKernelContext* ctxt) +{ + bool shouldExit; + + std::unique_lock lock(spu.mutex, std::defer_lock); + + while (true) + { + vm::reservation_acquire(vm::base(spu.offset + 0x100), vm::cast(ctxt->spurs.addr(), HERE), 128); + auto spurs = vm::_ptr(spu.offset + 0x100); + + // Find the number of SPUs that are idling in this SPURS instance + u32 nIdlingSpus = 0; + for (u32 i = 0; i < 8; i++) + { + if (spurs->spuIdling & (1 << i)) + { + nIdlingSpus++; + } + } + + bool allSpusIdle = nIdlingSpus == spurs->nSpus ? true : false; + bool exitIfNoWork = spurs->flags1 & SF1_EXIT_IF_NO_WORK ? true : false; + shouldExit = allSpusIdle && exitIfNoWork; + + // Check if any workloads can be scheduled + bool foundReadyWorkload = false; + if (spurs->sysSrvMessage & (1 << ctxt->spuNum)) + { + foundReadyWorkload = true; + } + else + { + if (spurs->flags1 & SF1_32_WORKLOADS) + { + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) + { + u32 j = i & 0x0F; + u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); + u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4; + u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j] & 0x0F : spurs->wklMaxContention[j] >> 4; + u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklCurrentContention[j] & 0x0F : spurs->wklCurrentContention[j] >> 4; + u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.load() & (0x8000 >> j) : spurs->wklSignal2.load() & (0x8000 >> j); + u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver == i ? 1 : 0 : 0; + u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j] : spurs->wklIdleSpuCountOrReadyCount2[j]; + + if (runnable && priority > 0 && maxContention > contention) + { + if (wklFlag || wklSignal || readyCount > contention) + { + foundReadyWorkload = true; + break; + } + } + } + } + else + { + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i); + u16 wklSignal = spurs->wklSignal1.load() & (0x8000 >> i); + u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver == i ? 1 : 0 : 0; + u8 readyCount = spurs->wklReadyCount1[i] > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].load(); + u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i] > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].load(); + u8 requestCount = readyCount + idleSpuCount; + + if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i] > spurs->wklCurrentContention[i]) + { + if (wklFlag || wklSignal || (readyCount != 0 && requestCount > spurs->wklCurrentContention[i])) + { + foundReadyWorkload = true; + break; + } + } + } + } + } + + bool spuIdling = spurs->spuIdling & (1 << ctxt->spuNum) ? true : false; + if (foundReadyWorkload && shouldExit == false) + { + spurs->spuIdling &= ~(1 << ctxt->spuNum); + } + else + { + spurs->spuIdling |= 1 << ctxt->spuNum; + } + + // If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events. + if (spuIdling && shouldExit == false && foundReadyWorkload == false) + { + // The system service blocks by making a reservation and waiting on the lock line reservation lost event. + CHECK_EMU_STATUS; + if (!lock) lock.lock(); + spu.cv.wait_for(lock, std::chrono::milliseconds(1)); + continue; + } + + if (vm::reservation_update(vm::cast(ctxt->spurs.addr(), HERE), vm::base(spu.offset + 0x100), 128) && (shouldExit || foundReadyWorkload)) + { + break; + } + } + + if (shouldExit) + { + // TODO: exit spu thread group + } +} + +// Main function for the system service +void spursSysServiceMain(SPUThread& spu, u32 pollStatus) +{ + auto ctxt = vm::_ptr(spu.offset + 0x100); + + if (!ctxt->spurs.aligned()) + { + LOG_ERROR(SPU, "spursSysServiceMain(): invalid spurs alignment"); + spursHalt(spu); + } + + // Initialise the system service if this is the first time its being started on this SPU + if (ctxt->sysSrvInitialised == 0) + { + ctxt->sysSrvInitialised = 1; + + vm::reservation_acquire(vm::base(spu.offset + 0x100), vm::cast(ctxt->spurs.addr(), HERE), 128); + + vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() + { + auto spurs = ctxt->spurs.get_ptr_priv(); + + // Halt if already initialised + if (spurs->sysSrvOnSpu & (1 << ctxt->spuNum)) + { + LOG_ERROR(SPU, "spursSysServiceMain(): already initialized"); + spursHalt(spu); + } + + spurs->sysSrvOnSpu |= 1 << ctxt->spuNum; + + std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); + }); + + ctxt->traceBuffer = 0; + ctxt->traceMsgCount = -1; + spursSysServiceTraceUpdate(spu, ctxt, 1, 1, 0); + spursSysServiceCleanupAfterSystemWorkload(spu, ctxt); + + // Trace - SERVICE: INIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_INIT; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + } + + // Trace - START: Module='SYS ' + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_START; + memcpy(pkt.data.start.module, "SYS ", 4); + pkt.data.start.level = 1; // Policy module + pkt.data.start.ls = 0xA00 >> 2; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + while (true) + { + CHECK_EMU_STATUS; + // Process requests for the system service + spursSysServiceProcessRequests(spu, ctxt); + + poll: + if (cellSpursModulePollStatus(spu, nullptr)) + { + // Trace - SERVICE: EXIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_EXIT; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + // Trace - STOP: GUID + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; + pkt.data.stop = SPURS_GUID_SYS_WKL; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + break; + } + + // If we reach here it means that either there are more system service messages to be processed + // or there are no workloads that can be scheduled. + + // If the SPU is not idling then process the remaining system service messages + if (ctxt->spuIdling == 0) + { + continue; + } + + // If we reach here it means that the SPU is idling + + // Trace - SERVICE: WAIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_WAIT; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + spursSysServiceIdleHandler(spu, ctxt); + CHECK_EMU_STATUS; + + goto poll; + } +} + +// Process any requests +void spursSysServiceProcessRequests(SPUThread& spu, SpursKernelContext* ctxt) +{ + bool updateTrace = false; + bool updateWorkload = false; + bool terminate = false; + + vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1), HERE), 128, [&]() + { + auto spurs = ctxt->spurs.get_ptr_priv(); + + // Terminate request + if (spurs->sysSrvMsgTerminate & (1 << ctxt->spuNum)) + { + spurs->sysSrvOnSpu &= ~(1 << ctxt->spuNum); + terminate = true; + } + + // Update workload message + if (spurs->sysSrvMsgUpdateWorkload & (1 << ctxt->spuNum)) + { + spurs->sysSrvMsgUpdateWorkload &= ~(1 << ctxt->spuNum); + updateWorkload = true; + } + + // Update trace message + if (spurs->sysSrvTrace.load().sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) + { + updateTrace = true; + } + + std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); + }); + + // Process update workload message + if (updateWorkload) + { + spursSysServiceActivateWorkload(spu, ctxt); + } + + // Process update trace message + if (updateTrace) + { + spursSysServiceTraceUpdate(spu, ctxt, 1, 0, 0); + } + + // Process terminate request + if (terminate) + { + // TODO: Rest of the terminate processing + } +} + +// Activate a workload +void spursSysServiceActivateWorkload(SPUThread& spu, SpursKernelContext* ctxt) +{ + auto spurs = vm::_ptr(spu.offset + 0x100); + std::memcpy(vm::base(spu.offset + 0x30000), ctxt->spurs->wklInfo1, 0x200); + if (spurs->flags1 & SF1_32_WORKLOADS) + { + std::memcpy(vm::base(spu.offset + 0x30200), ctxt->spurs->wklInfo2, 0x200); + } + + u32 wklShutdownBitSet = 0; + ctxt->wklRunnable1 = 0; + ctxt->wklRunnable2 = 0; + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + auto wklInfo1 = vm::_ptr(spu.offset + 0x30000); + + // Copy the priority of the workload for this SPU and its unique id to the LS + ctxt->priority[i] = wklInfo1[i].priority[ctxt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[ctxt->spuNum]; + ctxt->wklUniqueId[i] = wklInfo1[i].uniqueId; + + if (spurs->flags1 & SF1_32_WORKLOADS) + { + auto wklInfo2 = vm::_ptr(spu.offset + 0x30200); + + // Copy the priority of the workload for this SPU to the LS + if (wklInfo2[i].priority[ctxt->spuNum]) + { + ctxt->priority[i] |= (0x10 - wklInfo2[i].priority[ctxt->spuNum]) << 4; + } + } + } + + vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() + { + auto spurs = ctxt->spurs.get_ptr_priv(); + + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + // Update workload status and runnable flag based on the workload state + auto wklStatus = spurs->wklStatus1[i]; + if (spurs->wklState1[i] == SPURS_WKL_STATE_RUNNABLE) + { + spurs->wklStatus1[i] |= 1 << ctxt->spuNum; + ctxt->wklRunnable1 |= 0x8000 >> i; + } + else + { + spurs->wklStatus1[i] &= ~(1 << ctxt->spuNum); + } + + // If the workload is shutting down and if this is the last SPU from which it is being removed then + // add it to the shutdown bit set + if (spurs->wklState1[i] == SPURS_WKL_STATE_SHUTTING_DOWN) + { + if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus1[i] == 0)) + { + spurs->wklState1[i] = SPURS_WKL_STATE_REMOVABLE; + wklShutdownBitSet |= 0x80000000u >> i; + } + } + + if (spurs->flags1 & SF1_32_WORKLOADS) + { + // Update workload status and runnable flag based on the workload state + wklStatus = spurs->wklStatus2[i]; + if (spurs->wklState2[i] == SPURS_WKL_STATE_RUNNABLE) + { + spurs->wklStatus2[i] |= 1 << ctxt->spuNum; + ctxt->wklRunnable2 |= 0x8000 >> i; + } + else + { + spurs->wklStatus2[i] &= ~(1 << ctxt->spuNum); + } + + // If the workload is shutting down and if this is the last SPU from which it is being removed then + // add it to the shutdown bit set + if (spurs->wklState2[i] == SPURS_WKL_STATE_SHUTTING_DOWN) + { + if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus2[i] == 0)) + { + spurs->wklState2[i] = SPURS_WKL_STATE_REMOVABLE; + wklShutdownBitSet |= 0x8000 >> i; + } + } + } + } + + std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); + }); + + if (wklShutdownBitSet) + { + spursSysServiceUpdateShutdownCompletionEvents(spu, ctxt, wklShutdownBitSet); + } +} + +// Update shutdown completion events +void spursSysServiceUpdateShutdownCompletionEvents(SPUThread& spu, SpursKernelContext* ctxt, u32 wklShutdownBitSet) +{ + // Mark the workloads in wklShutdownBitSet as completed and also generate a bit set of the completed + // workloads that have a shutdown completion hook registered + u32 wklNotifyBitSet; + u8 spuPort; + vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() + { + auto spurs = ctxt->spurs.get_ptr_priv(); + + wklNotifyBitSet = 0; + spuPort = spurs->spuPort;; + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + if (wklShutdownBitSet & (0x80000000u >> i)) + { + spurs->wklEvent1[i] |= 0x01; + if (spurs->wklEvent1[i] & 0x02 || spurs->wklEvent1[i] & 0x10) + { + wklNotifyBitSet |= 0x80000000u >> i; + } + } + + if (wklShutdownBitSet & (0x8000 >> i)) + { + spurs->wklEvent2[i] |= 0x01; + if (spurs->wklEvent2[i] & 0x02 || spurs->wklEvent2[i] & 0x10) + { + wklNotifyBitSet |= 0x8000 >> i; + } + } + } + + std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); + }); + + if (wklNotifyBitSet) + { + // TODO: sys_spu_thread_send_event(spuPort, 0, wklNotifyMask); + } +} + +// Update the trace count for this SPU +void spursSysServiceTraceSaveCount(SPUThread& spu, SpursKernelContext* ctxt) +{ + if (ctxt->traceBuffer) + { + auto traceInfo = vm::ptr::make((u32)(ctxt->traceBuffer - (ctxt->spurs->traceStartIndex[ctxt->spuNum] << 4))); + traceInfo->count[ctxt->spuNum] = ctxt->traceMsgCount; + } +} + +// Update trace control +void spursSysServiceTraceUpdate(SPUThread& spu, SpursKernelContext* ctxt, u32 arg2, u32 arg3, u32 forceNotify) +{ + bool notify; + + u8 sysSrvMsgUpdateTrace; + vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() + { + auto spurs = ctxt->spurs.get_ptr_priv(); + auto& trace = spurs->sysSrvTrace.raw(); + + sysSrvMsgUpdateTrace = trace.sysSrvMsgUpdateTrace; + trace.sysSrvMsgUpdateTrace &= ~(1 << ctxt->spuNum); + trace.sysSrvTraceInitialised &= ~(1 << ctxt->spuNum); + trace.sysSrvTraceInitialised |= arg2 << ctxt->spuNum; + + notify = false; + if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) && (spurs->sysSrvTrace.load().sysSrvMsgUpdateTrace == 0) && (spurs->sysSrvTrace.load().sysSrvNotifyUpdateTraceComplete != 0)) + { + trace.sysSrvNotifyUpdateTraceComplete = 0; + notify = true; + } + + if (forceNotify && spurs->sysSrvTrace.load().sysSrvNotifyUpdateTraceComplete != 0) + { + trace.sysSrvNotifyUpdateTraceComplete = 0; + notify = true; + } + + std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); + }); + + // Get trace parameters from CellSpurs and store them in the LS + if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) || (arg3 != 0)) + { + vm::reservation_acquire(vm::base(spu.offset + 0x80), ctxt->spurs.ptr(&CellSpurs::traceBuffer).addr(), 128); + auto spurs = vm::_ptr(spu.offset + 0x80 - OFFSET_32(CellSpurs, traceBuffer)); + + if (ctxt->traceMsgCount != 0xFF || spurs->traceBuffer.addr() == 0) + { + spursSysServiceTraceSaveCount(spu, ctxt); + } + else + { + std::memcpy(vm::base(spu.offset + 0x2C00), vm::base(spurs->traceBuffer.addr() & -0x4), 0x80); + auto traceBuffer = vm::_ptr(spu.offset + 0x2C00); + ctxt->traceMsgCount = traceBuffer->count[ctxt->spuNum]; + } + + ctxt->traceBuffer = spurs->traceBuffer.addr() + (spurs->traceStartIndex[ctxt->spuNum] << 4); + ctxt->traceMaxCount = spurs->traceStartIndex[1] - spurs->traceStartIndex[0]; + if (ctxt->traceBuffer == 0) + { + ctxt->traceMsgCount = 0; + } + } + + if (notify) + { + auto spurs = vm::_ptr(spu.offset + 0x2D80 - OFFSET_32(CellSpurs, wklState1)); + sys_spu_thread_send_event(spu, spurs->spuPort, 2, 0); + } +} + +// Restore state after executing the system workload +void spursSysServiceCleanupAfterSystemWorkload(SPUThread& spu, SpursKernelContext* ctxt) +{ + u8 wklId; + + bool do_return = false; + + vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() + { + auto spurs = ctxt->spurs.get_ptr_priv(); + + if (spurs->sysSrvPreemptWklId[ctxt->spuNum] == 0xFF) + { + do_return = true; + return; + } + + wklId = spurs->sysSrvPreemptWklId[ctxt->spuNum]; + spurs->sysSrvPreemptWklId[ctxt->spuNum] = 0xFF; + + std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); + }); + + if (do_return) return; + + spursSysServiceActivateWorkload(spu, ctxt); + + vm::reservation_op(vm::cast(ctxt->spurs.addr(), HERE), 128, [&]() + { + auto spurs = ctxt->spurs.get_ptr_priv(); + + if (wklId >= CELL_SPURS_MAX_WORKLOAD) + { + spurs->wklCurrentContention[wklId & 0x0F] -= 0x10; + spurs->wklReadyCount1[wklId & 0x0F].raw() -= 1; + } + else + { + spurs->wklCurrentContention[wklId & 0x0F] -= 0x01; + spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].raw() -= 1; + } + + std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); + }); + + // Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace + // uses the current worload id to determine the workload to which the trace belongs + auto wklIdSaved = ctxt->wklCurrentId; + ctxt->wklCurrentId = wklId; + + // Trace - STOP: GUID + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; + pkt.data.stop = SPURS_GUID_SYS_WKL; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + ctxt->wklCurrentId = wklIdSaved; +} + +//---------------------------------------------------------------------------- +// SPURS taskset policy module functions +//---------------------------------------------------------------------------- + +enum SpursTasksetRequest +{ + SPURS_TASKSET_REQUEST_POLL_SIGNAL = -1, + SPURS_TASKSET_REQUEST_DESTROY_TASK = 0, + SPURS_TASKSET_REQUEST_YIELD_TASK = 1, + SPURS_TASKSET_REQUEST_WAIT_SIGNAL = 2, + SPURS_TASKSET_REQUEST_POLL = 3, + SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG = 4, + SPURS_TASKSET_REQUEST_SELECT_TASK = 5, + SPURS_TASKSET_REQUEST_RECV_WKL_FLAG = 6, +}; + +// Taskset PM entry point +bool spursTasksetEntry(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + auto kernelCtxt = vm::_ptr(spu.offset + spu.gpr[3]._u32[3]); + + auto arg = spu.gpr[4]._u64[1]; + auto pollStatus = spu.gpr[5]._u32[3]; + + // Initialise memory and save args + memset(ctxt, 0, sizeof(*ctxt)); + ctxt->taskset.set(arg); + memcpy(ctxt->moduleId, "SPURSTASK MODULE", sizeof(ctxt->moduleId)); + ctxt->kernelMgmtAddr = spu.gpr[3]._u32[3]; + ctxt->syscallAddr = CELL_SPURS_TASKSET_PM_SYSCALL_ADDR; + ctxt->spuNum = kernelCtxt->spuNum; + ctxt->dmaTagId = kernelCtxt->dmaTagId; + ctxt->taskId = 0xFFFFFFFF; + + // Register SPURS takset policy module HLE functions + spu.UnregisterHleFunctions(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, 0x40000/*LS_BOTTOM*/); + spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry); + spu.RegisterHleFunction(ctxt->syscallAddr, spursTasksetSyscallEntry); + + try + { + // Initialise the taskset policy module + spursTasksetInit(spu, pollStatus); + + // Dispatch + spursTasksetDispatch(spu); + } + catch (SpursModuleExit) + { + } + + return false; +} + +// Entry point into the Taskset PM for task syscalls +bool spursTasksetSyscallEntry(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + + try + { + // Save task context + ctxt->savedContextLr = spu.gpr[0]; + ctxt->savedContextSp = spu.gpr[1]; + for (auto i = 0; i < 48; i++) + { + ctxt->savedContextR80ToR127[i] = spu.gpr[80 + i]; + } + + // Handle the syscall + spu.gpr[3]._u32[3] = spursTasksetProcessSyscall(spu, spu.gpr[3]._u32[3], spu.gpr[4]._u32[3]); + + // Resume the previously executing task if the syscall did not cause a context switch + throw EXCEPTION("Broken (TODO)"); + //if (spu.m_is_branch == false) { + // spursTasksetResumeTask(spu); + //} + } + catch (SpursModuleExit) + { + } + + return false; +} + +// Resume a task +void spursTasksetResumeTask(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + + // Restore task context + spu.gpr[0] = ctxt->savedContextLr; + spu.gpr[1] = ctxt->savedContextSp; + for (auto i = 0; i < 48; i++) + { + spu.gpr[80 + i] = ctxt->savedContextR80ToR127[i]; + } + + spu.pc = spu.gpr[0]._u32[3] - 4; +} + +// Start a task +void spursTasksetStartTask(SPUThread& spu, CellSpursTaskArgument& taskArgs) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + auto taskset = vm::_ptr(spu.offset + 0x2700); + + spu.gpr[2].clear(); + spu.gpr[3] = v128::from64r(taskArgs._u64[0], taskArgs._u64[1]); + spu.gpr[4]._u64[1] = taskset->args; + spu.gpr[4]._u64[0] = taskset->spurs.addr(); + for (auto i = 5; i < 128; i++) + { + spu.gpr[i].clear(); + } + + spu.pc = ctxt->savedContextLr.value()._u32[3] - 4; +} + +// Process a request and update the state of the taskset +s32 spursTasksetProcessRequest(SPUThread& spu, s32 request, u32* taskId, u32* isWaiting) +{ + auto kernelCtxt = vm::_ptr(spu.offset + 0x100); + auto ctxt = vm::_ptr(spu.offset + 0x2700); + + s32 rc = CELL_OK; + s32 numNewlyReadyTasks; + vm::reservation_op(vm::cast(ctxt->taskset.addr(), HERE), 128, [&]() + { + auto taskset = ctxt->taskset.get_ptr_priv(); + + // Verify taskset state is valid + be_t _0(v128::from32(0)); + if ((taskset->waiting & taskset->running) != _0 || (taskset->ready & taskset->pending_ready) != _0 || + ((taskset->running | taskset->ready | taskset->pending_ready | taskset->signalled | taskset->waiting) & ~taskset->enabled) != _0) + { + LOG_ERROR(SPU, "Invalid taskset state"); + spursHalt(spu); + } + + // Find the number of tasks that have become ready since the last iteration + auto newlyReadyTasks = (taskset->signalled | taskset->pending_ready) & ~taskset->ready.value(); + numNewlyReadyTasks = 0; + for (auto i = 0; i < 128; i++) + { + if (newlyReadyTasks._bit[i]) + { + numNewlyReadyTasks++; + } + } + + v128 readyButNotRunning; + u8 selectedTaskId; + v128 running = taskset->running.value(); + v128 waiting = taskset->waiting.value(); + v128 enabled = taskset->enabled.value(); + v128 signalled = (taskset->signalled & (taskset->ready | taskset->pending_ready)); + v128 ready = (taskset->signalled | taskset->ready | taskset->pending_ready); + + switch (request) + { + case SPURS_TASKSET_REQUEST_POLL_SIGNAL: + rc = signalled._bit[ctxt->taskId] ? 1 : 0; + signalled._bit[ctxt->taskId] = false; + break; + case SPURS_TASKSET_REQUEST_DESTROY_TASK: + numNewlyReadyTasks--; + running._bit[ctxt->taskId] = false; + enabled._bit[ctxt->taskId] = false; + signalled._bit[ctxt->taskId] = false; + ready._bit[ctxt->taskId] = false; + break; + case SPURS_TASKSET_REQUEST_YIELD_TASK: + running._bit[ctxt->taskId] = false; + waiting._bit[ctxt->taskId] = true; + break; + case SPURS_TASKSET_REQUEST_WAIT_SIGNAL: + if (signalled._bit[ctxt->taskId] == false) + { + numNewlyReadyTasks--; + running._bit[ctxt->taskId] = false; + waiting._bit[ctxt->taskId] = true; + signalled._bit[ctxt->taskId] = false; + ready._bit[ctxt->taskId] = false; + } + break; + case SPURS_TASKSET_REQUEST_POLL: + readyButNotRunning = ready & ~running; + if (taskset->wkl_flag_wait_task < CELL_SPURS_MAX_TASK) + { + readyButNotRunning = readyButNotRunning & ~(v128::fromBit(taskset->wkl_flag_wait_task)); + } + + rc = readyButNotRunning != _0 ? 1 : 0; + break; + case SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG: + if (taskset->wkl_flag_wait_task == 0x81) + { + // A workload flag is already pending so consume it + taskset->wkl_flag_wait_task = 0x80; + rc = 0; + } + else if (taskset->wkl_flag_wait_task == 0x80) + { + // No tasks are waiting for the workload flag. Mark this task as waiting for the workload flag. + taskset->wkl_flag_wait_task = ctxt->taskId; + running._bit[ctxt->taskId] = false; + waiting._bit[ctxt->taskId] = true; + rc = 1; + numNewlyReadyTasks--; + } + else + { + // Another task is already waiting for the workload signal + rc = CELL_SPURS_TASK_ERROR_BUSY; + } + break; + case SPURS_TASKSET_REQUEST_SELECT_TASK: + readyButNotRunning = ready & ~running; + if (taskset->wkl_flag_wait_task < CELL_SPURS_MAX_TASK) + { + readyButNotRunning = readyButNotRunning & ~(v128::fromBit(taskset->wkl_flag_wait_task)); + } + + // Select a task from the readyButNotRunning set to run. Start from the task after the last scheduled task to ensure fairness. + for (selectedTaskId = taskset->last_scheduled_task + 1; selectedTaskId < 128; selectedTaskId++) + { + if (readyButNotRunning._bit[selectedTaskId]) + { + break; + } + } + + if (selectedTaskId == 128) + { + for (selectedTaskId = 0; selectedTaskId < taskset->last_scheduled_task + 1; selectedTaskId++) + { + if (readyButNotRunning._bit[selectedTaskId]) + { + break; + } + } + + if (selectedTaskId == taskset->last_scheduled_task + 1) + { + selectedTaskId = CELL_SPURS_MAX_TASK; + } + } + + *taskId = selectedTaskId; + *isWaiting = waiting._bit[selectedTaskId < CELL_SPURS_MAX_TASK ? selectedTaskId : 0] ? 1 : 0; + if (selectedTaskId != CELL_SPURS_MAX_TASK) + { + taskset->last_scheduled_task = selectedTaskId; + running._bit[selectedTaskId] = true; + waiting._bit[selectedTaskId] = false; + } + break; + case SPURS_TASKSET_REQUEST_RECV_WKL_FLAG: + if (taskset->wkl_flag_wait_task < CELL_SPURS_MAX_TASK) + { + // There is a task waiting for the workload flag + taskset->wkl_flag_wait_task = 0x80; + rc = 1; + numNewlyReadyTasks++; + } + else + { + // No tasks are waiting for the workload flag + taskset->wkl_flag_wait_task = 0x81; + rc = 0; + } + break; + default: + LOG_ERROR(SPU, "Unknown taskset request"); + spursHalt(spu); + } + + taskset->pending_ready = _0; + taskset->running = running; + taskset->waiting = waiting; + taskset->enabled = enabled; + taskset->signalled = signalled; + taskset->ready = ready; + + std::memcpy(vm::base(spu.offset + 0x2700), taskset, 128); + }); + + // Increment the ready count of the workload by the number of tasks that have become ready + vm::reservation_op(vm::cast(kernelCtxt->spurs.addr(), HERE), 128, [&]() + { + auto spurs = kernelCtxt->spurs.get_ptr_priv(); + + s32 readyCount = kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[kernelCtxt->wklCurrentId].load() : spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].load(); + readyCount += numNewlyReadyTasks; + readyCount = readyCount < 0 ? 0 : readyCount > 0xFF ? 0xFF : readyCount; + + if (kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD) + { + spurs->wklReadyCount1[kernelCtxt->wklCurrentId] = readyCount; + } + else + { + spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F] = readyCount; + } + + std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); + }); + + return rc; +} + +// Process pollStatus received from the SPURS kernel +void spursTasksetProcessPollStatus(SPUThread& spu, u32 pollStatus) +{ + if (pollStatus & CELL_SPURS_MODULE_POLL_STATUS_FLAG) + { + spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_RECV_WKL_FLAG, nullptr, nullptr); + } +} + +// Check execution rights +bool spursTasksetPollStatus(SPUThread& spu) +{ + u32 pollStatus; + + if (cellSpursModulePollStatus(spu, &pollStatus)) + { + return true; + } + + spursTasksetProcessPollStatus(spu, pollStatus); + return false; +} + +// Exit the Taskset PM +void spursTasksetExit(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + + // Trace - STOP + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = 0x54; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_STOP + pkt.data.stop = SPURS_GUID_TASKSET_PM; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + // Not sure why this check exists. Perhaps to check for memory corruption. + if (memcmp(ctxt->moduleId, "SPURSTASK MODULE", 16) != 0) + { + LOG_ERROR(SPU, "spursTasksetExit(): memory corruption"); + spursHalt(spu); + } + + cellSpursModuleExit(spu); +} + +// Invoked when a task exits +void spursTasksetOnTaskExit(SPUThread& spu, u64 addr, u32 taskId, s32 exitCode, u64 args) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + + std::memcpy(vm::base(spu.offset + 0x10000), vm::base(addr & -0x80), (addr & 0x7F) << 11); + + spu.gpr[3]._u64[1] = ctxt->taskset.addr(); + spu.gpr[4]._u32[3] = taskId; + spu.gpr[5]._u32[3] = exitCode; + spu.gpr[6]._u64[1] = args; + spu.fast_call(0x10000); +} + +// Save the context of a task +s32 spursTasketSaveTaskContext(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + auto taskInfo = vm::_ptr(spu.offset + 0x2780); + + //spursDmaWaitForCompletion(spu, 0xFFFFFFFF); + + if (taskInfo->context_save_storage_and_alloc_ls_blocks == 0) + { + return CELL_SPURS_TASK_ERROR_STAT; + } + + u32 allocLsBlocks = taskInfo->context_save_storage_and_alloc_ls_blocks & 0x7F; + u32 lsBlocks = 0; + v128 ls_pattern = v128::from64r(taskInfo->ls_pattern._u64[0], taskInfo->ls_pattern._u64[1]); + for (auto i = 0; i < 128; i++) + { + if (ls_pattern._bit[i]) + { + lsBlocks++; + } + } + + if (lsBlocks > allocLsBlocks) + { + return CELL_SPURS_TASK_ERROR_STAT; + } + + // Make sure the stack is area is specified in the ls pattern + for (auto i = (ctxt->savedContextSp.value()._u32[3]) >> 11; i < 128; i++) + { + if (ls_pattern._bit[i] == false) + { + return CELL_SPURS_TASK_ERROR_STAT; + } + } + + // Get the processor context + v128 r; + spu.fpscr.Read(r); + ctxt->savedContextFpscr = r; + ctxt->savedSpuWriteEventMask = spu.get_ch_value(SPU_RdEventMask); + ctxt->savedWriteTagGroupQueryMask = spu.get_ch_value(MFC_RdTagMask); + + // Store the processor context + const u32 contextSaveStorage = vm::cast(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80, HERE); + std::memcpy(vm::base(contextSaveStorage), vm::base(spu.offset + 0x2C80), 0x380); + + // Save LS context + for (auto i = 6; i < 128; i++) + { + if (ls_pattern._bit[i]) + { + // TODO: Combine DMA requests for consecutive blocks into a single request + std::memcpy(vm::base(contextSaveStorage + 0x400 + ((i - 6) << 11)), vm::base(spu.offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), 0x800); + } + } + + //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + return CELL_OK; +} + +// Taskset dispatcher +void spursTasksetDispatch(SPUThread& spu) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + auto taskset = vm::_ptr(spu.offset + 0x2700); + + u32 taskId; + u32 isWaiting; + spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_SELECT_TASK, &taskId, &isWaiting); + if (taskId >= CELL_SPURS_MAX_TASK) + { + spursTasksetExit(spu); + return; + } + + ctxt->taskId = taskId; + + // DMA in the task info for the selected task + std::memcpy(vm::base(spu.offset + 0x2780), &ctxt->taskset->task_info[taskId], sizeof(CellSpursTaskset::TaskInfo)); + auto taskInfo = vm::_ptr(spu.offset + 0x2780); + auto elfAddr = taskInfo->elf.addr().value(); + taskInfo->elf.set(taskInfo->elf.addr() & 0xFFFFFFFFFFFFFFF8); + + // Trace - Task: Incident=dispatch + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_TASK; + pkt.data.task.incident = CELL_SPURS_TRACE_TASK_DISPATCH; + pkt.data.task.taskId = taskId; + cellSpursModulePutTrace(&pkt, CELL_SPURS_KERNEL_DMA_TAG_ID); + + if (isWaiting == 0) + { + // If we reach here it means that the task is being started and not being resumed + std::memset(vm::base(spu.offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); + ctxt->guidAddr = CELL_SPURS_TASK_TOP; + + u32 entryPoint; + u32 lowestLoadAddr; + if (spursTasksetLoadElf(spu, &entryPoint, &lowestLoadAddr, taskInfo->elf.addr(), false) != CELL_OK) + { + LOG_ERROR(SPU, "spursTaskLoadElf() failed"); + spursHalt(spu); + } + + //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + + ctxt->savedContextLr = v128::from32r(entryPoint); + ctxt->guidAddr = lowestLoadAddr; + ctxt->tasksetMgmtAddr = 0x2700; + ctxt->x2FC0 = 0; + ctxt->taskExitCode = isWaiting; + ctxt->x2FD4 = elfAddr & 5; // TODO: Figure this out + + if ((elfAddr & 5) == 1) + { + std::memcpy(vm::base(spu.offset + 0x2FC0), &((CellSpursTaskset2*)(ctxt->taskset.get_ptr()))->task_exit_code[taskId], 0x10); + } + + // Trace - GUID + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_GUID; + pkt.data.guid = 0; // TODO: Put GUID of taskId here + cellSpursModulePutTrace(&pkt, 0x1F); + + if (elfAddr & 2) + { + // TODO: Figure this out + spu.status |= SPU_STATUS_STOPPED_BY_STOP; + throw cpu_state::stop; + } + + spursTasksetStartTask(spu, taskInfo->args); + } + else + { + if (taskset->enable_clear_ls) + { + std::memset(vm::base(spu.offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); + } + + // If the entire LS is saved then there is no need to load the ELF as it will be be saved in the context save area as well + v128 ls_pattern = v128::from64r(taskInfo->ls_pattern._u64[0], taskInfo->ls_pattern._u64[1]); + if (ls_pattern != v128::from64r(0x03FFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull)) + { + // Load the ELF + u32 entryPoint; + if (spursTasksetLoadElf(spu, &entryPoint, nullptr, taskInfo->elf.addr(), true) != CELL_OK) + { + LOG_ERROR(SPU, "spursTasksetLoadElf() failed"); + spursHalt(spu); + } + } + + // Load saved context from main memory to LS + const u32 contextSaveStorage = vm::cast(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80, HERE); + std::memcpy(vm::base(spu.offset + 0x2C80), vm::base(contextSaveStorage), 0x380); + for (auto i = 6; i < 128; i++) + { + if (ls_pattern._bit[i]) + { + // TODO: Combine DMA requests for consecutive blocks into a single request + std::memcpy(vm::base(spu.offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), vm::base(contextSaveStorage + 0x400 + ((i - 6) << 11)), 0x800); + } + } + + //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + + // Restore saved registers + spu.fpscr.Write(ctxt->savedContextFpscr.value()); + spu.set_ch_value(MFC_WrTagMask, ctxt->savedWriteTagGroupQueryMask); + spu.set_ch_value(SPU_WrEventMask, ctxt->savedSpuWriteEventMask); + + // Trace - GUID + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_GUID; + pkt.data.guid = 0; // TODO: Put GUID of taskId here + cellSpursModulePutTrace(&pkt, 0x1F); + + if (elfAddr & 2) + { + // TODO: Figure this out + spu.status |= SPU_STATUS_STOPPED_BY_STOP; + throw cpu_state::stop; + } + + spu.gpr[3].clear(); + spursTasksetResumeTask(spu); + } +} + +// Process a syscall request +s32 spursTasksetProcessSyscall(SPUThread& spu, u32 syscallNum, u32 args) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + auto taskset = vm::_ptr(spu.offset + 0x2700); + + // If the 0x10 bit is set in syscallNum then its the 2nd version of the + // syscall (e.g. cellSpursYield2 instead of cellSpursYield) and so don't wait + // for DMA completion + if ((syscallNum & 0x10) == 0) + { + //spursDmaWaitForCompletion(spu, 0xFFFFFFFF); + } + + s32 rc = 0; + u32 incident = 0; + switch (syscallNum & 0x0F) + { + case CELL_SPURS_TASK_SYSCALL_EXIT: + if (ctxt->x2FD4 == 4 || (ctxt->x2FC0 & 0xFFFFFFFF) != 0) + { // TODO: Figure this out + if (ctxt->x2FD4 != 4) + { + spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_DESTROY_TASK, nullptr, nullptr); + } + + const u64 addr = ctxt->x2FD4 == 4 ? taskset->x78 : ctxt->x2FC0; + const u64 args = ctxt->x2FD4 == 4 ? 0 : ctxt->x2FC8.value(); + spursTasksetOnTaskExit(spu, addr, ctxt->taskId, ctxt->taskExitCode, args); + } + + incident = CELL_SPURS_TRACE_TASK_EXIT; + break; + case CELL_SPURS_TASK_SYSCALL_YIELD: + if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_POLL, nullptr, nullptr)) + { + // If we reach here then it means that either another task can be scheduled or another workload can be scheduled + // Save the context of the current task + rc = spursTasketSaveTaskContext(spu); + if (rc == CELL_OK) + { + spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_YIELD_TASK, nullptr, nullptr); + incident = CELL_SPURS_TRACE_TASK_YIELD; + } + } + break; + case CELL_SPURS_TASK_SYSCALL_WAIT_SIGNAL: + if (spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_POLL_SIGNAL, nullptr, nullptr) == 0) + { + rc = spursTasketSaveTaskContext(spu); + if (rc == CELL_OK) + { + if (spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_WAIT_SIGNAL, nullptr, nullptr) == 0) + { + incident = CELL_SPURS_TRACE_TASK_WAIT; + } + } + } + break; + case CELL_SPURS_TASK_SYSCALL_POLL: + rc = spursTasksetPollStatus(spu) ? CELL_SPURS_TASK_POLL_FOUND_WORKLOAD : 0; + rc |= spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_POLL, nullptr, nullptr) ? CELL_SPURS_TASK_POLL_FOUND_TASK : 0; + break; + case CELL_SPURS_TASK_SYSCALL_RECV_WKL_FLAG: + if (args == 0) + { // TODO: Figure this out + LOG_ERROR(SPU, "args == 0"); + //spursHalt(spu); + } + + if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG, nullptr, nullptr) != 1) + { + rc = spursTasketSaveTaskContext(spu); + if (rc == CELL_OK) + { + incident = CELL_SPURS_TRACE_TASK_WAIT; + } + } + break; + default: + rc = CELL_SPURS_TASK_ERROR_NOSYS; + break; + } + + if (incident) + { + // Trace - TASK + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_TASK; + pkt.data.task.incident = incident; + pkt.data.task.taskId = ctxt->taskId; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + // Clear the GUID of the task + std::memset(vm::base(spu.offset + ctxt->guidAddr), 0, 0x10); + + if (spursTasksetPollStatus(spu)) + { + spursTasksetExit(spu); + } + else + { + spursTasksetDispatch(spu); + } + } + + return rc; +} + +// Initialise the Taskset PM +void spursTasksetInit(SPUThread& spu, u32 pollStatus) +{ + auto ctxt = vm::_ptr(spu.offset + 0x2700); + auto kernelCtxt = vm::_ptr(spu.offset + 0x100); + + kernelCtxt->moduleId[0] = 'T'; + kernelCtxt->moduleId[1] = 'K'; + + // Trace - START: Module='TKST' + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = 0x52; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_START + memcpy(pkt.data.start.module, "TKST", 4); + pkt.data.start.level = 2; + pkt.data.start.ls = 0xA00 >> 2; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + spursTasksetProcessPollStatus(spu, pollStatus); +} + +// Load an ELF +s32 spursTasksetLoadElf(SPUThread& spu, u32* entryPoint, u32* lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments) +{ + if (elfAddr == 0 || (elfAddr & 0x0F) != 0) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + const spu_exec_loader loader(fs::file(vm::base(vm::cast(elfAddr, HERE)), u32(0 - elfAddr))); + + if (loader != elf_error::ok) + { + return CELL_SPURS_TASK_ERROR_NOEXEC; + } + + u32 _lowestLoadAddr = CELL_SPURS_TASK_BOTTOM; + for (const auto& prog : loader.progs) + { + if (prog.p_paddr >= CELL_SPURS_TASK_BOTTOM) + { + break; + } + + if (prog.p_type == 1 /* PT_LOAD */) + { + if (skipWriteableSegments == false || (prog.p_flags & 2 /*PF_W*/ ) == 0) + { + if (prog.p_vaddr < CELL_SPURS_TASK_TOP || prog.p_vaddr + prog.p_memsz > CELL_SPURS_TASK_BOTTOM) + { + return CELL_SPURS_TASK_ERROR_FAULT; + } + + _lowestLoadAddr > prog.p_vaddr ? _lowestLoadAddr = prog.p_vaddr : _lowestLoadAddr; + } + } + } + + for (const auto& prog : loader.progs) + { + if (prog.p_paddr >= CELL_SPURS_TASK_BOTTOM) // ??? + { + break; + } + + if (prog.p_type == 1) + { + if (skipWriteableSegments == false || (prog.p_flags & 2) == 0) + { + std::memcpy(vm::base(spu.offset + prog.p_vaddr), prog.bin.data(), prog.p_filesz); + } + } + } + + *entryPoint = loader.header.e_entry; + if (lowestLoadAddr) *lowestLoadAddr = _lowestLoadAddr; + + return CELL_OK; +} diff --git a/rpcs3/Emu/SysCalls/Modules/cellSsl.cpp b/rpcs3/Emu/Cell/Modules/cellSsl.cpp similarity index 93% rename from rpcs3/Emu/SysCalls/Modules/cellSsl.cpp rename to rpcs3/Emu/Cell/Modules/cellSsl.cpp index eaac5d7760..ab14c7fedd 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSsl.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSsl.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellSsl; +LOG_CHANNEL(cellSsl); s32 cellSslInit() { @@ -88,7 +87,7 @@ s32 cellSslCertGetMd5Fingerprint() return CELL_OK; } -Module<> cellSsl("cellSsl", []() +DECLARE(ppu_module_manager::cellSsl)("cellSsl", []() { REG_FUNC(cellSsl, cellSslInit); REG_FUNC(cellSsl, cellSslEnd); diff --git a/rpcs3/Emu/SysCalls/Modules/cellStorage.cpp b/rpcs3/Emu/Cell/Modules/cellStorage.cpp similarity index 79% rename from rpcs3/Emu/SysCalls/Modules/cellStorage.cpp rename to rpcs3/Emu/Cell/Modules/cellStorage.cpp index 07ce05e6a5..894f33cf4a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellStorage.cpp +++ b/rpcs3/Emu/Cell/Modules/cellStorage.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellSysutil; +extern _log::channel cellSysutil; s32 cellStorageDataImportMove() { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSubdisplay.cpp b/rpcs3/Emu/Cell/Modules/cellSubdisplay.cpp similarity index 92% rename from rpcs3/Emu/SysCalls/Modules/cellSubdisplay.cpp rename to rpcs3/Emu/Cell/Modules/cellSubdisplay.cpp index 230adbc86f..6f971a4923 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSubdisplay.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSubdisplay.cpp @@ -1,10 +1,9 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellSubdisplay.h" -extern Module<> cellSubdisplay; +LOG_CHANNEL(cellSubdisplay); s32 cellSubDisplayInit() { @@ -74,7 +73,7 @@ s32 cellSubDisplayGetPeerList() return CELL_OK; } -Module<> cellSubdisplay("cellSubdisplay", []() +DECLARE(ppu_module_manager::cellSubdisplay)("cellSubdisplay", []() { REG_FUNC(cellSubdisplay, cellSubDisplayInit); REG_FUNC(cellSubdisplay, cellSubDisplayEnd); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSubdisplay.h b/rpcs3/Emu/Cell/Modules/cellSubdisplay.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellSubdisplay.h rename to rpcs3/Emu/Cell/Modules/cellSubdisplay.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/Cell/Modules/cellSync.cpp similarity index 79% rename from rpcs3/Emu/SysCalls/Modules/cellSync.cpp rename to rpcs3/Emu/Cell/Modules/cellSync.cpp index c01f8d4ddf..83ada37380 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSync.cpp @@ -1,17 +1,32 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/SysCalls/lv2/sys_sync.h" -#include "Emu/SysCalls/lv2/sys_event.h" -#include "Emu/SysCalls/lv2/sys_process.h" -#include "Emu/Event.h" +#include "Emu/Cell/lv2/sys_event.h" +#include "Emu/Cell/lv2/sys_process.h" #include "cellSync.h" -extern Module<> cellSync; +LOG_CHANNEL(cellSync); -s32 cellSyncMutexInitialize(vm::ptr mutex) +namespace _sync +{ + static inline be_t mutex_acquire(mutex& ctrl) + { + return ctrl.acq++; + } + + static inline bool mutex_try_lock(mutex& ctrl) + { + return ctrl.acq++ == ctrl.rel; + } + + static inline void mutex_unlock(mutex& ctrl) + { + ctrl.rel++; + } +} + +ppu_error_code cellSyncMutexInitialize(vm::ptr mutex) { cellSync.trace("cellSyncMutexInitialize(mutex=*0x%x)", mutex); @@ -30,7 +45,7 @@ s32 cellSyncMutexInitialize(vm::ptr mutex) return CELL_OK; } -s32 cellSyncMutexLock(PPUThread& ppu, vm::ptr mutex) +ppu_error_code cellSyncMutexLock(PPUThread& ppu, vm::ptr mutex) { cellSync.trace("cellSyncMutexLock(mutex=*0x%x)", mutex); @@ -45,7 +60,7 @@ s32 cellSyncMutexLock(PPUThread& ppu, vm::ptr mutex) } // increase acq value and remember its old value - const auto order = mutex->ctrl.atomic_op(_sync::mutex::acquire); + const auto order = mutex->ctrl.atomic_op(_sync::mutex_acquire); // wait until rel value is equal to old acq value vm::wait_op(ppu, mutex.addr(), 4, WRAP_EXPR(mutex->ctrl.load().rel == order)); @@ -55,7 +70,7 @@ s32 cellSyncMutexLock(PPUThread& ppu, vm::ptr mutex) return CELL_OK; } -s32 cellSyncMutexTryLock(vm::ptr mutex) +ppu_error_code cellSyncMutexTryLock(vm::ptr mutex) { cellSync.trace("cellSyncMutexTryLock(mutex=*0x%x)", mutex); @@ -69,15 +84,15 @@ s32 cellSyncMutexTryLock(vm::ptr mutex) return CELL_SYNC_ERROR_ALIGN; } - if (!mutex->ctrl.atomic_op(_sync::mutex::try_lock)) + if (!mutex->ctrl.atomic_op(_sync::mutex_try_lock)) { - return CELL_SYNC_ERROR_BUSY; + return NOT_AN_ERROR(CELL_SYNC_ERROR_BUSY); } return CELL_OK; } -s32 cellSyncMutexUnlock(vm::ptr mutex) +ppu_error_code cellSyncMutexUnlock(vm::ptr mutex) { cellSync.trace("cellSyncMutexUnlock(mutex=*0x%x)", mutex); @@ -91,14 +106,14 @@ s32 cellSyncMutexUnlock(vm::ptr mutex) return CELL_SYNC_ERROR_ALIGN; } - mutex->ctrl.atomic_op(_sync::mutex::unlock); + mutex->ctrl.atomic_op(_sync::mutex_unlock); vm::notify_at(mutex); return CELL_OK; } -s32 cellSyncBarrierInitialize(vm::ptr barrier, u16 total_count) +ppu_error_code cellSyncBarrierInitialize(vm::ptr barrier, u16 total_count) { cellSync.trace("cellSyncBarrierInitialize(barrier=*0x%x, total_count=%d)", barrier, total_count); @@ -123,7 +138,7 @@ s32 cellSyncBarrierInitialize(vm::ptr barrier, u16 total_count) return CELL_OK; } -s32 cellSyncBarrierNotify(PPUThread& ppu, vm::ptr barrier) +ppu_error_code cellSyncBarrierNotify(PPUThread& ppu, vm::ptr barrier) { cellSync.trace("cellSyncBarrierNotify(barrier=*0x%x)", barrier); @@ -144,7 +159,7 @@ s32 cellSyncBarrierNotify(PPUThread& ppu, vm::ptr barrier) return CELL_OK; } -s32 cellSyncBarrierTryNotify(vm::ptr barrier) +ppu_error_code cellSyncBarrierTryNotify(vm::ptr barrier) { cellSync.trace("cellSyncBarrierTryNotify(barrier=*0x%x)", barrier); @@ -162,7 +177,7 @@ s32 cellSyncBarrierTryNotify(vm::ptr barrier) if (!barrier->ctrl.atomic_op(_sync::barrier::try_notify)) { - return CELL_SYNC_ERROR_BUSY; + return NOT_AN_ERROR(CELL_SYNC_ERROR_BUSY); } vm::notify_at(barrier); @@ -170,7 +185,7 @@ s32 cellSyncBarrierTryNotify(vm::ptr barrier) return CELL_OK; } -s32 cellSyncBarrierWait(PPUThread& ppu, vm::ptr barrier) +ppu_error_code cellSyncBarrierWait(PPUThread& ppu, vm::ptr barrier) { cellSync.trace("cellSyncBarrierWait(barrier=*0x%x)", barrier); @@ -193,7 +208,7 @@ s32 cellSyncBarrierWait(PPUThread& ppu, vm::ptr barrier) return CELL_OK; } -s32 cellSyncBarrierTryWait(vm::ptr barrier) +ppu_error_code cellSyncBarrierTryWait(vm::ptr barrier) { cellSync.trace("cellSyncBarrierTryWait(barrier=*0x%x)", barrier); @@ -211,7 +226,7 @@ s32 cellSyncBarrierTryWait(vm::ptr barrier) if (!barrier->ctrl.atomic_op(_sync::barrier::try_wait)) { - return CELL_SYNC_ERROR_BUSY; + return NOT_AN_ERROR(CELL_SYNC_ERROR_BUSY); } vm::notify_at(barrier); @@ -219,7 +234,7 @@ s32 cellSyncBarrierTryWait(vm::ptr barrier) return CELL_OK; } -s32 cellSyncRwmInitialize(vm::ptr rwm, vm::ptr buffer, u32 buffer_size) +ppu_error_code cellSyncRwmInitialize(vm::ptr rwm, vm::ptr buffer, u32 buffer_size) { cellSync.trace("cellSyncRwmInitialize(rwm=*0x%x, buffer=*0x%x, buffer_size=0x%x)", rwm, buffer, buffer_size); @@ -248,7 +263,7 @@ s32 cellSyncRwmInitialize(vm::ptr rwm, vm::ptr buffer, u32 bu return CELL_OK; } -s32 cellSyncRwmRead(PPUThread& ppu, vm::ptr rwm, vm::ptr buffer) +ppu_error_code cellSyncRwmRead(PPUThread& ppu, vm::ptr rwm, vm::ptr buffer) { cellSync.trace("cellSyncRwmRead(rwm=*0x%x, buffer=*0x%x)", rwm, buffer); @@ -279,7 +294,7 @@ s32 cellSyncRwmRead(PPUThread& ppu, vm::ptr rwm, vm::ptr buff return CELL_OK; } -s32 cellSyncRwmTryRead(vm::ptr rwm, vm::ptr buffer) +ppu_error_code cellSyncRwmTryRead(vm::ptr rwm, vm::ptr buffer) { cellSync.trace("cellSyncRwmTryRead(rwm=*0x%x, buffer=*0x%x)", rwm, buffer); @@ -296,7 +311,7 @@ s32 cellSyncRwmTryRead(vm::ptr rwm, vm::ptr buffer) // increase `readers` if `writers` is zero if (!rwm->ctrl.atomic_op(_sync::rwlock::try_read_begin)) { - return CELL_SYNC_ERROR_BUSY; + return NOT_AN_ERROR(CELL_SYNC_ERROR_BUSY); } // copy data to buffer @@ -313,7 +328,7 @@ s32 cellSyncRwmTryRead(vm::ptr rwm, vm::ptr buffer) return CELL_OK; } -s32 cellSyncRwmWrite(PPUThread& ppu, vm::ptr rwm, vm::cptr buffer) +ppu_error_code cellSyncRwmWrite(PPUThread& ppu, vm::ptr rwm, vm::cptr buffer) { cellSync.trace("cellSyncRwmWrite(rwm=*0x%x, buffer=*0x%x)", rwm, buffer); @@ -344,7 +359,7 @@ s32 cellSyncRwmWrite(PPUThread& ppu, vm::ptr rwm, vm::cptr bu return CELL_OK; } -s32 cellSyncRwmTryWrite(vm::ptr rwm, vm::cptr buffer) +ppu_error_code cellSyncRwmTryWrite(vm::ptr rwm, vm::cptr buffer) { cellSync.trace("cellSyncRwmTryWrite(rwm=*0x%x, buffer=*0x%x)", rwm, buffer); @@ -361,7 +376,7 @@ s32 cellSyncRwmTryWrite(vm::ptr rwm, vm::cptr buffer) // set `writers` to 1 if `readers` and `writers` are zero if (!rwm->ctrl.compare_and_swap_test({ 0, 0 }, { 0, 1 })) { - return CELL_SYNC_ERROR_BUSY; + return NOT_AN_ERROR(CELL_SYNC_ERROR_BUSY); } // copy data from buffer @@ -375,7 +390,7 @@ s32 cellSyncRwmTryWrite(vm::ptr rwm, vm::cptr buffer) return CELL_OK; } -s32 cellSyncQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth) +ppu_error_code cellSyncQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth) { cellSync.trace("cellSyncQueueInitialize(queue=*0x%x, buffer=*0x%x, size=0x%x, depth=0x%x)", queue, buffer, size, depth); @@ -410,7 +425,7 @@ s32 cellSyncQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 return CELL_OK; } -s32 cellSyncQueuePush(PPUThread& ppu, vm::ptr queue, vm::cptr buffer) +ppu_error_code cellSyncQueuePush(PPUThread& ppu, vm::ptr queue, vm::cptr buffer) { cellSync.trace("cellSyncQueuePush(queue=*0x%x, buffer=*0x%x)", queue, buffer); @@ -428,20 +443,20 @@ s32 cellSyncQueuePush(PPUThread& ppu, vm::ptr queue, vm::cptrctrl.atomic_op(_sync::queue::try_push_begin, depth, position))); + vm::wait_op(ppu, queue.addr(), 8, WRAP_EXPR(queue->ctrl.atomic_op(_sync::queue::try_push_begin, depth, &position))); // copy data from the buffer at the position std::memcpy(&queue->buffer[position * queue->size], buffer.get_ptr(), queue->size); // ...push_end - queue->ctrl._and_not({ 0, 0xff000000 }); + queue->ctrl.atomic_op([](_sync::queue& ctrl) { ctrl._push = 0; }); vm::notify_at(queue.ptr(&CellSyncQueue::ctrl)); return CELL_OK; } -s32 cellSyncQueueTryPush(vm::ptr queue, vm::cptr buffer) +ppu_error_code cellSyncQueueTryPush(vm::ptr queue, vm::cptr buffer) { cellSync.trace("cellSyncQueueTryPush(queue=*0x%x, buffer=*0x%x)", queue, buffer); @@ -459,23 +474,23 @@ s32 cellSyncQueueTryPush(vm::ptr queue, vm::cptr buffer) u32 position; - if (!queue->ctrl.atomic_op(_sync::queue::try_push_begin, depth, position)) + if (!queue->ctrl.atomic_op(_sync::queue::try_push_begin, depth, &position)) { - return CELL_SYNC_ERROR_BUSY; + return NOT_AN_ERROR(CELL_SYNC_ERROR_BUSY); } // copy data from the buffer at the position std::memcpy(&queue->buffer[position * queue->size], buffer.get_ptr(), queue->size); // ...push_end - queue->ctrl._and_not({ 0, 0xff000000 }); + queue->ctrl.atomic_op([](_sync::queue& ctrl) { ctrl._push = 0; }); vm::notify_at(queue.ptr(&CellSyncQueue::ctrl)); return CELL_OK; } -s32 cellSyncQueuePop(PPUThread& ppu, vm::ptr queue, vm::ptr buffer) +ppu_error_code cellSyncQueuePop(PPUThread& ppu, vm::ptr queue, vm::ptr buffer) { cellSync.trace("cellSyncQueuePop(queue=*0x%x, buffer=*0x%x)", queue, buffer); @@ -493,20 +508,20 @@ s32 cellSyncQueuePop(PPUThread& ppu, vm::ptr queue, vm::ptr u32 position; - vm::wait_op(ppu, queue.addr(), 8, WRAP_EXPR(queue->ctrl.atomic_op(_sync::queue::try_pop_begin, depth, position))); + vm::wait_op(ppu, queue.addr(), 8, WRAP_EXPR(queue->ctrl.atomic_op(_sync::queue::try_pop_begin, depth, &position))); // copy data at the position to the buffer std::memcpy(buffer.get_ptr(), &queue->buffer[position % depth * queue->size], queue->size); // ...pop_end - queue->ctrl._and_not({ 0xff000000, 0 }); + queue->ctrl.atomic_op([](_sync::queue& ctrl) { ctrl._pop = 0; }); vm::notify_at(queue.ptr(&CellSyncQueue::ctrl)); return CELL_OK; } -s32 cellSyncQueueTryPop(vm::ptr queue, vm::ptr buffer) +ppu_error_code cellSyncQueueTryPop(vm::ptr queue, vm::ptr buffer) { cellSync.trace("cellSyncQueueTryPop(queue=*0x%x, buffer=*0x%x)", queue, buffer); @@ -524,23 +539,23 @@ s32 cellSyncQueueTryPop(vm::ptr queue, vm::ptr buffer) u32 position; - if (!queue->ctrl.atomic_op(_sync::queue::try_pop_begin, depth, position)) + if (!queue->ctrl.atomic_op(_sync::queue::try_pop_begin, depth, &position)) { - return CELL_SYNC_ERROR_BUSY; + return NOT_AN_ERROR(CELL_SYNC_ERROR_BUSY); } // copy data at the position to the buffer std::memcpy(buffer.get_ptr(), &queue->buffer[position % depth * queue->size], queue->size); // ...pop_end - queue->ctrl._and_not({ 0xff000000, 0 }); + queue->ctrl.atomic_op([](_sync::queue& ctrl) { ctrl._pop = 0; }); vm::notify_at(queue.ptr(&CellSyncQueue::ctrl)); return CELL_OK; } -s32 cellSyncQueuePeek(PPUThread& ppu, vm::ptr queue, vm::ptr buffer) +ppu_error_code cellSyncQueuePeek(PPUThread& ppu, vm::ptr queue, vm::ptr buffer) { cellSync.trace("cellSyncQueuePeek(queue=*0x%x, buffer=*0x%x)", queue, buffer); @@ -558,20 +573,20 @@ s32 cellSyncQueuePeek(PPUThread& ppu, vm::ptr queue, vm::ptrctrl.atomic_op(_sync::queue::try_peek_begin, depth, position))); + vm::wait_op(ppu, queue.addr(), 8, WRAP_EXPR(queue->ctrl.atomic_op(_sync::queue::try_peek_begin, depth, &position))); // copy data at the position to the buffer std::memcpy(buffer.get_ptr(), &queue->buffer[position % depth * queue->size], queue->size); // ...peek_end - queue->ctrl._and_not({ 0xff000000, 0 }); + queue->ctrl.atomic_op([](_sync::queue& ctrl) { ctrl._pop = 0; }); vm::notify_at(queue.ptr(&CellSyncQueue::ctrl)); return CELL_OK; } -s32 cellSyncQueueTryPeek(vm::ptr queue, vm::ptr buffer) +ppu_error_code cellSyncQueueTryPeek(vm::ptr queue, vm::ptr buffer) { cellSync.trace("cellSyncQueueTryPeek(queue=*0x%x, buffer=*0x%x)", queue, buffer); @@ -589,23 +604,23 @@ s32 cellSyncQueueTryPeek(vm::ptr queue, vm::ptr buffer) u32 position; - if (!queue->ctrl.atomic_op(_sync::queue::try_peek_begin, depth, position)) + if (!queue->ctrl.atomic_op(_sync::queue::try_peek_begin, depth, &position)) { - return CELL_SYNC_ERROR_BUSY; + return NOT_AN_ERROR(CELL_SYNC_ERROR_BUSY); } // copy data at the position to the buffer std::memcpy(buffer.get_ptr(), &queue->buffer[position % depth * queue->size], queue->size); // ...peek_end - queue->ctrl._and_not({ 0xff000000, 0 }); + queue->ctrl.atomic_op([](_sync::queue& ctrl) { ctrl._pop = 0; }); vm::notify_at(queue.ptr(&CellSyncQueue::ctrl)); return CELL_OK; } -s32 cellSyncQueueSize(vm::ptr queue) +ppu_error_code cellSyncQueueSize(vm::ptr queue) { cellSync.trace("cellSyncQueueSize(queue=*0x%x)", queue); @@ -621,10 +636,10 @@ s32 cellSyncQueueSize(vm::ptr queue) const u32 depth = queue->check_depth(); - return queue->ctrl.load().count & 0xffffff; + return NOT_AN_ERROR(queue->ctrl.load().count & 0xffffff); } -s32 cellSyncQueueClear(PPUThread& ppu, vm::ptr queue) +ppu_error_code cellSyncQueueClear(PPUThread& ppu, vm::ptr queue) { cellSync.trace("cellSyncQueueClear(queue=*0x%x)", queue); @@ -692,7 +707,7 @@ void syncLFQueueInitialize(vm::ptr queue, vm::cptr buffer queue->m_eq_id = 0; } -s32 cellSyncLFQueueInitialize(vm::ptr queue, vm::cptr buffer, u32 size, u32 depth, u32 direction, vm::ptr eaSignal) +ppu_error_code cellSyncLFQueueInitialize(vm::ptr queue, vm::cptr buffer, u32 size, u32 depth, u32 direction, vm::ptr eaSignal) { cellSync.warning("cellSyncLFQueueInitialize(queue=*0x%x, buffer=*0x%x, size=0x%x, depth=0x%x, direction=%d, eaSignal=*0x%x)", queue, buffer, size, depth, direction, eaSignal); @@ -729,7 +744,7 @@ s32 cellSyncLFQueueInitialize(vm::ptr queue, vm::cptr buf if (s32 ret = process_get_sdk_version(process_getpid(), sdk_ver)) { - return ret; + return NOT_AN_ERROR(ret); } if (sdk_ver == -1) @@ -801,7 +816,7 @@ s32 cellSyncLFQueueInitialize(vm::ptr queue, vm::cptr buf return CELL_OK; } -s32 _cellSyncLFQueueGetPushPointer(PPUThread& ppu, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) +ppu_error_code _cellSyncLFQueueGetPushPointer(PPUThread& ppu, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) { cellSync.warning("_cellSyncLFQueueGetPushPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue); @@ -883,21 +898,18 @@ s32 _cellSyncLFQueueGetPushPointer(PPUThread& ppu, vm::ptr queu { if (!push.m_h7 || res) { - return res; + return NOT_AN_ERROR(res); } break; } } - if (s32 res = sys_event_queue_receive(ppu, queue->m_eq_id, vm::null, 0)) - { - throw EXCEPTION(""); - } + ASSERT(sys_event_queue_receive(ppu, queue->m_eq_id, vm::null, 0) == CELL_OK); var1 = 1; } } -s32 _cellSyncLFQueueGetPushPointer2(PPUThread& ppu, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) +ppu_error_code _cellSyncLFQueueGetPushPointer2(PPUThread& ppu, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) { // arguments copied from _cellSyncLFQueueGetPushPointer cellSync.todo("_cellSyncLFQueueGetPushPointer2(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue); @@ -905,7 +917,7 @@ s32 _cellSyncLFQueueGetPushPointer2(PPUThread& ppu, vm::ptr que throw EXCEPTION(""); } -s32 _cellSyncLFQueueCompletePushPointer(PPUThread& ppu, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) +ppu_error_code _cellSyncLFQueueCompletePushPointer(PPUThread& ppu, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) { cellSync.warning("_cellSyncLFQueueCompletePushPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x)", queue, pointer, fpSendSignal); @@ -983,7 +995,7 @@ s32 _cellSyncLFQueueCompletePushPointer(PPUThread& ppu, vm::ptr if (var9 > 1 && (u32)var8 > 1) { - assert(16 - var2 <= 1); + ASSERT(16 - var2 <= 1); } s32 var11 = (pack >> 10) & 0x1f; @@ -1015,16 +1027,12 @@ s32 _cellSyncLFQueueCompletePushPointer(PPUThread& ppu, vm::ptr if (queue->push2.compare_and_swap_test(old, push2)) { - assert(var2 + var4 < 16); + ASSERT(var2 + var4 < 16); if (var6 != -1) { - bool exch = queue->push3.compare_and_swap_test(old2, push3); - assert(exch); - if (exch) - { - assert(fpSendSignal); - return fpSendSignal(ppu, (u32)queue->m_eaSignal.addr(), var6); - } + ASSERT(queue->push3.compare_and_swap_test(old2, push3)); + ASSERT(fpSendSignal); + return NOT_AN_ERROR(fpSendSignal(ppu, (u32)queue->m_eaSignal.addr(), var6)); } else { @@ -1041,7 +1049,7 @@ s32 _cellSyncLFQueueCompletePushPointer(PPUThread& ppu, vm::ptr } } -s32 _cellSyncLFQueueCompletePushPointer2(PPUThread& ppu, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) +ppu_error_code _cellSyncLFQueueCompletePushPointer2(PPUThread& ppu, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) { // arguments copied from _cellSyncLFQueueCompletePushPointer cellSync.todo("_cellSyncLFQueueCompletePushPointer2(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x)", queue, pointer, fpSendSignal); @@ -1049,7 +1057,7 @@ s32 _cellSyncLFQueueCompletePushPointer2(PPUThread& ppu, vm::ptr queue, vm::cptr buffer, u32 isBlocking) +ppu_error_code _cellSyncLFQueuePushBody(PPUThread& ppu, vm::ptr queue, vm::cptr buffer, u32 isBlocking) { // cellSyncLFQueuePush has 1 in isBlocking param, cellSyncLFQueueTryPush has 0 cellSync.warning("_cellSyncLFQueuePushBody(queue=*0x%x, buffer=*0x%x, isBlocking=%d)", queue, buffer, isBlocking); @@ -1083,7 +1091,7 @@ s32 _cellSyncLFQueuePushBody(PPUThread& ppu, vm::ptr queue, vm: if (!isBlocking || res != CELL_SYNC_ERROR_AGAIN) { - if (res) return res; + if (res) return NOT_AN_ERROR(res); break; } @@ -1094,7 +1102,7 @@ s32 _cellSyncLFQueuePushBody(PPUThread& ppu, vm::ptr queue, vm: const s32 depth = queue->m_depth; const s32 size = queue->m_size; const s32 pos = *position; - const u32 addr = VM_CAST((u64)((queue->m_buffer.addr() & ~1ull) + size * (pos >= depth ? pos - depth : pos))); + const u32 addr = vm::cast((u64)((queue->m_buffer.addr() & ~1ull) + size * (pos >= depth ? pos - depth : pos)), HERE); std::memcpy(vm::base(addr), buffer.get_ptr(), size); if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) @@ -1107,7 +1115,7 @@ s32 _cellSyncLFQueuePushBody(PPUThread& ppu, vm::ptr queue, vm: } } -s32 _cellSyncLFQueueGetPopPointer(PPUThread& ppu, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 arg4, u32 useEventQueue) +ppu_error_code _cellSyncLFQueueGetPopPointer(PPUThread& ppu, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 arg4, u32 useEventQueue) { cellSync.warning("_cellSyncLFQueueGetPopPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, arg4=%d, useEventQueue=%d)", queue, pointer, isBlocking, arg4, useEventQueue); @@ -1189,21 +1197,18 @@ s32 _cellSyncLFQueueGetPopPointer(PPUThread& ppu, vm::ptr queue { if (!pop.m_h3 || res) { - return res; + return NOT_AN_ERROR(res); } break; } } - if (s32 res = sys_event_queue_receive(ppu, queue->m_eq_id, vm::null, 0)) - { - throw EXCEPTION(""); - } + ASSERT(sys_event_queue_receive(ppu, queue->m_eq_id, vm::null, 0) == CELL_OK); var1 = 1; } } -s32 _cellSyncLFQueueGetPopPointer2(PPUThread& ppu, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) +ppu_error_code _cellSyncLFQueueGetPopPointer2(PPUThread& ppu, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) { // arguments copied from _cellSyncLFQueueGetPopPointer cellSync.todo("_cellSyncLFQueueGetPopPointer2(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue); @@ -1211,7 +1216,7 @@ s32 _cellSyncLFQueueGetPopPointer2(PPUThread& ppu, vm::ptr queu throw EXCEPTION(""); } -s32 _cellSyncLFQueueCompletePopPointer(PPUThread& ppu, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) +ppu_error_code _cellSyncLFQueueCompletePopPointer(PPUThread& ppu, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) { // arguments copied from _cellSyncLFQueueCompletePushPointer + unknown argument (noQueueFull taken from LFQueue2CompletePopPointer) cellSync.warning("_cellSyncLFQueueCompletePopPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x, noQueueFull=%d)", queue, pointer, fpSendSignal, noQueueFull); @@ -1294,7 +1299,7 @@ s32 _cellSyncLFQueueCompletePopPointer(PPUThread& ppu, vm::ptr if (var9 > 1 && (u32)var8 > 1) { - assert(16 - var2 <= 1); + ASSERT(16 - var2 <= 1); } s32 var11 = (pack >> 10) & 0x1f; @@ -1324,13 +1329,9 @@ s32 _cellSyncLFQueueCompletePopPointer(PPUThread& ppu, vm::ptr { if (var6 != -1) { - bool exch = queue->pop3.compare_and_swap_test(old2, pop3); - assert(exch); - if (exch) - { - assert(fpSendSignal); - return fpSendSignal(ppu, (u32)queue->m_eaSignal.addr(), var6); - } + ASSERT(queue->pop3.compare_and_swap_test(old2, pop3)); + ASSERT(fpSendSignal); + return NOT_AN_ERROR(fpSendSignal(ppu, (u32)queue->m_eaSignal.addr(), var6)); } else { @@ -1347,7 +1348,7 @@ s32 _cellSyncLFQueueCompletePopPointer(PPUThread& ppu, vm::ptr } } -s32 _cellSyncLFQueueCompletePopPointer2(PPUThread& ppu, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) +ppu_error_code _cellSyncLFQueueCompletePopPointer2(PPUThread& ppu, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) { // arguments copied from _cellSyncLFQueueCompletePopPointer cellSync.todo("_cellSyncLFQueueCompletePopPointer2(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x, noQueueFull=%d)", queue, pointer, fpSendSignal, noQueueFull); @@ -1355,7 +1356,7 @@ s32 _cellSyncLFQueueCompletePopPointer2(PPUThread& ppu, vm::ptr throw EXCEPTION(""); } -s32 _cellSyncLFQueuePopBody(PPUThread& ppu, vm::ptr queue, vm::ptr buffer, u32 isBlocking) +ppu_error_code _cellSyncLFQueuePopBody(PPUThread& ppu, vm::ptr queue, vm::ptr buffer, u32 isBlocking) { // cellSyncLFQueuePop has 1 in isBlocking param, cellSyncLFQueueTryPop has 0 cellSync.warning("_cellSyncLFQueuePopBody(queue=*0x%x, buffer=*0x%x, isBlocking=%d)", queue, buffer, isBlocking); @@ -1389,7 +1390,7 @@ s32 _cellSyncLFQueuePopBody(PPUThread& ppu, vm::ptr queue, vm:: if (!isBlocking || res != CELL_SYNC_ERROR_AGAIN) { - if (res) return res; + if (res) return NOT_AN_ERROR(res); break; } @@ -1400,7 +1401,7 @@ s32 _cellSyncLFQueuePopBody(PPUThread& ppu, vm::ptr queue, vm:: const s32 depth = queue->m_depth; const s32 size = queue->m_size; const s32 pos = *position; - const u32 addr = VM_CAST((u64)((queue->m_buffer.addr() & ~1) + size * (pos >= depth ? pos - depth : pos))); + const u32 addr = vm::cast((u64)((queue->m_buffer.addr() & ~1) + size * (pos >= depth ? pos - depth : pos)), HERE); std::memcpy(buffer.get_ptr(), vm::base(addr), size); if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) @@ -1413,7 +1414,7 @@ s32 _cellSyncLFQueuePopBody(PPUThread& ppu, vm::ptr queue, vm:: } } -s32 cellSyncLFQueueClear(vm::ptr queue) +ppu_error_code cellSyncLFQueueClear(vm::ptr queue) { cellSync.warning("cellSyncLFQueueClear(queue=*0x%x)", queue); @@ -1464,7 +1465,7 @@ s32 cellSyncLFQueueClear(vm::ptr queue) return CELL_OK; } -s32 cellSyncLFQueueSize(vm::ptr queue, vm::ptr size) +ppu_error_code cellSyncLFQueueSize(vm::ptr queue, vm::ptr size) { cellSync.warning("cellSyncLFQueueSize(queue=*0x%x, size=*0x%x)", queue, size); @@ -1501,7 +1502,7 @@ s32 cellSyncLFQueueSize(vm::ptr queue, vm::ptr size) } } -s32 cellSyncLFQueueDepth(vm::ptr queue, vm::ptr depth) +ppu_error_code cellSyncLFQueueDepth(vm::ptr queue, vm::ptr depth) { cellSync.trace("cellSyncLFQueueDepth(queue=*0x%x, depth=*0x%x)", queue, depth); @@ -1520,7 +1521,7 @@ s32 cellSyncLFQueueDepth(vm::ptr queue, vm::ptr depth) return CELL_OK; } -s32 _cellSyncLFQueueGetSignalAddress(vm::cptr queue, vm::pptr ppSignal) +ppu_error_code _cellSyncLFQueueGetSignalAddress(vm::cptr queue, vm::pptr ppSignal) { cellSync.trace("_cellSyncLFQueueGetSignalAddress(queue=*0x%x, ppSignal=**0x%x)", queue, ppSignal); @@ -1539,7 +1540,7 @@ s32 _cellSyncLFQueueGetSignalAddress(vm::cptr queue, vm::pptr queue, vm::ptr direction) +ppu_error_code cellSyncLFQueueGetDirection(vm::cptr queue, vm::ptr direction) { cellSync.trace("cellSyncLFQueueGetDirection(queue=*0x%x, direction=*0x%x)", queue, direction); @@ -1558,7 +1559,7 @@ s32 cellSyncLFQueueGetDirection(vm::cptr queue, vm::ptr di return CELL_OK; } -s32 cellSyncLFQueueGetEntrySize(vm::cptr queue, vm::ptr entry_size) +ppu_error_code cellSyncLFQueueGetEntrySize(vm::cptr queue, vm::ptr entry_size) { cellSync.trace("cellSyncLFQueueGetEntrySize(queue=*0x%x, entry_size=*0x%x)", queue, entry_size); @@ -1577,57 +1578,22 @@ s32 cellSyncLFQueueGetEntrySize(vm::cptr queue, vm::ptr en return CELL_OK; } -s32 _cellSyncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) +ppu_error_code _cellSyncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) { cellSync.todo("_cellSyncLFQueueAttachLv2EventQueue(spus=*0x%x, num=%d, queue=*0x%x)", spus, num, queue); throw EXCEPTION(""); } -s32 _cellSyncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) +ppu_error_code _cellSyncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) { cellSync.todo("_cellSyncLFQueueDetachLv2EventQueue(spus=*0x%x, num=%d, queue=*0x%x)", spus, num, queue); throw EXCEPTION(""); } -Module<> cellSync("cellSync", []() +DECLARE(ppu_module_manager::cellSync)("cellSync", []() { - // setup error handler - cellSync.on_error = [](s64 value, ModuleFunc* func) - { - // get error name for CELL_SYNC errors - auto get_error = [](u32 code) -> const char* - { - switch (code) - { - case CELL_SYNC_ERROR_AGAIN: return "CELL_SYNC_ERROR_AGAIN"; - case CELL_SYNC_ERROR_INVAL: return "CELL_SYNC_ERROR_INVAL"; - case CELL_SYNC_ERROR_NOSYS: return "CELL_SYNC_ERROR_NOSYS"; - case CELL_SYNC_ERROR_NOMEM: return "CELL_SYNC_ERROR_NOMEM"; - case CELL_SYNC_ERROR_SRCH: return "CELL_SYNC_ERROR_SRCH"; - case CELL_SYNC_ERROR_NOENT: return "CELL_SYNC_ERROR_NOENT"; - case CELL_SYNC_ERROR_NOEXEC: return "CELL_SYNC_ERROR_NOEXEC"; - case CELL_SYNC_ERROR_DEADLK: return "CELL_SYNC_ERROR_DEADLK"; - case CELL_SYNC_ERROR_PERM: return "CELL_SYNC_ERROR_PERM"; - case CELL_SYNC_ERROR_BUSY: return "CELL_SYNC_ERROR_BUSY"; - case CELL_SYNC_ERROR_ABORT: return "CELL_SYNC_ERROR_ABORT"; - case CELL_SYNC_ERROR_FAULT: return "CELL_SYNC_ERROR_FAULT"; - case CELL_SYNC_ERROR_CHILD: return "CELL_SYNC_ERROR_CHILD"; - case CELL_SYNC_ERROR_STAT: return "CELL_SYNC_ERROR_STAT"; - case CELL_SYNC_ERROR_ALIGN: return "CELL_SYNC_ERROR_ALIGN"; - } - - return "???"; - }; - - // analyse error code - if (u32 code = (value & 0xffffff00) == 0x80410100 ? static_cast(value) : 0) - { - cellSync.error("%s() -> %s (0x%x)", func->name, get_error(code), code); - } - }; - REG_FUNC(cellSync, cellSyncMutexInitialize); REG_FUNC(cellSync, cellSyncMutexLock); REG_FUNC(cellSync, cellSyncMutexTryLock); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/Cell/Modules/cellSync.h similarity index 58% rename from rpcs3/Emu/SysCalls/Modules/cellSync.h rename to rpcs3/Emu/Cell/Modules/cellSync.h index fbf1e7464b..831ce776d1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/Cell/Modules/cellSync.h @@ -3,53 +3,82 @@ namespace vm { using namespace ps3; } // Return Codes -enum +enum CellSyncError : s32 { - CELL_SYNC_ERROR_AGAIN = 0x80410101, - CELL_SYNC_ERROR_INVAL = 0x80410102, - CELL_SYNC_ERROR_NOSYS = 0x80410103, - CELL_SYNC_ERROR_NOMEM = 0x80410104, - CELL_SYNC_ERROR_SRCH = 0x80410105, - CELL_SYNC_ERROR_NOENT = 0x80410106, - CELL_SYNC_ERROR_NOEXEC = 0x80410107, - CELL_SYNC_ERROR_DEADLK = 0x80410108, - CELL_SYNC_ERROR_PERM = 0x80410109, - CELL_SYNC_ERROR_BUSY = 0x8041010A, - CELL_SYNC_ERROR_ABORT = 0x8041010C, - CELL_SYNC_ERROR_FAULT = 0x8041010D, - CELL_SYNC_ERROR_CHILD = 0x8041010E, - CELL_SYNC_ERROR_STAT = 0x8041010F, - CELL_SYNC_ERROR_ALIGN = 0x80410110, - - CELL_SYNC_ERROR_NULL_POINTER = 0x80410111, - CELL_SYNC_ERROR_NOT_SUPPORTED_THREAD = 0x80410112, - CELL_SYNC_ERROR_SHOTAGE = 0x80410112, - CELL_SYNC_ERROR_NO_NOTIFIER = 0x80410113, - CELL_SYNC_ERROR_UNKNOWNKEY = 0x80410113, - CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, + CELL_SYNC_ERROR_AGAIN = ERROR_CODE(0x80410101), + CELL_SYNC_ERROR_INVAL = ERROR_CODE(0x80410102), + CELL_SYNC_ERROR_NOSYS = ERROR_CODE(0x80410103), + CELL_SYNC_ERROR_NOMEM = ERROR_CODE(0x80410104), + CELL_SYNC_ERROR_SRCH = ERROR_CODE(0x80410105), + CELL_SYNC_ERROR_NOENT = ERROR_CODE(0x80410106), + CELL_SYNC_ERROR_NOEXEC = ERROR_CODE(0x80410107), + CELL_SYNC_ERROR_DEADLK = ERROR_CODE(0x80410108), + CELL_SYNC_ERROR_PERM = ERROR_CODE(0x80410109), + CELL_SYNC_ERROR_BUSY = ERROR_CODE(0x8041010A), + CELL_SYNC_ERROR_ABORT = ERROR_CODE(0x8041010C), + CELL_SYNC_ERROR_FAULT = ERROR_CODE(0x8041010D), + CELL_SYNC_ERROR_CHILD = ERROR_CODE(0x8041010E), + CELL_SYNC_ERROR_STAT = ERROR_CODE(0x8041010F), + CELL_SYNC_ERROR_ALIGN = ERROR_CODE(0x80410110), + CELL_SYNC_ERROR_NULL_POINTER = ERROR_CODE(0x80410111), + CELL_SYNC_ERROR_NOT_SUPPORTED_THREAD = ERROR_CODE(0x80410112), + CELL_SYNC_ERROR_NO_NOTIFIER = ERROR_CODE(0x80410113), + CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = ERROR_CODE(0x80410114), }; +enum CellSyncError1 : s32 +{ + CELL_SYNC_ERROR_SHOTAGE = ERROR_CODE(0x80410112), + CELL_SYNC_ERROR_UNKNOWNKEY = ERROR_CODE(0x80410113), +}; + +template<> +inline const char* ppu_error_code::print(CellSyncError error) +{ + switch (error) + { + STR_CASE(CELL_SYNC_ERROR_AGAIN); + STR_CASE(CELL_SYNC_ERROR_INVAL); + STR_CASE(CELL_SYNC_ERROR_NOSYS); + STR_CASE(CELL_SYNC_ERROR_NOMEM); + STR_CASE(CELL_SYNC_ERROR_SRCH); + STR_CASE(CELL_SYNC_ERROR_NOENT); + STR_CASE(CELL_SYNC_ERROR_NOEXEC); + STR_CASE(CELL_SYNC_ERROR_DEADLK); + STR_CASE(CELL_SYNC_ERROR_PERM); + STR_CASE(CELL_SYNC_ERROR_BUSY); + STR_CASE(CELL_SYNC_ERROR_ABORT); + STR_CASE(CELL_SYNC_ERROR_FAULT); + STR_CASE(CELL_SYNC_ERROR_CHILD); + STR_CASE(CELL_SYNC_ERROR_STAT); + STR_CASE(CELL_SYNC_ERROR_ALIGN); + STR_CASE(CELL_SYNC_ERROR_NULL_POINTER); + STR_CASE(CELL_SYNC_ERROR_NOT_SUPPORTED_THREAD); + STR_CASE(CELL_SYNC_ERROR_NO_NOTIFIER); + STR_CASE(CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE); + } + + return nullptr; +} + +template<> +inline const char* ppu_error_code::print(CellSyncError1 error) +{ + switch (error) + { + STR_CASE(CELL_SYNC_ERROR_SHOTAGE); + STR_CASE(CELL_SYNC_ERROR_UNKNOWNKEY); + } + + return nullptr; +} + namespace _sync { struct alignas(4) mutex // CellSyncMutex control variable { be_t rel; be_t acq; - - static inline be_t acquire(mutex& ctrl) - { - return ctrl.acq++; - } - - static inline bool try_lock(mutex& ctrl) - { - return ctrl.acq++ == ctrl.rel; - } - - static inline void unlock(mutex& ctrl) - { - ctrl.rel++; - } }; } @@ -108,7 +137,7 @@ CHECK_SIZE_ALIGN(CellSyncBarrier, 4, 4); namespace _sync { - struct rwlock // CellSyncRwm control variable + struct alignas(4) rwlock // CellSyncRwm control variable { be_t readers; be_t writers; @@ -160,25 +189,25 @@ CHECK_SIZE_ALIGN(CellSyncRwm, 16, 16); namespace _sync { - struct queue // CellSyncQueue control variable + struct alignas(8) queue // CellSyncQueue control variable { union { be_t x0; - bf_be_t next; - bf_be_t _pop; + bf_t, 0, 24> next; + bf_t, 24, 8> _pop; }; union { be_t x4; - bf_be_t count; - bf_be_t _push; + bf_t, 0, 24> count; + bf_t, 24, 8> _push; }; - static inline bool try_push_begin(queue& ctrl, u32 depth, u32& position) + static inline bool try_push_begin(queue& ctrl, u32 depth, u32* position) { const u32 count = ctrl.count; @@ -187,14 +216,14 @@ namespace _sync return false; } - position = ctrl.next; - ctrl.next = position + 1 != depth ? position + 1 : 0; + *position = ctrl.next; + ctrl.next = *position + 1 != depth ? *position + 1 : 0; ctrl.count = count + 1; ctrl._push = 1; return true; } - static inline bool try_pop_begin(queue& ctrl, u32 depth, u32& position) + static inline bool try_pop_begin(queue& ctrl, u32 depth, u32* position) { const u32 count = ctrl.count; @@ -204,12 +233,12 @@ namespace _sync } ctrl._pop = 1; - position = ctrl.next + depth - count; + *position = ctrl.next + depth - count; ctrl.count = count - 1; return true; } - static inline bool try_peek_begin(queue& ctrl, u32 depth, u32& position) + static inline bool try_peek_begin(queue& ctrl, u32 depth, u32* position) { const u32 count = ctrl.count; @@ -219,7 +248,7 @@ namespace _sync } ctrl._pop = 1; - position = ctrl.next + depth - count; + *position = ctrl.next + depth - count; return true; } @@ -281,7 +310,7 @@ enum CellSyncQueueDirection : u32 // CellSyncLFQueueDirection struct alignas(128) CellSyncLFQueue { - struct pop1_t + struct alignas(8) pop1_t { be_t m_h1; be_t m_h2; @@ -294,13 +323,13 @@ struct alignas(128) CellSyncLFQueue be_t pack; }; - struct pop3_t + struct alignas(4) pop3_t { be_t m_h1; be_t m_h2; }; - struct push1_t + struct alignas(8) push1_t { be_t m_h5; be_t m_h6; @@ -313,7 +342,7 @@ struct alignas(128) CellSyncLFQueue be_t pack; }; - struct push3_t + struct alignas(4) push3_t { be_t m_h5; be_t m_h6; @@ -367,4 +396,4 @@ struct alignas(128) CellSyncLFQueue CHECK_SIZE_ALIGN(CellSyncLFQueue, 128, 128); // Prototypes -s32 cellSyncLFQueueInitialize(vm::ptr queue, vm::cptr buffer, u32 size, u32 depth, u32 direction, vm::ptr eaSignal); +ppu_error_code cellSyncLFQueueInitialize(vm::ptr queue, vm::cptr buffer, u32 size, u32 depth, u32 direction, vm::ptr eaSignal); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync2.cpp b/rpcs3/Emu/Cell/Modules/cellSync2.cpp similarity index 89% rename from rpcs3/Emu/SysCalls/Modules/cellSync2.cpp rename to rpcs3/Emu/Cell/Modules/cellSync2.cpp index b875e2f7ec..145d51ba98 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync2.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSync2.cpp @@ -1,21 +1,17 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellSync2.h" -struct Sync2Instance -{ - CellSync2CallerThreadType gCellSync2CallerThreadTypePpuThread; - CellSync2Notifier gCellSync2NotifierPpuThread; - CellSync2CallerThreadType gCellSync2CallerThreadTypePpuFiber; - CellSync2Notifier gCellSync2NotifierPpuFiber; - CellSync2Notifier gCellSync2NotifierSpursTask; - CellSync2Notifier gCellSync2NotifierSpursJobQueueJob; -}; +LOG_CHANNEL(cellSync2); -extern Module cellSync2; +vm::gvar gCellSync2CallerThreadTypePpuThread; +vm::gvar gCellSync2NotifierPpuThread; +vm::gvar gCellSync2CallerThreadTypePpuFiber; +vm::gvar gCellSync2NotifierPpuFiber; +vm::gvar gCellSync2NotifierSpursTask; +vm::gvar gCellSync2NotifierSpursJobQueueJob; s32 _cellSync2MutexAttributeInitialize(vm::ptr attr, u32 sdkVersion) { @@ -259,14 +255,14 @@ s32 cellSync2QueueGetDepth() return CELL_OK; } -Module cellSync2("cellSync2", []() +DECLARE(ppu_module_manager::cellSync2)("cellSync2", []() { - REG_VARIABLE(cellSync2, gCellSync2CallerThreadTypePpuThread); - REG_VARIABLE(cellSync2, gCellSync2NotifierPpuThread); - REG_VARIABLE(cellSync2, gCellSync2CallerThreadTypePpuFiber); - REG_VARIABLE(cellSync2, gCellSync2NotifierPpuFiber); - REG_VARIABLE(cellSync2, gCellSync2NotifierSpursTask); - REG_VARIABLE(cellSync2, gCellSync2NotifierSpursJobQueueJob); + REG_VAR(cellSync2, gCellSync2CallerThreadTypePpuThread); + REG_VAR(cellSync2, gCellSync2NotifierPpuThread); + REG_VAR(cellSync2, gCellSync2CallerThreadTypePpuFiber); + REG_VAR(cellSync2, gCellSync2NotifierPpuFiber); + REG_VAR(cellSync2, gCellSync2NotifierSpursTask); + REG_VAR(cellSync2, gCellSync2NotifierSpursJobQueueJob); REG_FUNC(cellSync2, _cellSync2MutexAttributeInitialize); REG_FUNC(cellSync2, cellSync2MutexEstimateBufferSize); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync2.h b/rpcs3/Emu/Cell/Modules/cellSync2.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellSync2.h rename to rpcs3/Emu/Cell/Modules/cellSync2.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysconf.cpp b/rpcs3/Emu/Cell/Modules/cellSysconf.cpp similarity index 58% rename from rpcs3/Emu/SysCalls/Modules/cellSysconf.cpp rename to rpcs3/Emu/Cell/Modules/cellSysconf.cpp index 9a3a55f788..3685f8f1ef 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysconf.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysconf.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellSysconf; +LOG_CHANNEL(cellSysconf); s32 cellSysconfAbort() { @@ -21,13 +20,11 @@ s32 cellSysconfBtGetDeviceList() void cellSysutil_Sysconf_init() { - extern Module<> cellSysutil; - REG_FUNC(cellSysutil, cellSysconfAbort); REG_FUNC(cellSysutil, cellSysconfOpen); } -Module<> cellSysconf("cellSysconf", []() +DECLARE(ppu_module_manager::cellSysconf)("cellSysconfExtUtility", []() { - REG_FUNC(cellSysconf, cellSysconfBtGetDeviceList); + REG_FUNC(cellSysconfExtUtility, cellSysconfBtGetDeviceList); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp b/rpcs3/Emu/Cell/Modules/cellSysmodule.cpp similarity index 53% rename from rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp rename to rpcs3/Emu/Cell/Modules/cellSysmodule.cpp index f5fe1b2230..c8ffe495d0 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysmodule.cpp @@ -1,221 +1,357 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/System.h" -#include "Emu/SysCalls/ModuleManager.h" -#include "Emu/SysCalls/Modules.h" - -extern Module<> cellSysmodule; - -enum -{ - CELL_SYSMODULE_LOADED = CELL_OK, - CELL_SYSMODULE_ERROR_DUPLICATED = 0x80012001, - CELL_SYSMODULE_ERROR_UNKNOWN = 0x80012002, - CELL_SYSMODULE_ERROR_UNLOADED = 0x80012003, - CELL_SYSMODULE_ERROR_INVALID_MEMCONTAINER = 0x80012004, - CELL_SYSMODULE_ERROR_FATAL = 0x800120ff, -}; - -const char* get_module_id(u16 id) -{ - switch (id) - { - case 0x0000: return "CELL_SYSMODULE_NET"; - case 0x0001: return "CELL_SYSMODULE_HTTP"; - case 0x0002: return "CELL_SYSMODULE_HTTP_UTIL"; - case 0x0003: return "CELL_SYSMODULE_SSL"; - case 0x0004: return "CELL_SYSMODULE_HTTPS"; - case 0x0005: return "CELL_SYSMODULE_VDEC"; - case 0x0006: return "CELL_SYSMODULE_ADEC"; - case 0x0007: return "CELL_SYSMODULE_DMUX"; - case 0x0008: return "CELL_SYSMODULE_VPOST"; - case 0x0009: return "CELL_SYSMODULE_RTC"; - case 0x000a: return "CELL_SYSMODULE_SPURS"; - case 0x000b: return "CELL_SYSMODULE_OVIS"; - case 0x000c: return "CELL_SYSMODULE_SHEAP"; - case 0x000d: return "CELL_SYSMODULE_SYNC"; - case 0x000e: return "CELL_SYSMODULE_FS"; - case 0x000f: return "CELL_SYSMODULE_JPGDEC"; - case 0x0010: return "CELL_SYSMODULE_GCM_SYS"; - case 0x0011: return "CELL_SYSMODULE_AUDIO"; - case 0x0012: return "CELL_SYSMODULE_PAMF"; - case 0x0013: return "CELL_SYSMODULE_ATRAC3PLUS"; - case 0x0014: return "CELL_SYSMODULE_NETCTL"; - case 0x0015: return "CELL_SYSMODULE_SYSUTIL"; - case 0x0016: return "CELL_SYSMODULE_SYSUTIL_NP"; - case 0x0017: return "CELL_SYSMODULE_IO"; - case 0x0018: return "CELL_SYSMODULE_PNGDEC"; - case 0x0019: return "CELL_SYSMODULE_FONT"; - case 0x001a: return "CELL_SYSMODULE_FONTFT"; - case 0x001b: return "CELL_SYSMODULE_FREETYPE"; - case 0x001c: return "CELL_SYSMODULE_USBD"; - case 0x001d: return "CELL_SYSMODULE_SAIL"; - case 0x001e: return "CELL_SYSMODULE_L10N"; - case 0x001f: return "CELL_SYSMODULE_RESC"; - case 0x0020: return "CELL_SYSMODULE_DAISY"; - case 0x0021: return "CELL_SYSMODULE_KEY2CHAR"; - case 0x0022: return "CELL_SYSMODULE_MIC"; - case 0x0023: return "CELL_SYSMODULE_CAMERA"; - case 0x0024: return "CELL_SYSMODULE_VDEC_MPEG2"; - case 0x0025: return "CELL_SYSMODULE_VDEC_AVC"; - case 0x0026: return "CELL_SYSMODULE_ADEC_LPCM"; - case 0x0027: return "CELL_SYSMODULE_ADEC_AC3"; - case 0x0028: return "CELL_SYSMODULE_ADEC_ATX"; - case 0x0029: return "CELL_SYSMODULE_ADEC_AT3"; - case 0x002a: return "CELL_SYSMODULE_DMUX_PAMF"; - case 0x002b: return "CELL_SYSMODULE_VDEC_AL"; - case 0x002c: return "CELL_SYSMODULE_ADEC_AL"; - case 0x002d: return "CELL_SYSMODULE_DMUX_AL"; - case 0x002e: return "CELL_SYSMODULE_LV2DBG"; - case 0x002f: return "CELL_SYSMODULE_SYSUTIL_AVCHAT"; - case 0x0030: return "CELL_SYSMODULE_USBPSPCM"; - case 0x0031: return "CELL_SYSMODULE_AVCONF_EXT"; - case 0x0032: return "CELL_SYSMODULE_SYSUTIL_USERINFO"; - case 0x0033: return "CELL_SYSMODULE_SYSUTIL_SAVEDATA"; - case 0x0034: return "CELL_SYSMODULE_SUBDISPLAY"; - case 0x0035: return "CELL_SYSMODULE_SYSUTIL_REC"; - case 0x0036: return "CELL_SYSMODULE_VIDEO_EXPORT"; - case 0x0037: return "CELL_SYSMODULE_SYSUTIL_GAME_EXEC"; - case 0x0038: return "CELL_SYSMODULE_SYSUTIL_NP2"; - case 0x0039: return "CELL_SYSMODULE_SYSUTIL_AP"; - case 0x003a: return "CELL_SYSMODULE_SYSUTIL_NP_CLANS"; - case 0x003b: return "CELL_SYSMODULE_SYSUTIL_OSK_EXT"; - case 0x003c: return "CELL_SYSMODULE_VDEC_DIVX"; - case 0x003d: return "CELL_SYSMODULE_JPGENC"; - case 0x003e: return "CELL_SYSMODULE_SYSUTIL_GAME"; - case 0x003f: return "CELL_SYSMODULE_BGDL"; - case 0x0040: return "CELL_SYSMODULE_FREETYPE_TT"; - case 0x0041: return "CELL_SYSMODULE_SYSUTIL_VIDEO_UPLOAD"; - case 0x0042: return "CELL_SYSMODULE_SYSUTIL_SYSCONF_EXT"; - case 0x0043: return "CELL_SYSMODULE_FIBER"; - case 0x0044: return "CELL_SYSMODULE_SYSUTIL_NP_COMMERCE2"; - case 0x0045: return "CELL_SYSMODULE_SYSUTIL_NP_TUS"; - case 0x0046: return "CELL_SYSMODULE_VOICE"; - case 0x0047: return "CELL_SYSMODULE_ADEC_CELP8"; - case 0x0048: return "CELL_SYSMODULE_CELP8ENC"; - case 0x0049: return "CELL_SYSMODULE_SYSUTIL_LICENSEAREA"; - case 0x004a: return "CELL_SYSMODULE_SYSUTIL_MUSIC2"; - case 0x004e: return "CELL_SYSMODULE_SYSUTIL_SCREENSHOT"; - case 0x004f: return "CELL_SYSMODULE_SYSUTIL_MUSIC_DECODE"; - case 0x0050: return "CELL_SYSMODULE_SPURS_JQ"; - case 0x0052: return "CELL_SYSMODULE_PNGENC"; - case 0x0053: return "CELL_SYSMODULE_SYSUTIL_MUSIC_DECODE2"; - case 0x0055: return "CELL_SYSMODULE_SYNC2"; - case 0x0056: return "CELL_SYSMODULE_SYSUTIL_NP_UTIL"; - case 0x0057: return "CELL_SYSMODULE_RUDP"; - case 0x0059: return "CELL_SYSMODULE_SYSUTIL_NP_SNS"; - case 0x005a: return "CELL_SYSMODULE_GEM"; - case 0xf00a: return "CELL_SYSMODULE_CELPENC"; - case 0xf010: return "CELL_SYSMODULE_GIFDEC"; - case 0xf019: return "CELL_SYSMODULE_ADEC_CELP"; - case 0xf01b: return "CELL_SYSMODULE_ADEC_M2BC"; - case 0xf01d: return "CELL_SYSMODULE_ADEC_M4AAC"; - case 0xf01e: return "CELL_SYSMODULE_ADEC_MP3"; - case 0xf023: return "CELL_SYSMODULE_IMEJP"; - case 0xf028: return "CELL_SYSMODULE_SYSUTIL_MUSIC"; - case 0xf029: return "CELL_SYSMODULE_PHOTO_EXPORT"; - case 0xf02a: return "CELL_SYSMODULE_PRINT"; - case 0xf02b: return "CELL_SYSMODULE_PHOTO_IMPORT"; - case 0xf02c: return "CELL_SYSMODULE_MUSIC_EXPORT"; - case 0xf02e: return "CELL_SYSMODULE_PHOTO_DECODE"; - case 0xf02f: return "CELL_SYSMODULE_SYSUTIL_SEARCH"; - case 0xf030: return "CELL_SYSMODULE_SYSUTIL_AVCHAT2"; - case 0xf034: return "CELL_SYSMODULE_SAIL_REC"; - case 0xf035: return "CELL_SYSMODULE_SYSUTIL_NP_TROPHY"; - case 0xf054: return "CELL_SYSMODULE_LIBATRAC3MULTI"; - case 0xffff: return "CELL_SYSMODULE_INVALID"; - } - - return "UNKNOWN MODULE"; -} - -s32 cellSysmoduleInitialize() -{ - cellSysmodule.warning("cellSysmoduleInitialize()"); - return CELL_OK; -} - -s32 cellSysmoduleFinalize() -{ - cellSysmodule.warning("cellSysmoduleFinalize()"); - return CELL_OK; -} - -s32 cellSysmoduleSetMemcontainer(u32 ct_id) -{ - cellSysmodule.todo("cellSysmoduleSetMemcontainer(ct_id=0x%x)", ct_id); - return CELL_OK; -} - -s32 cellSysmoduleLoadModule(u16 id) -{ - cellSysmodule.warning("cellSysmoduleLoadModule(id=0x%04x: %s)", id, get_module_id(id)); - - if (!Emu.GetModuleManager().CheckModuleId(id)) - { - return CELL_SYSMODULE_ERROR_UNKNOWN; - } - - if (Module<>* m = Emu.GetModuleManager().GetModuleById(id)) - { - // CELL_SYSMODULE_ERROR_DUPLICATED shouldn't be returned - m->Load(); - } - - return CELL_OK; -} - -s32 cellSysmoduleUnloadModule(u16 id) -{ - cellSysmodule.warning("cellSysmoduleUnloadModule(id=0x%04x: %s)", id, get_module_id(id)); - - if (!Emu.GetModuleManager().CheckModuleId(id)) - { - return CELL_SYSMODULE_ERROR_UNKNOWN; - } - - if (Module<>* m = Emu.GetModuleManager().GetModuleById(id)) - { - if (!m->IsLoaded()) - { - cellSysmodule.error("cellSysmoduleUnloadModule() failed: module not loaded (id=0x%04x)", id); - return CELL_SYSMODULE_ERROR_FATAL; - } - - m->Unload(); - } - - return CELL_OK; -} - -s32 cellSysmoduleIsLoaded(u16 id) -{ - cellSysmodule.warning("cellSysmoduleIsLoaded(id=0x%04x: %s)", id, get_module_id(id)); - - if (!Emu.GetModuleManager().CheckModuleId(id)) - { - cellSysmodule.error("cellSysmoduleIsLoaded(): unknown module (id=0x%04x)", id); - return CELL_SYSMODULE_ERROR_UNKNOWN; - } - - if (Module<>* m = Emu.GetModuleManager().GetModuleById(id)) - { - if (!m->IsLoaded()) - { - cellSysmodule.warning("cellSysmoduleIsLoaded(): module not loaded (id=0x%04x)", id); - return CELL_SYSMODULE_ERROR_UNLOADED; - } - } - - return CELL_SYSMODULE_LOADED; -} - -Module<> cellSysmodule("cellSysmodule", []() -{ - REG_FUNC(cellSysmodule, cellSysmoduleInitialize); - REG_FUNC(cellSysmodule, cellSysmoduleFinalize); - REG_FUNC(cellSysmodule, cellSysmoduleSetMemcontainer); - REG_FUNC(cellSysmodule, cellSysmoduleLoadModule); - REG_FUNC(cellSysmodule, cellSysmoduleUnloadModule); - REG_FUNC(cellSysmodule, cellSysmoduleIsLoaded); -}); +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/Cell/PPUModule.h" + +LOG_CHANNEL(cellSysmodule); + +enum +{ + CELL_SYSMODULE_LOADED = CELL_OK, + CELL_SYSMODULE_ERROR_DUPLICATED = 0x80012001, + CELL_SYSMODULE_ERROR_UNKNOWN = 0x80012002, + CELL_SYSMODULE_ERROR_UNLOADED = 0x80012003, + CELL_SYSMODULE_ERROR_INVALID_MEMCONTAINER = 0x80012004, + CELL_SYSMODULE_ERROR_FATAL = 0x800120ff, +}; + +static const char* get_module_name(u16 id) +{ + switch (id) + { + case 0x0000: return "sys_net"; + case 0x0001: return "cellHttp"; + case 0x0002: return "cellHttpUtil"; + case 0x0003: return "cellSsl"; + case 0x0004: return "cellHttps"; + case 0x0005: return "libvdec"; + case 0x0006: return "cellAdec"; + case 0x0007: return "cellDmux"; + case 0x0008: return "cellVpost"; + case 0x0009: return "cellRtc"; + case 0x000a: return "cellSpurs"; + case 0x000b: return "cellOvis"; + case 0x000c: return "cellSheap"; + case 0x000d: return "cellSync"; + case 0x000e: return "sys_fs"; + case 0x000f: return "cellJpgDec"; + case 0x0010: return "cellGcmSys"; + case 0x0011: return "cellAudio"; + case 0x0012: return "cellPamf"; + case 0x0013: return "cellAtrac"; + case 0x0014: return "cellNetCtl"; + case 0x0015: return "cellSysutil"; + case 0x0016: return "sceNp"; + case 0x0017: return "sys_io"; + case 0x0018: return "cellPngDec"; + case 0x0019: return "cellFont"; + case 0x001a: return "cellFontFT"; + case 0x001b: return "cell_FreeType2"; + case 0x001c: return "cellUsbd"; + case 0x001d: return "cellSail"; + case 0x001e: return "cellL10n"; + case 0x001f: return "cellResc"; + case 0x0020: return "cellDaisy"; + case 0x0021: return "cellKey2char"; + case 0x0022: return "cellMic"; + case 0x0023: return "cellCamera"; + case 0x0024: return "cellVdecMpeg2"; + case 0x0025: return "cellVdecAvc"; + case 0x0026: return "cellAdecLpcm"; + case 0x0027: return "cellAdecAc3"; + case 0x0028: return "cellAdecAtx"; + case 0x0029: return "cellAdecAt3"; + case 0x002a: return "cellDmuxPamf"; + case 0x002b: return nullptr; + case 0x002c: return nullptr; + case 0x002d: return nullptr; + case 0x002e: return "sys_lv2dbg"; + case 0x002f: return "cellSysutilAvcExt"; + case 0x0030: return "cellUsbPspcm"; + case 0x0031: return "cellSysutilAvconfExt"; + case 0x0032: return "cellUserInfo"; + case 0x0033: return "cellSaveData"; + case 0x0034: return "cellSubDisplay"; + case 0x0035: return "cellRec"; + case 0x0036: return "cellVideoExportUtility"; + case 0x0037: return "cellGameExec"; + case 0x0038: return "sceNp2"; + case 0x0039: return "cellSysutilAp"; + case 0x003a: return "sceNpClans"; + case 0x003b: return "cellOskExtUtility"; + case 0x003c: return "cellVdecDivx"; + case 0x003d: return "cellJpgEnc"; + case 0x003e: return "cellGame"; + case 0x003f: return "cellBGDLUtility"; + case 0x0040: return "cell_FreeType2"; + case 0x0041: return "cellVideoUpload"; + case 0x0042: return "cellSysconfExtUtility"; + case 0x0043: return "cellFiber"; + case 0x0044: return "sceNpCommerce2"; + case 0x0045: return "sceNpTus"; + case 0x0046: return "cellVoice"; + case 0x0047: return "cellAdecCelp8"; + case 0x0048: return "cellCelp8Enc"; + case 0x0049: return "cellSysutilMisc"; + case 0x004a: return "cellMusicUtility"; + case 0x004e: return "cellScreenShotUtility"; + case 0x004f: return "cellMusicDecodeUtility"; + case 0x0050: return "cellSpursJq"; + case 0x0052: return "cellPngEnc"; + case 0x0053: return "cellMusicDecodeUtility"; + case 0x0055: return "cellSync2"; + case 0x0056: return "sceNpUtil"; + case 0x0057: return "cellRudp"; + case 0x0059: return "sceNpSns"; + case 0x005a: return "libgem"; + case 0xf00a: return "cellCelpEnc"; + case 0xf010: return "cellGifDec"; + case 0xf019: return "cellAdecCelp"; + case 0xf01b: return "cellAdecM2bc"; + case 0xf01d: return "cellAdecM4aac"; + case 0xf01e: return "cellAdecMp3"; + case 0xf023: return "cellImeJpUtility"; + case 0xf028: return "cellMusicUtility"; + case 0xf029: return "cellPhotoUtility"; + case 0xf02a: return "cellPrintUtility"; + case 0xf02b: return "cellPhotoImportUtil"; + case 0xf02c: return "cellMusicExportUtility"; + case 0xf02e: return "cellPhotoDecodeUtil"; + case 0xf02f: return "cellSearchUtility"; + case 0xf030: return "cellSysutilAvc2"; + case 0xf034: return "cellSailRec"; + case 0xf035: return "sceNpTrophy"; + case 0xf053: return "cellAdecAt3multi"; + case 0xf054: return "cellAtracMulti"; + } + + return nullptr; +} + +static const char* get_module_id(u16 id) +{ + thread_local static char tls_id_name[8]; // for test + + switch (id) + { + case 0x0000: return "CELL_SYSMODULE_NET"; + case 0x0001: return "CELL_SYSMODULE_HTTP"; + case 0x0002: return "CELL_SYSMODULE_HTTP_UTIL"; + case 0x0003: return "CELL_SYSMODULE_SSL"; + case 0x0004: return "CELL_SYSMODULE_HTTPS"; + case 0x0005: return "CELL_SYSMODULE_VDEC"; + case 0x0006: return "CELL_SYSMODULE_ADEC"; + case 0x0007: return "CELL_SYSMODULE_DMUX"; + case 0x0008: return "CELL_SYSMODULE_VPOST"; + case 0x0009: return "CELL_SYSMODULE_RTC"; + case 0x000a: return "CELL_SYSMODULE_SPURS"; + case 0x000b: return "CELL_SYSMODULE_OVIS"; + case 0x000c: return "CELL_SYSMODULE_SHEAP"; + case 0x000d: return "CELL_SYSMODULE_SYNC"; + case 0x000e: return "CELL_SYSMODULE_FS"; + case 0x000f: return "CELL_SYSMODULE_JPGDEC"; + case 0x0010: return "CELL_SYSMODULE_GCM_SYS"; + case 0x0011: return "CELL_SYSMODULE_AUDIO"; + case 0x0012: return "CELL_SYSMODULE_PAMF"; + case 0x0013: return "CELL_SYSMODULE_ATRAC3PLUS"; + case 0x0014: return "CELL_SYSMODULE_NETCTL"; + case 0x0015: return "CELL_SYSMODULE_SYSUTIL"; + case 0x0016: return "CELL_SYSMODULE_SYSUTIL_NP"; + case 0x0017: return "CELL_SYSMODULE_IO"; + case 0x0018: return "CELL_SYSMODULE_PNGDEC"; + case 0x0019: return "CELL_SYSMODULE_FONT"; + case 0x001a: return "CELL_SYSMODULE_FONTFT"; + case 0x001b: return "CELL_SYSMODULE_FREETYPE"; + case 0x001c: return "CELL_SYSMODULE_USBD"; + case 0x001d: return "CELL_SYSMODULE_SAIL"; + case 0x001e: return "CELL_SYSMODULE_L10N"; + case 0x001f: return "CELL_SYSMODULE_RESC"; + case 0x0020: return "CELL_SYSMODULE_DAISY"; + case 0x0021: return "CELL_SYSMODULE_KEY2CHAR"; + case 0x0022: return "CELL_SYSMODULE_MIC"; + case 0x0023: return "CELL_SYSMODULE_CAMERA"; + case 0x0024: return "CELL_SYSMODULE_VDEC_MPEG2"; + case 0x0025: return "CELL_SYSMODULE_VDEC_AVC"; + case 0x0026: return "CELL_SYSMODULE_ADEC_LPCM"; + case 0x0027: return "CELL_SYSMODULE_ADEC_AC3"; + case 0x0028: return "CELL_SYSMODULE_ADEC_ATX"; + case 0x0029: return "CELL_SYSMODULE_ADEC_AT3"; + case 0x002a: return "CELL_SYSMODULE_DMUX_PAMF"; + case 0x002b: return "CELL_SYSMODULE_VDEC_AL"; + case 0x002c: return "CELL_SYSMODULE_ADEC_AL"; + case 0x002d: return "CELL_SYSMODULE_DMUX_AL"; + case 0x002e: return "CELL_SYSMODULE_LV2DBG"; + case 0x002f: return "CELL_SYSMODULE_SYSUTIL_AVCHAT"; + case 0x0030: return "CELL_SYSMODULE_USBPSPCM"; + case 0x0031: return "CELL_SYSMODULE_AVCONF_EXT"; + case 0x0032: return "CELL_SYSMODULE_SYSUTIL_USERINFO"; + case 0x0033: return "CELL_SYSMODULE_SYSUTIL_SAVEDATA"; + case 0x0034: return "CELL_SYSMODULE_SUBDISPLAY"; + case 0x0035: return "CELL_SYSMODULE_SYSUTIL_REC"; + case 0x0036: return "CELL_SYSMODULE_VIDEO_EXPORT"; + case 0x0037: return "CELL_SYSMODULE_SYSUTIL_GAME_EXEC"; + case 0x0038: return "CELL_SYSMODULE_SYSUTIL_NP2"; + case 0x0039: return "CELL_SYSMODULE_SYSUTIL_AP"; + case 0x003a: return "CELL_SYSMODULE_SYSUTIL_NP_CLANS"; + case 0x003b: return "CELL_SYSMODULE_SYSUTIL_OSK_EXT"; + case 0x003c: return "CELL_SYSMODULE_VDEC_DIVX"; + case 0x003d: return "CELL_SYSMODULE_JPGENC"; + case 0x003e: return "CELL_SYSMODULE_SYSUTIL_GAME"; + case 0x003f: return "CELL_SYSMODULE_BGDL"; + case 0x0040: return "CELL_SYSMODULE_FREETYPE_TT"; + case 0x0041: return "CELL_SYSMODULE_SYSUTIL_VIDEO_UPLOAD"; + case 0x0042: return "CELL_SYSMODULE_SYSUTIL_SYSCONF_EXT"; + case 0x0043: return "CELL_SYSMODULE_FIBER"; + case 0x0044: return "CELL_SYSMODULE_SYSUTIL_NP_COMMERCE2"; + case 0x0045: return "CELL_SYSMODULE_SYSUTIL_NP_TUS"; + case 0x0046: return "CELL_SYSMODULE_VOICE"; + case 0x0047: return "CELL_SYSMODULE_ADEC_CELP8"; + case 0x0048: return "CELL_SYSMODULE_CELP8ENC"; + case 0x0049: return "CELL_SYSMODULE_SYSUTIL_LICENSEAREA"; + case 0x004a: return "CELL_SYSMODULE_SYSUTIL_MUSIC2"; + case 0x004e: return "CELL_SYSMODULE_SYSUTIL_SCREENSHOT"; + case 0x004f: return "CELL_SYSMODULE_SYSUTIL_MUSIC_DECODE"; + case 0x0050: return "CELL_SYSMODULE_SPURS_JQ"; + case 0x0052: return "CELL_SYSMODULE_PNGENC"; + case 0x0053: return "CELL_SYSMODULE_SYSUTIL_MUSIC_DECODE2"; + case 0x0055: return "CELL_SYSMODULE_SYNC2"; + case 0x0056: return "CELL_SYSMODULE_SYSUTIL_NP_UTIL"; + case 0x0057: return "CELL_SYSMODULE_RUDP"; + case 0x0059: return "CELL_SYSMODULE_SYSUTIL_NP_SNS"; + case 0x005a: return "CELL_SYSMODULE_GEM"; + case 0xf00a: return "CELL_SYSMODULE_CELPENC"; + case 0xf010: return "CELL_SYSMODULE_GIFDEC"; + case 0xf019: return "CELL_SYSMODULE_ADEC_CELP"; + case 0xf01b: return "CELL_SYSMODULE_ADEC_M2BC"; + case 0xf01d: return "CELL_SYSMODULE_ADEC_M4AAC"; + case 0xf01e: return "CELL_SYSMODULE_ADEC_MP3"; + case 0xf023: return "CELL_SYSMODULE_IMEJP"; + case 0xf028: return "CELL_SYSMODULE_SYSUTIL_MUSIC"; + case 0xf029: return "CELL_SYSMODULE_PHOTO_EXPORT"; + case 0xf02a: return "CELL_SYSMODULE_PRINT"; + case 0xf02b: return "CELL_SYSMODULE_PHOTO_IMPORT"; + case 0xf02c: return "CELL_SYSMODULE_MUSIC_EXPORT"; + case 0xf02e: return "CELL_SYSMODULE_PHOTO_DECODE"; + case 0xf02f: return "CELL_SYSMODULE_SYSUTIL_SEARCH"; + case 0xf030: return "CELL_SYSMODULE_SYSUTIL_AVCHAT2"; + case 0xf034: return "CELL_SYSMODULE_SAIL_REC"; + case 0xf035: return "CELL_SYSMODULE_SYSUTIL_NP_TROPHY"; + case 0xf054: return "CELL_SYSMODULE_LIBATRAC3MULTI"; + case 0xffff: return "CELL_SYSMODULE_INVALID"; + } + + std::snprintf(tls_id_name, sizeof(tls_id_name), "0x%04X", id); + return tls_id_name; +} + +s32 cellSysmoduleInitialize() +{ + cellSysmodule.warning("cellSysmoduleInitialize()"); + return CELL_OK; +} + +s32 cellSysmoduleFinalize() +{ + cellSysmodule.warning("cellSysmoduleFinalize()"); + return CELL_OK; +} + +s32 cellSysmoduleSetMemcontainer(u32 ct_id) +{ + cellSysmodule.todo("cellSysmoduleSetMemcontainer(ct_id=0x%x)", ct_id); + return CELL_OK; +} + +s32 cellSysmoduleLoadModule(u16 id) +{ + cellSysmodule.warning("cellSysmoduleLoadModule(id=%s)", get_module_id(id)); + + const auto name = get_module_name(id); + + if (!name) + { + cellSysmodule.error("cellSysmoduleLoadModule() failed: unknown module 0x%04X", id); + return CELL_SYSMODULE_ERROR_UNKNOWN; + } + + //if (Module<>* m = Emu.GetModuleManager().GetModuleById(id)) + //{ + // // CELL_SYSMODULE_ERROR_DUPLICATED shouldn't be returned + // m->Load(); + //} + + return CELL_OK; +} + +s32 cellSysmoduleUnloadModule(u16 id) +{ + cellSysmodule.warning("cellSysmoduleUnloadModule(id=%s)", get_module_id(id)); + + const auto name = get_module_name(id); + + if (!name) + { + cellSysmodule.error("cellSysmoduleUnloadModule() failed: unknown module 0x%04X", id); + return CELL_SYSMODULE_ERROR_UNKNOWN; + } + + //if (Module<>* m = Emu.GetModuleManager().GetModuleById(id)) + //{ + // if (!m->IsLoaded()) + // { + // cellSysmodule.error("cellSysmoduleUnloadModule() failed: module not loaded (id=0x%04x)", id); + // return CELL_SYSMODULE_ERROR_FATAL; + // } + + // m->Unload(); + //} + + return CELL_OK; +} + +s32 cellSysmoduleIsLoaded(u16 id) +{ + cellSysmodule.warning("cellSysmoduleIsLoaded(id=%s)", get_module_id(id)); + + const auto name = get_module_name(id); + + if (!name) + { + cellSysmodule.error("cellSysmoduleIsLoaded() failed: unknown module 0x%04X", id); + return CELL_SYSMODULE_ERROR_UNKNOWN; + } + + //if (Module<>* m = Emu.GetModuleManager().GetModuleById(id)) + //{ + // if (!m->IsLoaded()) + // { + // cellSysmodule.warning("cellSysmoduleIsLoaded(): module not loaded (id=0x%04x)", id); + // return CELL_SYSMODULE_ERROR_UNLOADED; + // } + //} + + return CELL_SYSMODULE_LOADED; +} + +s32 cellSysmoduleGetImagesize() +{ + UNIMPLEMENTED_FUNC(cellSysmodule); + return CELL_OK; +} + +s32 cellSysmoduleFetchImage() +{ + UNIMPLEMENTED_FUNC(cellSysmodule); + return CELL_OK; +} + +DECLARE(ppu_module_manager::cellSysmodule)("cellSysmodule", []() +{ + REG_FUNC(cellSysmodule, cellSysmoduleInitialize); + REG_FUNC(cellSysmodule, cellSysmoduleFinalize); + REG_FUNC(cellSysmodule, cellSysmoduleSetMemcontainer); + REG_FUNC(cellSysmodule, cellSysmoduleLoadModule); + REG_FUNC(cellSysmodule, cellSysmoduleUnloadModule); + REG_FUNC(cellSysmodule, cellSysmoduleIsLoaded); + REG_FUNC(cellSysmodule, cellSysmoduleGetImagesize); + REG_FUNC(cellSysmodule, cellSysmoduleFetchImage); +}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/Cell/Modules/cellSysutil.cpp similarity index 76% rename from rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp rename to rpcs3/Emu/Cell/Modules/cellSysutil.cpp index 048dd4625c..ecf5c77899 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysutil.cpp @@ -1,19 +1,60 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/state.h" -#include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/IdManager.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/FS/VFS.h" #include "cellSysutil.h" -extern Module<> cellSysutil; +LOG_CHANNEL(cellSysutil); -std::unique_ptr g_sysutil; +// Temporarily +using sys_callbacks_t = std::array, vm::ptr>, 4>; -const char* get_systemparam_id_name(s32 id) +void sysutilSendSystemCommand(u64 status, u64 param) { + if (const auto g_sys_callback = fxm::get()) + { + for (auto& cb : *g_sys_callback) + { + if (cb.first) + { + Emu.GetCallbackManager().Register([=](PPUThread& ppu) -> s32 + { + // TODO: check it and find the source of the return value (void isn't equal to CELL_OK) + cb.first(ppu, status, param, cb.second); + return CELL_OK; + }); + } + } + } +} + +cfg::map_entry g_cfg_sys_language(cfg::root.sys, "Language", +{ + { "Japanese", CELL_SYSUTIL_LANG_JAPANESE }, + { "English (US)", CELL_SYSUTIL_LANG_ENGLISH_US }, + { "French", CELL_SYSUTIL_LANG_FRENCH }, + { "Spanish", CELL_SYSUTIL_LANG_SPANISH }, + { "German", CELL_SYSUTIL_LANG_GERMAN }, + { "Italian", CELL_SYSUTIL_LANG_ITALIAN }, + { "Dutch", CELL_SYSUTIL_LANG_DUTCH }, + { "Portuguese (PT)", CELL_SYSUTIL_LANG_PORTUGUESE_PT }, + { "Russian", CELL_SYSUTIL_LANG_RUSSIAN }, + { "Korean", CELL_SYSUTIL_LANG_KOREAN }, + { "Chinese (Trad.)", CELL_SYSUTIL_LANG_CHINESE_T }, + { "Chinese (Simp.)", CELL_SYSUTIL_LANG_CHINESE_S }, + { "Finnish", CELL_SYSUTIL_LANG_FINNISH }, + { "Swedish", CELL_SYSUTIL_LANG_SWEDISH }, + { "Danish", CELL_SYSUTIL_LANG_DANISH }, + { "Norwegian", CELL_SYSUTIL_LANG_NORWEGIAN }, + { "Polish", CELL_SYSUTIL_LANG_POLISH }, + { "English (UK)", CELL_SYSUTIL_LANG_ENGLISH_GB }, +}); + +static const char* get_systemparam_id_name(s32 id) +{ + thread_local static char tls_id_name[16]; // for test + switch (id) { case CELL_SYSUTIL_SYSTEMPARAM_ID_LANG: return "ID_LANG"; @@ -33,18 +74,22 @@ const char* get_systemparam_id_name(s32 id) case CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF: return "ID_PAD_AUTOOFF"; case CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME: return "ID_NICKNAME"; case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME: return "ID_CURRENT_USERNAME"; - default: return "???"; } + + std::snprintf(tls_id_name, sizeof(tls_id_name), "0x%04X", id); + return tls_id_name; } s32 cellSysutilGetSystemParamInt(s32 id, vm::ptr value) { - cellSysutil.warning("cellSysutilGetSystemParamInt(id=0x%x(%s), value=*0x%x)", id, get_systemparam_id_name(id), value); + cellSysutil.warning("cellSysutilGetSystemParamInt(id=%s, value=*0x%x)", get_systemparam_id_name(id), value); + + // TODO: load this information from config (preferably "sys/" group) switch(id) { case CELL_SYSUTIL_SYSTEMPARAM_ID_LANG: - *value = rpcs3::config.system.language.value(); + *value = g_cfg_sys_language.get(); break; case CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN: @@ -133,29 +178,6 @@ s32 cellSysutilGetSystemParamString(s32 id, vm::ptr buf, u32 bufsize) return CELL_OK; } -struct sys_callback -{ - vm::ptr func; - vm::ptr arg; -} -g_sys_callback[4]; - -void sysutilSendSystemCommand(u64 status, u64 param) -{ - // TODO: check it and find the source of the return value (void isn't equal to CELL_OK) - for (auto& cb : g_sys_callback) - { - if (cb.func) - { - Emu.GetCallbackManager().Register([=](PPUThread& ppu) -> s32 - { - cb.func(ppu, status, param, cb.arg); - return CELL_OK; - }); - } - } -} - s32 cellSysutilCheckCallback(PPUThread& CPU) { cellSysutil.trace("cellSysutilCheckCallback()"); @@ -177,27 +199,25 @@ s32 cellSysutilRegisterCallback(s32 slot, vm::ptr func, vm: { cellSysutil.warning("cellSysutilRegisterCallback(slot=%d, func=*0x%x, userdata=*0x%x)", slot, func, userdata); - if ((u32)slot > 3) + if (slot >= sys_callbacks_t{}.size()) { return CELL_SYSUTIL_ERROR_VALUE; } - g_sys_callback[slot].func = func; - g_sys_callback[slot].arg = userdata; + fxm::get_always()->at(slot) = std::make_pair(func, userdata); return CELL_OK; } -s32 cellSysutilUnregisterCallback(s32 slot) +s32 cellSysutilUnregisterCallback(u32 slot) { cellSysutil.warning("cellSysutilUnregisterCallback(slot=%d)", slot); - if ((u32)slot > 3) + if (slot >= sys_callbacks_t{}.size()) { return CELL_SYSUTIL_ERROR_VALUE; } - g_sys_callback[slot].func.set(0); - g_sys_callback[slot].arg.set(0); + fxm::get_always()->at(slot) = std::make_pair(vm::null, vm::null); return CELL_OK; } @@ -205,13 +225,12 @@ s32 cellSysCacheClear(void) { cellSysutil.todo("cellSysCacheClear()"); - if (!g_sysutil->cacheMounted) + if (!fxm::check()) { return CELL_SYSCACHE_ERROR_NOTMOUNTED; } - std::string localPath; - Emu.GetVFS().GetDevice("/dev_hdd1/cache/", localPath); + const std::string& local_path = vfs::get("/dev_hdd1/cache/"); // TODO: Write tests to figure out, what is deleted. @@ -222,13 +241,15 @@ s32 cellSysCacheMount(vm::ptr param) { cellSysutil.warning("cellSysCacheMount(param=*0x%x)", param); - // TODO: implement - char id[CELL_SYSCACHE_ID_SIZE] = { '\0' }; - strncpy(id, param->cacheId, CELL_SYSCACHE_ID_SIZE - 1); - strncpy(param->getCachePath, ("/dev_hdd1/cache/"s + id + "/").c_str(), CELL_SYSCACHE_PATH_MAX); - param->getCachePath[CELL_SYSCACHE_PATH_MAX - 1] = '\0'; - Emu.GetVFS().CreateDir(param->getCachePath); - g_sysutil->cacheMounted.exchange(true); + const std::string& cache_id = param->cacheId; + ASSERT(cache_id.size() < sizeof(param->cacheId)); + + const std::string& cache_path = "/dev_hdd1/cache/" + cache_id + '/'; + strcpy_trunc(param->getCachePath, cache_path); + + // TODO: implement (what?) + fs::create_dir(vfs::get(cache_path)); + fxm::make_always(*param); return CELL_SYSCACHE_RET_OK_RELAYED; } @@ -302,7 +323,8 @@ s32 cellSysutilGetBgmPlaybackStatus2(vm::ptr stat s32 cellSysutilSetBgmPlaybackExtraParam() { - throw EXCEPTION(""); + cellSysutil.todo("cellSysutilSetBgmPlaybackExtraParam()"); + return CELL_OK; } s32 cellSysutilRegisterCallbackDispatcher() @@ -351,16 +373,8 @@ extern void cellSysutil_WebBrowser_init(); extern void cellSysutil_AudioOut_init(); extern void cellSysutil_VideoOut_init(); -Module<> cellSysutil("cellSysutil", []() +DECLARE(ppu_module_manager::cellSysutil)("cellSysutil", []() { - g_sysutil = std::make_unique(); - - for (auto& v : g_sys_callback) - { - v.func.set(0); - v.arg.set(0); - } - cellSysutil_SaveData_init(); // cellSaveData functions cellSysutil_GameData_init(); // cellGameData, cellHddGame functions cellSysutil_MsgDialog_init(); // cellMsgDialog functions diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h b/rpcs3/Emu/Cell/Modules/cellSysutil.h similarity index 97% rename from rpcs3/Emu/SysCalls/Modules/cellSysutil.h rename to rpcs3/Emu/Cell/Modules/cellSysutil.h index 1018ba4d89..69d9c2917d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h +++ b/rpcs3/Emu/Cell/Modules/cellSysutil.h @@ -82,8 +82,6 @@ enum using CellSysutilCallback = void(u64 status, u64 param, vm::ptr userdata); -void sysutilSendSystemCommand(u64 status, u64 param); - enum { CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE = 0, @@ -197,7 +195,4 @@ struct CellSysCacheParam vm::ptr reserved; }; -struct sysutil_t -{ - std::atomic cacheMounted{ false }; -}; +extern void sysutilSendSystemCommand(u64 status, u64 param); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutilAp.cpp b/rpcs3/Emu/Cell/Modules/cellSysutilAp.cpp similarity index 87% rename from rpcs3/Emu/SysCalls/Modules/cellSysutilAp.cpp rename to rpcs3/Emu/Cell/Modules/cellSysutilAp.cpp index b2d3947b8d..f8c6d1668f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutilAp.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysutilAp.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellSysutilAp; +LOG_CHANNEL(cellSysutilAp); // Return Codes enum @@ -35,7 +34,7 @@ s32 cellSysutilApOff() return CELL_OK; } -Module<> cellSysutilAp("cellSysutilAp", []() +DECLARE(ppu_module_manager::cellSysutilAp)("cellSysutilAp", []() { REG_FUNC(cellSysutilAp, cellSysutilApGetRequiredMemSize); REG_FUNC(cellSysutilAp, cellSysutilApOn); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutilAvc.cpp b/rpcs3/Emu/Cell/Modules/cellSysutilAvc.cpp similarity index 96% rename from rpcs3/Emu/SysCalls/Modules/cellSysutilAvc.cpp rename to rpcs3/Emu/Cell/Modules/cellSysutilAvc.cpp index b6d132419b..24b78da7b4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutilAvc.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysutilAvc.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellSysutilAvc; +LOG_CHANNEL(cellSysutilAvc); s32 cellSysutilAvcByeRequest() { @@ -218,8 +217,6 @@ s32 cellSysutilAvcExtGetWindowShowStatus() void cellSysutil_SysutilAvc_init() { - extern Module<> cellSysutil; - REG_FUNC(cellSysutil, cellSysutilAvcByeRequest); REG_FUNC(cellSysutil, cellSysutilAvcCancelByeRequest); REG_FUNC(cellSysutil, cellSysutilAvcCancelJoinRequest); @@ -242,7 +239,7 @@ void cellSysutil_SysutilAvc_init() REG_FUNC(cellSysutil, cellSysutilAvcUnloadAsync); } -Module<> cellSysutilAvc("cellSysutilAvc", []() +DECLARE(ppu_module_manager::cellSysutilAvc)("cellSysutilAvc", []() { REG_FUNC(cellSysutilAvc, cellSysutilAvcExtInitOptionParam); REG_FUNC(cellSysutilAvc, cellSysutilAvcExtSetHideNamePlate); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutilAvc2.cpp b/rpcs3/Emu/Cell/Modules/cellSysutilAvc2.cpp similarity index 94% rename from rpcs3/Emu/SysCalls/Modules/cellSysutilAvc2.cpp rename to rpcs3/Emu/Cell/Modules/cellSysutilAvc2.cpp index 97cfb7cb29..c88ffd32d5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutilAvc2.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysutilAvc2.cpp @@ -1,13 +1,11 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" -#include "Emu/state.h" +#include "Emu/Cell/PPUModule.h" #include "sceNp.h" #include "sceNp2.h" #include "cellSysutilAvc2.h" -extern Module<> cellSysutilAvc2; +LOG_CHANNEL(cellSysutilAvc2); s32 cellSysutilAvc2GetPlayerInfo() { @@ -133,16 +131,7 @@ s32 cellSysutilAvc2IsCameraAttached(vm::ptr status) { cellSysutilAvc2.todo("cellSysutilAvc2IsCameraAttached()"); - if (rpcs3::config.io.camera.value() == io_camera_state::null) - { - *status = CELL_AVC2_CAMERA_STATUS_DETACHED; - } - else - { - // TODO: We need to check if the camera has been turned on, but this requires further implementation of cellGem/cellCamera. - *status = CELL_AVC2_CAMERA_STATUS_ATTACHED_OFF; - } - + *status = CELL_AVC2_CAMERA_STATUS_DETACHED; return CELL_OK; } @@ -334,7 +323,7 @@ s32 cellSysutilAvc2GetWindowPosition() } -Module<> cellSysutilAvc2("cellSysutilAvc2", []() +DECLARE(ppu_module_manager::cellSysutilAvc2)("cellSysutilAvc2", []() { REG_FUNC(cellSysutilAvc2, cellSysutilAvc2GetPlayerInfo); REG_FUNC(cellSysutilAvc2, cellSysutilAvc2JoinChat); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutilAvc2.h b/rpcs3/Emu/Cell/Modules/cellSysutilAvc2.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellSysutilAvc2.h rename to rpcs3/Emu/Cell/Modules/cellSysutilAvc2.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutilMisc.cpp b/rpcs3/Emu/Cell/Modules/cellSysutilMisc.cpp similarity index 86% rename from rpcs3/Emu/SysCalls/Modules/cellSysutilMisc.cpp rename to rpcs3/Emu/Cell/Modules/cellSysutilMisc.cpp index d93bba7751..e009f8e0bc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutilMisc.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysutilMisc.cpp @@ -1,9 +1,8 @@ #include "stdafx.h" #include "Emu/System.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellSysutilMisc; +LOG_CHANNEL(cellSysutilMisc); // License areas enum @@ -33,7 +32,7 @@ s32 cellSysutilGetLicenseArea() } } -Module<> cellSysutilMisc("cellSysutilMisc", []() +DECLARE(ppu_module_manager::cellSysutilMisc)("cellSysutilMisc", []() { REG_FUNC(cellSysutilMisc, cellSysutilGetLicenseArea); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellUsbd.cpp b/rpcs3/Emu/Cell/Modules/cellUsbd.cpp similarity index 96% rename from rpcs3/Emu/SysCalls/Modules/cellUsbd.cpp rename to rpcs3/Emu/Cell/Modules/cellUsbd.cpp index bcd3476fc4..607277c74e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellUsbd.cpp +++ b/rpcs3/Emu/Cell/Modules/cellUsbd.cpp @@ -1,10 +1,9 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellUsbd.h" -extern Module<> cellUsbd; +LOG_CHANNEL(cellUsbd); s32 cellUsbdInit() { @@ -152,7 +151,7 @@ s32 cellUsbdFreeMemory() return CELL_OK; } -Module<> cellUsbd("cellUsbd", []() +DECLARE(ppu_module_manager::cellUsbd)("cellUsbd", []() { REG_FUNC(cellUsbd, cellUsbdInit); REG_FUNC(cellUsbd, cellUsbdEnd); diff --git a/rpcs3/Emu/SysCalls/Modules/cellUsbd.h b/rpcs3/Emu/Cell/Modules/cellUsbd.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellUsbd.h rename to rpcs3/Emu/Cell/Modules/cellUsbd.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellUsbpspcm.cpp b/rpcs3/Emu/Cell/Modules/cellUsbpspcm.cpp similarity index 96% rename from rpcs3/Emu/SysCalls/Modules/cellUsbpspcm.cpp rename to rpcs3/Emu/Cell/Modules/cellUsbpspcm.cpp index 30a9fe71d1..ccd4cae8bb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellUsbpspcm.cpp +++ b/rpcs3/Emu/Cell/Modules/cellUsbpspcm.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellUsbPspcm; +LOG_CHANNEL(cellUsbPspcm); // Return Codes enum @@ -183,7 +182,7 @@ s32 cellUsbPspcmCancelWaitData() return CELL_OK; } -Module<> cellUsbPspcm("cellUsbPspcm", []() +DECLARE(ppu_module_manager::cellUsbPspcm)("cellUsbPspcm", []() { REG_FUNC(cellUsbPspcm, cellUsbPspcmInit); REG_FUNC(cellUsbPspcm, cellUsbPspcmEnd); diff --git a/rpcs3/Emu/SysCalls/Modules/cellUserInfo.cpp b/rpcs3/Emu/Cell/Modules/cellUserInfo.cpp similarity index 69% rename from rpcs3/Emu/SysCalls/Modules/cellUserInfo.cpp rename to rpcs3/Emu/Cell/Modules/cellUserInfo.cpp index a868720f4e..facf4365aa 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellUserInfo.cpp +++ b/rpcs3/Emu/Cell/Modules/cellUserInfo.cpp @@ -1,13 +1,10 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -#include "Emu/FS/VFS.h" -#include "Emu/FS/vfsFileBase.h" #include "cellUserInfo.h" -extern Module<> cellUserInfo; +LOG_CHANNEL(cellUserInfo); s32 cellUserInfoGetStat(u32 id, vm::ptr stat) { @@ -22,24 +19,16 @@ s32 cellUserInfoGetStat(u32 id, vm::ptr stat) id = 1; } - char path[256]; - sprintf(path, "/dev_hdd0/home/%08d", id); - if (!Emu.GetVFS().ExistsDir(path)) + const std::string& path = vfs::get(fmt::format("/dev_hdd0/home/%08d/", id)); + if (!fs::is_dir(path)) return CELL_USERINFO_ERROR_NOUSER; - sprintf(path, "/dev_hdd0/home/%08d/localusername", id); - vfsStream* stream = Emu.GetVFS().OpenFile(path, fom::read); - if (!stream || !(stream->IsOpened())) + const fs::file f(path + "localusername"); + if (!f) return CELL_USERINFO_ERROR_INTERNAL; - char name [CELL_USERINFO_USERNAME_SIZE]; - memset(name, 0, CELL_USERINFO_USERNAME_SIZE); - stream->Read(name, CELL_USERINFO_USERNAME_SIZE); - stream->Close(); - delete stream; - stat->id = id; - memcpy(stat->name, name, CELL_USERINFO_USERNAME_SIZE); + strcpy_trunc(stat->name, f.to_string()); return CELL_OK; } @@ -79,7 +68,7 @@ s32 cellUserInfoGetList(vm::ptr listNum, vm::ptr list return CELL_OK; } -Module<> cellUserInfo("cellUserInfo", []() +DECLARE(ppu_module_manager::cellUserInfo)("cellUserInfo", []() { REG_FUNC(cellUserInfo, cellUserInfoGetStat); REG_FUNC(cellUserInfo, cellUserInfoSelectUser_ListType); diff --git a/rpcs3/Emu/SysCalls/Modules/cellUserInfo.h b/rpcs3/Emu/Cell/Modules/cellUserInfo.h similarity index 73% rename from rpcs3/Emu/SysCalls/Modules/cellUserInfo.h rename to rpcs3/Emu/Cell/Modules/cellUserInfo.h index a06391519c..a9a77159c0 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellUserInfo.h +++ b/rpcs3/Emu/Cell/Modules/cellUserInfo.h @@ -21,7 +21,7 @@ enum CellUserInfoParamSize CELL_USERINFO_USERNAME_SIZE = 64, }; -enum CellUserInfoListType +enum CellUserInfoListType { CELL_USERINFO_LISTTYPE_ALL = 0, CELL_USERINFO_LISTTYPE_NOCURRENT = 1, @@ -37,7 +37,7 @@ enum struct CellUserInfoUserStat { be_t id; - u8 name[CELL_USERINFO_USERNAME_SIZE]; + char name[CELL_USERINFO_USERNAME_SIZE]; }; struct CellUserInfoUserList @@ -47,17 +47,17 @@ struct CellUserInfoUserList struct CellUserInfoListSet { - be_t title_addr; // (char*) - be_t focus; + vm::bptr title; + be_t focus; // id be_t fixedListNum; - vm::ptr fixedList; - be_t reserved_addr; // (void*) + vm::bptr fixedList; + vm::bptr reserved; }; struct CellUserInfoTypeSet { - be_t title_addr; // (char*) - be_t focus; - CellUserInfoListType type; - be_t reserved_addr; // (void*) + vm::bptr title; + be_t focus; // id + be_t type; // CellUserInfoListType + vm::bptr reserved; }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/Cell/Modules/cellVdec.cpp similarity index 96% rename from rpcs3/Emu/SysCalls/Modules/cellVdec.cpp rename to rpcs3/Emu/Cell/Modules/cellVdec.cpp index 34e06c726f..92f33a2d66 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellVdec.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" std::mutex g_mutex_avcodec_open2; @@ -17,7 +16,9 @@ extern "C" #include "cellPamf.h" #include "cellVdec.h" -extern Module<> cellVdec; +LOG_CHANNEL(cellVdec); + +vm::gvar _cell_vdec_prx_ver; // ??? VideoDecoder::VideoDecoder(s32 type, u32 profile, u32 addr, u32 size, vm::ptr func, u32 arg) : type(type) @@ -538,8 +539,9 @@ void vdecOpen(u32 vdec_id) // TODO: call from the constructor vdec.is_finished = true; }; - vdec.vdecCb->run(); - vdec.vdecCb->exec(); + vdec.vdecCb->cpu_init(); + vdec.vdecCb->state -= cpu_state::stop; + vdec.vdecCb->safe_notify(); } s32 cellVdecQueryAttr(vm::cptr type, vm::ptr attr) @@ -595,7 +597,7 @@ s32 cellVdecClose(u32 handle) std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack } - idm::remove(vdec->vdecCb->get_id()); + idm::remove(vdec->vdecCb->id); idm::remove(handle); return CELL_OK; } @@ -948,24 +950,24 @@ s32 cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc) return CELL_OK; } -Module<> cellVdec("cellVdec", []() +DECLARE(ppu_module_manager::cellVdec)("libvdec", []() { - //REG_VARIABLE(cellVdec, _cell_vdec_prx_ver); // 0x085a7ecb + REG_VAR(libvdec, _cell_vdec_prx_ver); // 0x085a7ecb - REG_FUNC(cellVdec, cellVdecQueryAttr); - REG_FUNC(cellVdec, cellVdecQueryAttrEx); - REG_FUNC(cellVdec, cellVdecOpen); - REG_FUNC(cellVdec, cellVdecOpenEx); - //REG_FUNC(cellVdec, cellVdecOpenExt); // 0xef4d8ad7 - REG_FUNC(cellVdec, cellVdecClose); - REG_FUNC(cellVdec, cellVdecStartSeq); - //REG_FUNC(cellVdec, cellVdecStartSeqExt); // 0xebb8e70a - REG_FUNC(cellVdec, cellVdecEndSeq); - REG_FUNC(cellVdec, cellVdecDecodeAu); - REG_FUNC(cellVdec, cellVdecGetPicture); - REG_FUNC(cellVdec, cellVdecGetPictureExt); // 0xa21aa896 - REG_FUNC(cellVdec, cellVdecGetPicItem); - //REG_FUNC(cellVdec, cellVdecGetPicItemExt); // 0x2cbd9806 - REG_FUNC(cellVdec, cellVdecSetFrameRate); - //REG_FUNC(cellVdec, cellVdecSetFrameRateExt); // 0xcffc42a5 + REG_FUNC(libvdec, cellVdecQueryAttr); + REG_FUNC(libvdec, cellVdecQueryAttrEx); + REG_FUNC(libvdec, cellVdecOpen); + REG_FUNC(libvdec, cellVdecOpenEx); + //REG_FUNC(libvdec, cellVdecOpenExt); // 0xef4d8ad7 + REG_FUNC(libvdec, cellVdecClose); + REG_FUNC(libvdec, cellVdecStartSeq); + //REG_FUNC(libvdec, cellVdecStartSeqExt); // 0xebb8e70a + REG_FUNC(libvdec, cellVdecEndSeq); + REG_FUNC(libvdec, cellVdecDecodeAu); + REG_FUNC(libvdec, cellVdecGetPicture); + REG_FUNC(libvdec, cellVdecGetPictureExt); // 0xa21aa896 + REG_FUNC(libvdec, cellVdecGetPicItem); + //REG_FUNC(libvdec, cellVdecGetPicItemExt); // 0x2cbd9806 + REG_FUNC(libvdec, cellVdecSetFrameRate); + //REG_FUNC(libvdec, cellVdecSetFrameRateExt); // 0xcffc42a5 }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/Cell/Modules/cellVdec.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellVdec.h rename to rpcs3/Emu/Cell/Modules/cellVdec.h diff --git a/rpcs3/Emu/Cell/Modules/cellVideoExport.cpp b/rpcs3/Emu/Cell/Modules/cellVideoExport.cpp new file mode 100644 index 0000000000..266d8abc45 --- /dev/null +++ b/rpcs3/Emu/Cell/Modules/cellVideoExport.cpp @@ -0,0 +1,45 @@ +#include "stdafx.h" +#include "Emu/Cell/PPUModule.h" + +LOG_CHANNEL(cellVideoExport); + +s32 cellVideoExportProgress() +{ + throw EXCEPTION(""); +} + +s32 cellVideoExportInitialize2() +{ + throw EXCEPTION(""); +} + +s32 cellVideoExportInitialize() +{ + throw EXCEPTION(""); +} + +s32 cellVideoExportFromFileWithCopy() +{ + throw EXCEPTION(""); +} + +s32 cellVideoExportFromFile() +{ + throw EXCEPTION(""); +} + +s32 cellVideoExportFinalize() +{ + throw EXCEPTION(""); +} + + +DECLARE(ppu_module_manager::cellVideoExport)("cellVideoExportUtility", []() +{ + REG_FUNC(cellVideoExportUtility, cellVideoExportProgress); + REG_FUNC(cellVideoExportUtility, cellVideoExportInitialize2); + REG_FUNC(cellVideoExportUtility, cellVideoExportInitialize); + REG_FUNC(cellVideoExportUtility, cellVideoExportFromFileWithCopy); + REG_FUNC(cellVideoExportUtility, cellVideoExportFromFile); + REG_FUNC(cellVideoExportUtility, cellVideoExportFinalize); +}); diff --git a/rpcs3/Emu/Cell/Modules/cellVideoOut.cpp b/rpcs3/Emu/Cell/Modules/cellVideoOut.cpp new file mode 100644 index 0000000000..c3fd404652 --- /dev/null +++ b/rpcs3/Emu/Cell/Modules/cellVideoOut.cpp @@ -0,0 +1,239 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/Cell/PPUModule.h" + +#include "cellVideoOut.h" + +extern _log::channel cellSysutil; + +cfg::map_entry g_cfg_video_out_resolution(cfg::root.video, "Resolution", "1280x720", +{ + { "1920x1080", CELL_VIDEO_OUT_RESOLUTION_1080 }, + { "1280x720", CELL_VIDEO_OUT_RESOLUTION_720 }, + { "720x480", CELL_VIDEO_OUT_RESOLUTION_480 }, + { "720x576", CELL_VIDEO_OUT_RESOLUTION_576 }, + { "1600x1080", CELL_VIDEO_OUT_RESOLUTION_1600x1080 }, + { "1440x1080", CELL_VIDEO_OUT_RESOLUTION_1440x1080 }, + { "1280x1080", CELL_VIDEO_OUT_RESOLUTION_1280x1080 }, + { "960x1080", CELL_VIDEO_OUT_RESOLUTION_960x1080 }, +}); + +cfg::map_entry g_cfg_video_out_aspect_ratio(cfg::root.video, "Aspect ratio", "16x9", +{ + { "4x3", CELL_VIDEO_OUT_ASPECT_4_3 }, + { "16x9", CELL_VIDEO_OUT_ASPECT_16_9 }, +}); + +const extern std::unordered_map g_video_out_resolution_map +{ + { CELL_VIDEO_OUT_RESOLUTION_1080, { 1920, 1080 } }, + { CELL_VIDEO_OUT_RESOLUTION_720, { 1280, 720 } }, + { CELL_VIDEO_OUT_RESOLUTION_480, { 720, 480 } }, + { CELL_VIDEO_OUT_RESOLUTION_576, { 720, 576 } }, + { CELL_VIDEO_OUT_RESOLUTION_1600x1080, { 1600, 1080 } }, + { CELL_VIDEO_OUT_RESOLUTION_1440x1080, { 1440, 1080 } }, + { CELL_VIDEO_OUT_RESOLUTION_1280x1080, { 1280, 1080 } }, + { CELL_VIDEO_OUT_RESOLUTION_960x1080, { 960, 1080 } }, +}; + +ppu_error_code cellVideoOutGetState(u32 videoOut, u32 deviceIndex, vm::ptr state) +{ + cellSysutil.trace("cellVideoOutGetState(videoOut=%d, deviceIndex=%d, state=*0x%x)", videoOut, deviceIndex, state); + + if (deviceIndex) return CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND; + + switch (videoOut) + { + case CELL_VIDEO_OUT_PRIMARY: + state->state = CELL_VIDEO_OUT_OUTPUT_STATE_ENABLED; + state->colorSpace = CELL_VIDEO_OUT_COLOR_SPACE_RGB; + state->displayMode.resolutionId = g_cfg_video_out_resolution.get(); // TODO + state->displayMode.scanMode = CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE; + state->displayMode.conversion = CELL_VIDEO_OUT_DISPLAY_CONVERSION_NONE; + state->displayMode.aspect = g_cfg_video_out_aspect_ratio.get(); // TODO + state->displayMode.refreshRates = CELL_VIDEO_OUT_REFRESH_RATE_59_94HZ; + return CELL_OK; + + case CELL_VIDEO_OUT_SECONDARY: + *state = { CELL_VIDEO_OUT_OUTPUT_STATE_DISABLED }; // ??? + return CELL_OK; + } + + return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; +} + +ppu_error_code cellVideoOutGetResolution(u32 resolutionId, vm::ptr resolution) +{ + cellSysutil.trace("cellVideoOutGetResolution(resolutionId=0x%x, resolution=*0x%x)", resolutionId, resolution); + + if (!resolution) + { + return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER; + } + + switch (resolutionId) + { + case 0x01: *resolution = { 0x780, 0x438 }; break; + case 0x02: *resolution = { 0x500, 0x2d0 }; break; + case 0x04: *resolution = { 0x2d0, 0x1e0 }; break; + case 0x05: *resolution = { 0x2d0, 0x240 }; break; + case 0x0a: *resolution = { 0x640, 0x438 }; break; + case 0x0b: *resolution = { 0x5a0, 0x438 }; break; + case 0x0c: *resolution = { 0x500, 0x438 }; break; + case 0x0d: *resolution = { 0x3c0, 0x438 }; break; + case 0x64: *resolution = { 0x550, 0x300 }; break; + case 0x81: *resolution = { 0x500, 0x5be }; break; + case 0x82: *resolution = { 0x780, 0x438 }; break; + case 0x83: *resolution = { 0x780, 0x89d }; break; + case 0x8b: *resolution = { 0x280, 0x5be }; break; + case 0x8a: *resolution = { 0x320, 0x5be }; break; + case 0x89: *resolution = { 0x3c0, 0x5be }; break; + case 0x88: *resolution = { 0x400, 0x5be }; break; + case 0x91: *resolution = { 0x500, 0x5be }; break; + case 0x92: *resolution = { 0x780, 0x438 }; break; + case 0x9b: *resolution = { 0x280, 0x5be }; break; + case 0x9a: *resolution = { 0x320, 0x5be }; break; + case 0x99: *resolution = { 0x3c0, 0x5be }; break; + case 0x98: *resolution = { 0x400, 0x5be }; break; + case 0xa1: *resolution = { 0x780, 0x438 }; break; + + default: return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER; + } + + return CELL_OK; +} + +ppu_error_code cellVideoOutConfigure(u32 videoOut, vm::ptr config, vm::ptr option, u32 waitForEvent) +{ + cellSysutil.warning("cellVideoOutConfigure(videoOut=%d, config=*0x%x, option=*0x%x, waitForEvent=%d)", videoOut, config, option, waitForEvent); + + switch (videoOut) + { + case CELL_VIDEO_OUT_PRIMARY: + // TODO + return CELL_OK; + + case CELL_VIDEO_OUT_SECONDARY: + return CELL_OK; + } + + return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; +} + +ppu_error_code cellVideoOutGetConfiguration(u32 videoOut, vm::ptr config, vm::ptr option) +{ + cellSysutil.warning("cellVideoOutGetConfiguration(videoOut=%d, config=*0x%x, option=*0x%x)", videoOut, config, option); + + if (option) *option = {}; + *config = {}; + + switch (videoOut) + { + case CELL_VIDEO_OUT_PRIMARY: + config->resolutionId = g_cfg_video_out_resolution.get(); + config->format = CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8; + config->aspect = g_cfg_video_out_aspect_ratio.get(); + config->pitch = 4 * g_video_out_resolution_map.at(g_cfg_video_out_resolution.get()).width; + + return CELL_OK; + + case CELL_VIDEO_OUT_SECONDARY: + + return CELL_OK; + } + + return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; +} + +ppu_error_code cellVideoOutGetDeviceInfo(u32 videoOut, u32 deviceIndex, vm::ptr info) +{ + cellSysutil.warning("cellVideoOutGetDeviceInfo(videoOut=%d, deviceIndex=%d, info=*0x%x)", videoOut, deviceIndex, info); + + if (deviceIndex) return CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND; + + // Use standard dummy values for now. + info->portType = CELL_VIDEO_OUT_PORT_HDMI; + info->colorSpace = CELL_VIDEO_OUT_COLOR_SPACE_RGB; + info->latency = 1000; + info->availableModeCount = 1; + info->state = CELL_VIDEO_OUT_DEVICE_STATE_AVAILABLE; + info->rgbOutputRange = 1; + info->colorInfo.blueX = 0xFFFF; + info->colorInfo.blueY = 0xFFFF; + info->colorInfo.greenX = 0xFFFF; + info->colorInfo.greenY = 0xFFFF; + info->colorInfo.redX = 0xFFFF; + info->colorInfo.redY = 0xFFFF; + info->colorInfo.whiteX = 0xFFFF; + info->colorInfo.whiteY = 0xFFFF; + info->colorInfo.gamma = 100; + info->availableModes[0].aspect = 0; + info->availableModes[0].conversion = 0; + info->availableModes[0].refreshRates = 0xF; + info->availableModes[0].resolutionId = 1; + info->availableModes[0].scanMode = 0; + + return CELL_OK; +} + +ppu_error_code cellVideoOutGetNumberOfDevice(u32 videoOut) +{ + cellSysutil.warning("cellVideoOutGetNumberOfDevice(videoOut=%d)", videoOut); + + switch (videoOut) + { + case CELL_VIDEO_OUT_PRIMARY: return NOT_AN_ERROR(1); + case CELL_VIDEO_OUT_SECONDARY: return NOT_AN_ERROR(0); + } + + return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; +} + +ppu_error_code cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 aspect, u32 option) +{ + cellSysutil.warning("cellVideoOutGetResolutionAvailability(videoOut=%d, resolutionId=0x%x, aspect=%d, option=%d)", videoOut, resolutionId, aspect, option); + + switch (videoOut) + { + case CELL_VIDEO_OUT_PRIMARY: return NOT_AN_ERROR(1); + case CELL_VIDEO_OUT_SECONDARY: return NOT_AN_ERROR(0); + } + + return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; +} + +s32 cellVideoOutGetConvertCursorColorInfo(vm::ptr rgbOutputRange) +{ + throw EXCEPTION(""); +} + +s32 cellVideoOutDebugSetMonitorType(u32 videoOut, u32 monitorType) +{ + throw EXCEPTION(""); +} + +s32 cellVideoOutRegisterCallback(u32 slot, vm::ptr function, vm::ptr userData) +{ + throw EXCEPTION(""); +} + +s32 cellVideoOutUnregisterCallback(u32 slot) +{ + throw EXCEPTION(""); +} + + +void cellSysutil_VideoOut_init() +{ + REG_FUNC(cellSysutil, cellVideoOutGetState); + REG_FUNC(cellSysutil, cellVideoOutGetResolution, MFF_PERFECT); + REG_FUNC(cellSysutil, cellVideoOutConfigure); + REG_FUNC(cellSysutil, cellVideoOutGetConfiguration); + REG_FUNC(cellSysutil, cellVideoOutGetDeviceInfo); + REG_FUNC(cellSysutil, cellVideoOutGetNumberOfDevice); + REG_FUNC(cellSysutil, cellVideoOutGetResolutionAvailability); + REG_FUNC(cellSysutil, cellVideoOutGetConvertCursorColorInfo); + REG_FUNC(cellSysutil, cellVideoOutDebugSetMonitorType); + REG_FUNC(cellSysutil, cellVideoOutRegisterCallback); + REG_FUNC(cellSysutil, cellVideoOutUnregisterCallback); +} diff --git a/rpcs3/Emu/Cell/Modules/cellVideoOut.h b/rpcs3/Emu/Cell/Modules/cellVideoOut.h new file mode 100644 index 0000000000..988c36335c --- /dev/null +++ b/rpcs3/Emu/Cell/Modules/cellVideoOut.h @@ -0,0 +1,262 @@ +#pragma once + +namespace vm { using namespace ps3; } + +#include "Emu/Cell/ErrorCodes.h" + +// Video Out Error Codes +enum CellVideoOutError : s32 +{ + CELL_VIDEO_OUT_ERROR_NOT_IMPLEMENTED = ERROR_CODE(0x8002b220), + CELL_VIDEO_OUT_ERROR_ILLEGAL_CONFIGURATION = ERROR_CODE(0x8002b221), + CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER = ERROR_CODE(0x8002b222), + CELL_VIDEO_OUT_ERROR_PARAMETER_OUT_OF_RANGE = ERROR_CODE(0x8002b223), + CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND = ERROR_CODE(0x8002b224), + CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT = ERROR_CODE(0x8002b225), + CELL_VIDEO_OUT_ERROR_UNSUPPORTED_DISPLAY_MODE = ERROR_CODE(0x8002b226), + CELL_VIDEO_OUT_ERROR_CONDITION_BUSY = ERROR_CODE(0x8002b227), + CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET = ERROR_CODE(0x8002b228), +}; + +template<> +inline const char* ppu_error_code::print(CellVideoOutError error) +{ + switch (error) + { + STR_CASE(CELL_VIDEO_OUT_ERROR_NOT_IMPLEMENTED); + STR_CASE(CELL_VIDEO_OUT_ERROR_ILLEGAL_CONFIGURATION); + STR_CASE(CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER); + STR_CASE(CELL_VIDEO_OUT_ERROR_PARAMETER_OUT_OF_RANGE); + STR_CASE(CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND); + STR_CASE(CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT); + STR_CASE(CELL_VIDEO_OUT_ERROR_UNSUPPORTED_DISPLAY_MODE); + STR_CASE(CELL_VIDEO_OUT_ERROR_CONDITION_BUSY); + STR_CASE(CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET); + } + + return nullptr; +} + +enum CellVideoOut : s32 +{ + CELL_VIDEO_OUT_PRIMARY = 0, + CELL_VIDEO_OUT_SECONDARY = 1, +}; + +enum CellVideoOutResolutionId : s32 +{ + CELL_VIDEO_OUT_RESOLUTION_UNDEFINED = 0, + CELL_VIDEO_OUT_RESOLUTION_1080 = 1, + CELL_VIDEO_OUT_RESOLUTION_720 = 2, + CELL_VIDEO_OUT_RESOLUTION_480 = 4, + CELL_VIDEO_OUT_RESOLUTION_576 = 5, + CELL_VIDEO_OUT_RESOLUTION_1600x1080 = 0xa, + CELL_VIDEO_OUT_RESOLUTION_1440x1080 = 0xb, + CELL_VIDEO_OUT_RESOLUTION_1280x1080 = 0xc, + CELL_VIDEO_OUT_RESOLUTION_960x1080 = 0xd, + CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING = 0x81, + CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING = 0x88, + CELL_VIDEO_OUT_RESOLUTION_960x720_3D_FRAME_PACKING = 0x89, + CELL_VIDEO_OUT_RESOLUTION_800x720_3D_FRAME_PACKING = 0x8a, + CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING = 0x8b, + CELL_VIDEO_OUT_RESOLUTION_720_DUALVIEW_FRAME_PACKING = 0x91, + CELL_VIDEO_OUT_RESOLUTION_720_SIMULVIEW_FRAME_PACKING = 0x91, + CELL_VIDEO_OUT_RESOLUTION_1024x720_DUALVIEW_FRAME_PACKING = 0x98, + CELL_VIDEO_OUT_RESOLUTION_1024x720_SIMULVIEW_FRAME_PACKING = 0x98, + CELL_VIDEO_OUT_RESOLUTION_960x720_DUALVIEW_FRAME_PACKING = 0x99, + CELL_VIDEO_OUT_RESOLUTION_960x720_SIMULVIEW_FRAME_PACKING = 0x99, + CELL_VIDEO_OUT_RESOLUTION_800x720_DUALVIEW_FRAME_PACKING = 0x9a, + CELL_VIDEO_OUT_RESOLUTION_800x720_SIMULVIEW_FRAME_PACKING = 0x9a, + CELL_VIDEO_OUT_RESOLUTION_640x720_DUALVIEW_FRAME_PACKING = 0x9b, + CELL_VIDEO_OUT_RESOLUTION_640x720_SIMULVIEW_FRAME_PACKING = 0x9b, +}; + +enum CellVideoOutScanMode : s32 +{ + CELL_VIDEO_OUT_SCAN_MODE_INTERLACE, + CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE, +}; + +enum CellVideoOutScanMode2 : s32 +{ + CELL_VIDEO_OUT_SCAN_MODE2_AUTO, + CELL_VIDEO_OUT_SCAN_MODE2_INTERLACE, + CELL_VIDEO_OUT_SCAN_MODE2_PROGRESSIVE, +}; + +enum CellVideoOutRefreshRate : s32 +{ + CELL_VIDEO_OUT_REFRESH_RATE_AUTO = 0x0000, + CELL_VIDEO_OUT_REFRESH_RATE_59_94HZ = 0x0001, + CELL_VIDEO_OUT_REFRESH_RATE_50HZ = 0x0002, + CELL_VIDEO_OUT_REFRESH_RATE_60HZ = 0x0004, + CELL_VIDEO_OUT_REFRESH_RATE_30HZ = 0x0008, +}; + +enum CellVideoOutPortType : s32 +{ + CELL_VIDEO_OUT_PORT_NONE = 0x00, + CELL_VIDEO_OUT_PORT_HDMI = 0x01, + CELL_VIDEO_OUT_PORT_NETWORK = 0x41, + CELL_VIDEO_OUT_PORT_COMPOSITE_S = 0x81, + CELL_VIDEO_OUT_PORT_D = 0x82, + CELL_VIDEO_OUT_PORT_COMPONENT = 0x83, + CELL_VIDEO_OUT_PORT_RGB = 0x84, + CELL_VIDEO_OUT_PORT_AVMULTI_SCART = 0x85, + CELL_VIDEO_OUT_PORT_DSUB = 0x86, +}; + +enum CellVideoOutDisplayAspect : s32 +{ + CELL_VIDEO_OUT_ASPECT_AUTO, + CELL_VIDEO_OUT_ASPECT_4_3, + CELL_VIDEO_OUT_ASPECT_16_9, +}; + +enum CellVideoOutBufferColorFormat : s32 +{ + CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8, + CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8B8G8R8, + CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_R16G16B16X16_FLOAT, +}; + +enum CellVideoOutOutputState : s32 +{ + CELL_VIDEO_OUT_OUTPUT_STATE_ENABLED, + CELL_VIDEO_OUT_OUTPUT_STATE_DISABLED, + CELL_VIDEO_OUT_OUTPUT_STATE_PREPARING, +}; + +enum CellVideoOutDeviceState : s32 +{ + CELL_VIDEO_OUT_DEVICE_STATE_UNAVAILABLE, + CELL_VIDEO_OUT_DEVICE_STATE_AVAILABLE, +}; + +enum CellVideoOutColorSpace : s32 +{ + CELL_VIDEO_OUT_COLOR_SPACE_RGB = 0x01, + CELL_VIDEO_OUT_COLOR_SPACE_YUV = 0x02, + CELL_VIDEO_OUT_COLOR_SPACE_XVYCC = 0x04, +}; + +enum CellVideoOutDebugMonitorType : s32 +{ + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_UNDEFINED = 0, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_480I_59_94HZ = 1, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_576I_50HZ = 2, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_480P_59_94HZ = 3, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_576P_50HZ = 4, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_1080I_59_94HZ = 5, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_720P_59_94HZ = 7, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_1080P_59_94HZ = 9, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_WXGA_60HZ = 11, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_SXGA_60HZ = 12, + CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_WUXGA_60HZ = 13, +}; + +struct CellVideoOutColorInfo +{ + be_t redX; + be_t redY; + be_t greenX; + be_t greenY; + be_t blueX; + be_t blueY; + be_t whiteX; + be_t whiteY; + be_t gamma; +}; + +struct CellVideoOutKSVList +{ + u8 ksv[32*5]; + u8 reserved[4]; + be_t count; +}; + +enum CellVideoOutDisplayConversion : s32 +{ + CELL_VIDEO_OUT_DISPLAY_CONVERSION_NONE = 0x00, + CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_WXGA = 0x01, + CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_SXGA = 0x02, + CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_WUXGA = 0x03, + CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_1080 = 0x05, + CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_REMOTEPLAY = 0x10, + CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_720_3D_FRAME_PACKING = 0x80, +}; + +struct CellVideoOutDisplayMode +{ + u8 resolutionId; + u8 scanMode; + u8 conversion; + u8 aspect; + u8 reserved[2]; + be_t refreshRates; +}; + +struct CellVideoOutResolution +{ + be_t width; + be_t height; +}; + +struct CellVideoOutDeviceInfo +{ + u8 portType; + u8 colorSpace; + be_t latency; + u8 availableModeCount; + u8 state; + u8 rgbOutputRange; + u8 reserved[5]; + CellVideoOutColorInfo colorInfo; + CellVideoOutDisplayMode availableModes[32]; + CellVideoOutKSVList ksvList; +}; + +struct CellVideoOutState +{ + u8 state; + u8 colorSpace; + u8 reserved[6]; + CellVideoOutDisplayMode displayMode; +}; + +struct CellVideoOutConfiguration +{ + u8 resolutionId; + u8 format; + u8 aspect; + u8 reserved[9]; + be_t pitch; +}; + +struct CellVideoOutOption +{ + be_t reserved; +}; + +enum CellVideoOutEvent : s32 +{ + CELL_VIDEO_OUT_EVENT_DEVICE_CHANGED, + CELL_VIDEO_OUT_EVENT_OUTPUT_DISABLED, + CELL_VIDEO_OUT_EVENT_DEVICE_AUTHENTICATED, + CELL_VIDEO_OUT_EVENT_OUTPUT_ENABLED, +}; + +enum CellVideoOutCopyControl : s32 +{ + CELL_VIDEO_OUT_COPY_CONTROL_COPY_FREE, + CELL_VIDEO_OUT_COPY_CONTROL_COPY_ONCE, + CELL_VIDEO_OUT_COPY_CONTROL_COPY_NEVER, +}; + +enum CellVideoOutRGBOutputRange : s32 +{ + CELL_VIDEO_OUT_RGB_OUTPUT_RANGE_LIMITED, + CELL_VIDEO_OUT_RGB_OUTPUT_RANGE_FULL, +}; + +using CellVideoOutCallback = s32(u32 slot, u32 videoOut, u32 deviceIndex, u32 event, vm::ptr info, vm::ptr userData); diff --git a/rpcs3/Emu/Cell/Modules/cellVideoUpload.cpp b/rpcs3/Emu/Cell/Modules/cellVideoUpload.cpp new file mode 100644 index 0000000000..f41f52a573 --- /dev/null +++ b/rpcs3/Emu/Cell/Modules/cellVideoUpload.cpp @@ -0,0 +1,14 @@ +#include "stdafx.h" +#include "Emu/Cell/PPUModule.h" + +LOG_CHANNEL(cellVideoUpload); + +s32 cellVideoUploadInitialize() +{ + throw EXCEPTION(""); +} + +DECLARE(ppu_module_manager::cellVideoUpload)("cellVideoUpload", []() +{ + REG_FUNC(cellVideoUpload, cellVideoUploadInitialize); +}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVoice.cpp b/rpcs3/Emu/Cell/Modules/cellVoice.cpp similarity index 97% rename from rpcs3/Emu/SysCalls/Modules/cellVoice.cpp rename to rpcs3/Emu/Cell/Modules/cellVoice.cpp index 5083aa6823..83c227faa9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVoice.cpp +++ b/rpcs3/Emu/Cell/Modules/cellVoice.cpp @@ -1,9 +1,8 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" -extern Module<> cellVoice; +LOG_CHANNEL(cellVoice); // Error Codes enum @@ -237,7 +236,7 @@ s32 cellVoiceDebugTopology() return CELL_OK; } -Module<> cellVoice("cellVoice", []() +DECLARE(ppu_module_manager::cellVoice)("cellVoice", []() { REG_FUNC(cellVoice, cellVoiceConnectIPortToOPort); REG_FUNC(cellVoice, cellVoiceCreateNotifyEventQueue); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/Cell/Modules/cellVpost.cpp similarity index 97% rename from rpcs3/Emu/SysCalls/Modules/cellVpost.cpp rename to rpcs3/Emu/Cell/Modules/cellVpost.cpp index 1f466e12db..d42d4febbc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/Cell/Modules/cellVpost.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" extern "C" { @@ -11,7 +10,7 @@ extern "C" #include "cellVpost.h" -extern Module<> cellVpost; +LOG_CHANNEL(cellVpost); s32 cellVpostQueryAttr(vm::cptr cfgParam, vm::ptr attr) { @@ -137,7 +136,7 @@ s32 cellVpostExec(u32 handle, vm::cptr inPicBuff, vm::cptr cellVpost("cellVpost", []() +DECLARE(ppu_module_manager::cellVpost)("cellVpost", []() { REG_FUNC(cellVpost, cellVpostQueryAttr); REG_FUNC(cellVpost, cellVpostOpen); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.h b/rpcs3/Emu/Cell/Modules/cellVpost.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellVpost.h rename to rpcs3/Emu/Cell/Modules/cellVpost.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellWebBrowser.cpp b/rpcs3/Emu/Cell/Modules/cellWebBrowser.cpp similarity index 98% rename from rpcs3/Emu/SysCalls/Modules/cellWebBrowser.cpp rename to rpcs3/Emu/Cell/Modules/cellWebBrowser.cpp index 1929045f4a..4f0877a095 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellWebBrowser.cpp +++ b/rpcs3/Emu/Cell/Modules/cellWebBrowser.cpp @@ -1,10 +1,9 @@ #include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" +#include "Emu/Cell/PPUModule.h" #include "cellWebBrowser.h" -extern Module<> cellSysutil; +extern _log::channel cellSysutil; s32 cellWebBrowserActivate() { diff --git a/rpcs3/Emu/SysCalls/Modules/cellWebBrowser.h b/rpcs3/Emu/Cell/Modules/cellWebBrowser.h similarity index 100% rename from rpcs3/Emu/SysCalls/Modules/cellWebBrowser.h rename to rpcs3/Emu/Cell/Modules/cellWebBrowser.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp deleted file mode 100644 index bcd8928643..0000000000 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ /dev/null @@ -1,1027 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/System.h" -#include "Emu/state.h" -#include "Emu/IdManager.h" -#include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" - -#include "Emu/SysCalls/lv2/sys_sync.h" -#include "Emu/SysCalls/lv2/sys_event.h" -#include "Emu/Event.h" -#include "Emu/Audio/AudioManager.h" -#include "Emu/Audio/AudioDumper.h" - -#include "cellAudio.h" - -extern Module<> cellAudio; - -extern u64 get_system_time(); - -AudioConfig g_audio; - -std::shared_ptr g_audio_thread; - -s32 cellAudioInit() -{ - cellAudio.warning("cellAudioInit()"); - - if (!g_audio.state.compare_and_swap_test(AUDIO_STATE_NOT_INITIALIZED, AUDIO_STATE_INITIALIZED)) - { - return CELL_AUDIO_ERROR_ALREADY_INIT; - } - - // clear ports - for (auto& port : g_audio.ports) - { - port.state = AUDIO_PORT_STATE_CLOSED; - } - - // reset variables - g_audio.counter = 0; - g_audio.keys.clear(); - g_audio.start_time = get_system_time(); - - // alloc memory (only once until the emulator is stopped) - g_audio.buffer = g_audio.buffer ? g_audio.buffer : vm::alloc(AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT, vm::main); - g_audio.indexes = g_audio.indexes ? g_audio.indexes : vm::alloc(SIZE_32(u64) * AUDIO_PORT_COUNT, vm::main); - - // clear memory - std::memset(vm::base(g_audio.buffer), 0, AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT); - std::memset(vm::base(g_audio.indexes), 0, SIZE_32(u64) * AUDIO_PORT_COUNT); - - // start audio thread - g_audio_thread = thread_ctrl::spawn(PURE_EXPR("Audio Thread"s), []() - { - const bool do_dump = rpcs3::config.audio.dump_to_file.value(); - - AudioDumper m_dump; - if (do_dump && !m_dump.Init(2)) // Init AudioDumper for 2 channels - { - throw EXCEPTION("AudioDumper::Init() failed"); - } - - float buf2ch[2 * BUFFER_SIZE]; // intermediate buffer for 2 channels - float buf8ch[8 * BUFFER_SIZE]; // intermediate buffer for 8 channels - - static const size_t out_buffer_size = 8 * BUFFER_SIZE; // output buffer for 8 channels - - std::unique_ptr out_buffer[BUFFER_NUM]; - - for (u32 i = 0; i < BUFFER_NUM; i++) - { - out_buffer[i].reset(new float[out_buffer_size] {}); - } - - squeue_t out_queue; - - scope_thread_t iat(PURE_EXPR("Internal Audio Thread"s), [&out_queue]() - { - const bool use_u16 = rpcs3::config.audio.convert_to_u16.value(); - - Emu.GetAudioManager().GetAudioOut().Init(); - - bool opened = false; - float* buffer; - - while (out_queue.pop(buffer, [](){ return g_audio.state != AUDIO_STATE_INITIALIZED; })) - { - if (use_u16) - { - // convert the data from float to u16 with clipping: - // 2x MULPS - // 2x MAXPS (optional) - // 2x MINPS (optional) - // 2x CVTPS2DQ (converts float to s32) - // PACKSSDW (converts s32 to s16 with signed saturation) - - u16 buf_u16[out_buffer_size]; - for (size_t i = 0; i < out_buffer_size; i += 8) - { - const auto scale = _mm_set1_ps(0x8000); - (__m128i&)(buf_u16[i]) = _mm_packs_epi32( - _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(buffer + i), scale)), - _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(buffer + i + 4), scale))); - } - - if (!opened) - { - Emu.GetAudioManager().GetAudioOut().Open(buf_u16, out_buffer_size * sizeof(u16)); - opened = true; - } - else - { - Emu.GetAudioManager().GetAudioOut().AddData(buf_u16, out_buffer_size * sizeof(u16)); - } - } - else - { - if (!opened) - { - Emu.GetAudioManager().GetAudioOut().Open(buffer, out_buffer_size * sizeof(float)); - opened = true; - } - else - { - Emu.GetAudioManager().GetAudioOut().AddData(buffer, out_buffer_size * sizeof(float)); - } - } - } - - Emu.GetAudioManager().GetAudioOut().Quit(); - }); - - while (g_audio.state == AUDIO_STATE_INITIALIZED && !Emu.IsStopped()) - { - if (Emu.IsPaused()) - { - std::this_thread::sleep_for(1ms); // hack - continue; - } - - const u64 stamp0 = get_system_time(); - - const u64 time_pos = stamp0 - g_audio.start_time - Emu.GetPauseTime(); - - // TODO: send beforemix event (in ~2,6 ms before mixing) - - // precise time of sleeping: 5,(3) ms (or 256/48000 sec) - const u64 expected_time = g_audio.counter * AUDIO_SAMPLES * 1000000 / 48000; - if (expected_time >= time_pos) - { - std::this_thread::sleep_for(1ms); // hack - continue; - } - - //// crutch to hide giant lags caused by debugger - //const u64 missed_time = time_pos - expected_time; - //if (missed_time > AUDIO_SAMPLES * MHZ / 48000) - //{ - // cellAudio.notice("%f ms adjusted", (float)missed_time / 1000); - // g_audio.start_time += missed_time; - //} - - g_audio.counter++; - - const u32 out_pos = g_audio.counter % BUFFER_NUM; - - bool first_mix = true; - - // mixing: - for (auto& port : g_audio.ports) - { - if (port.state != AUDIO_PORT_STATE_STARTED) continue; - - const u32 block_size = port.channel * AUDIO_SAMPLES; - const u32 position = port.tag % port.block; // old value - const u32 buf_addr = port.addr + position * block_size * sizeof(float); - - auto buf = vm::_ptr(buf_addr); - - static const float k = 1.0f; // may be 1.0f - const float& m = port.level; - - auto step_volume = [](AudioPortConfig& port) // part of cellAudioSetPortLevel functionality - { - const auto param = port.level_set.load(); - - if (param.inc != 0.0f) - { - port.level += param.inc; - const bool dec = param.inc < 0.0f; - - if ((!dec && param.value - port.level <= 0.0f) || (dec && param.value - port.level >= 0.0f)) - { - port.level = param.value; - port.level_set.compare_and_swap(param, { param.value, 0.0f }); - } - } - }; - - if (port.channel == 2) - { - if (first_mix) - { - for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 2) - { - step_volume(port); - - // reverse byte order - const float left = buf[i + 0] * m; - const float right = buf[i + 1] * m; - - buf2ch[i + 0] = left; - buf2ch[i + 1] = right; - - buf8ch[i * 4 + 0] = left; - buf8ch[i * 4 + 1] = right; - buf8ch[i * 4 + 2] = 0.0f; - buf8ch[i * 4 + 3] = 0.0f; - buf8ch[i * 4 + 4] = 0.0f; - buf8ch[i * 4 + 5] = 0.0f; - buf8ch[i * 4 + 6] = 0.0f; - buf8ch[i * 4 + 7] = 0.0f; - } - first_mix = false; - } - else - { - for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 2) - { - step_volume(port); - - const float left = buf[i + 0] * m; - const float right = buf[i + 1] * m; - - buf2ch[i + 0] += left; - buf2ch[i + 1] += right; - - buf8ch[i * 4 + 0] += left; - buf8ch[i * 4 + 1] += right; - } - } - } - else if (port.channel == 8) - { - if (first_mix) - { - for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 2) - { - step_volume(port); - - const float left = buf[i * 4 + 0] * m; - const float right = buf[i * 4 + 1] * m; - const float center = buf[i * 4 + 2] * m; - const float low_freq = buf[i * 4 + 3] * m; - const float rear_left = buf[i * 4 + 4] * m; - const float rear_right = buf[i * 4 + 5] * m; - const float side_left = buf[i * 4 + 6] * m; - const float side_right = buf[i * 4 + 7] * m; - - const float mid = (center + low_freq) * 0.708f; - buf2ch[i + 0] = (left + rear_left + side_left + mid) * k; - buf2ch[i + 1] = (right + rear_right + side_right + mid) * k; - - buf8ch[i * 4 + 0] = left; - buf8ch[i * 4 + 1] = right; - buf8ch[i * 4 + 2] = center; - buf8ch[i * 4 + 3] = low_freq; - buf8ch[i * 4 + 4] = rear_left; - buf8ch[i * 4 + 5] = rear_right; - buf8ch[i * 4 + 6] = side_left; - buf8ch[i * 4 + 7] = side_right; - } - first_mix = false; - } - else - { - for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 2) - { - step_volume(port); - - const float left = buf[i * 4 + 0] * m; - const float right = buf[i * 4 + 1] * m; - const float center = buf[i * 4 + 2] * m; - const float low_freq = buf[i * 4 + 3] * m; - const float rear_left = buf[i * 4 + 4] * m; - const float rear_right = buf[i * 4 + 5] * m; - const float side_left = buf[i * 4 + 6] * m; - const float side_right = buf[i * 4 + 7] * m; - - const float mid = (center + low_freq) * 0.708f; - buf2ch[i + 0] += (left + rear_left + side_left + mid) * k; - buf2ch[i + 1] += (right + rear_right + side_right + mid) * k; - - buf8ch[i * 4 + 0] += left; - buf8ch[i * 4 + 1] += right; - buf8ch[i * 4 + 2] += center; - buf8ch[i * 4 + 3] += low_freq; - buf8ch[i * 4 + 4] += rear_left; - buf8ch[i * 4 + 5] += rear_right; - buf8ch[i * 4 + 6] += side_left; - buf8ch[i * 4 + 7] += side_right; - } - } - } - else - { - throw EXCEPTION("Unknown channel count (port=%lld, channel=%d)", &port - g_audio.ports, port.channel); - } - - memset(buf, 0, block_size * sizeof(float)); - } - - - if (!first_mix) - { - // copy output data (2 ch) - //for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i++) - //{ - // out_buffer[out_pos][i] = buf2ch[i]; - //} - - // copy output data (8 ch) - for (u32 i = 0; i < (sizeof(buf8ch) / sizeof(float)); i++) - { - out_buffer[out_pos][i] = buf8ch[i]; - } - } - - //const u64 stamp1 = get_system_time(); - - if (first_mix) - { - memset(out_buffer[out_pos].get(), 0, out_buffer_size * sizeof(float)); - } - - if (!out_queue.push(out_buffer[out_pos].get(), [](){ return g_audio.state != AUDIO_STATE_INITIALIZED; })) - { - break; - } - - //const u64 stamp2 = get_system_time(); - - { - // update indices: - - auto indexes = vm::ptr::make(g_audio.indexes); - - for (u32 i = 0; i < AUDIO_PORT_COUNT; i++) - { - AudioPortConfig& port = g_audio.ports[i]; - - if (port.state != AUDIO_PORT_STATE_STARTED) continue; - - u32 position = port.tag % port.block; // old value - port.counter = g_audio.counter; - port.tag++; // absolute index of block that will be read - indexes[i] = (position + 1) % port.block; // write new value - } - - // send aftermix event (normal audio event) - - LV2_LOCK; - - std::lock_guard lock(g_audio.mutex); - - for (auto key : g_audio.keys) - { - if (const auto queue = Emu.GetEventManager().GetEventQueue(key)) - { - queue->push(lv2_lock, 0, 0, 0, 0); // TODO: check arguments - } - } - } - - - //const u64 stamp3 = get_system_time(); - - if (do_dump && !first_mix) - { - if (m_dump.GetCh() == 8) - { - if (m_dump.WriteData(&buf8ch, sizeof(buf8ch)) != sizeof(buf8ch)) // write file data (8 ch) - { - throw EXCEPTION("AudioDumper::WriteData() failed (8 ch)"); - } - } - else if (m_dump.GetCh() == 2) - { - if (m_dump.WriteData(&buf2ch, sizeof(buf2ch)) != sizeof(buf2ch)) // write file data (2 ch) - { - throw EXCEPTION("AudioDumper::WriteData() failed (2 ch)"); - } - } - else - { - throw EXCEPTION("AudioDumper::GetCh() returned unknown value (%d)", m_dump.GetCh()); - } - } - - //LOG_NOTICE(HLE, "Audio perf: start=%d (access=%d, AddData=%d, events=%d, dump=%d)", - //time_pos, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3); - } - }); - - return CELL_OK; -} - -s32 cellAudioQuit() -{ - cellAudio.warning("cellAudioQuit()"); - - if (!g_audio.state.compare_and_swap_test(AUDIO_STATE_INITIALIZED, AUDIO_STATE_FINALIZED)) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - g_audio_thread->join(); - g_audio_thread.reset(); - g_audio.state.exchange(AUDIO_STATE_NOT_INITIALIZED); - - return CELL_OK; -} - -s32 cellAudioPortOpen(vm::ptr audioParam, vm::ptr portNum) -{ - cellAudio.warning("cellAudioPortOpen(audioParam=*0x%x, portNum=*0x%x)", audioParam, portNum); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (!audioParam || !portNum) - { - return CELL_AUDIO_ERROR_PARAM; - } - - const u64 channel = audioParam->nChannel; - const u64 block = audioParam->nBlock; - const u64 attr = audioParam->attr; - - // check attributes - if (channel != CELL_AUDIO_PORT_2CH && - channel != CELL_AUDIO_PORT_8CH && - channel) - { - return CELL_AUDIO_ERROR_PARAM; - } - - if (block != CELL_AUDIO_BLOCK_8 && - block != CELL_AUDIO_BLOCK_16 && - block != 2 && - block != 4 && - block != 32) - { - return CELL_AUDIO_ERROR_PARAM; - } - - // list unsupported flags - if (attr & CELL_AUDIO_PORTATTR_BGM) - { - cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_BGM"); - } - if (attr & CELL_AUDIO_PORTATTR_OUT_SECONDARY) - { - cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_SECONDARY"); - } - if (attr & CELL_AUDIO_PORTATTR_OUT_PERSONAL_0) - { - cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_PERSONAL_0"); - } - if (attr & CELL_AUDIO_PORTATTR_OUT_PERSONAL_1) - { - cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_PERSONAL_1"); - } - if (attr & CELL_AUDIO_PORTATTR_OUT_PERSONAL_2) - { - cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_PERSONAL_2"); - } - if (attr & CELL_AUDIO_PORTATTR_OUT_PERSONAL_3) - { - cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_PERSONAL_3"); - } - if (attr & CELL_AUDIO_PORTATTR_OUT_NO_ROUTE) - { - cellAudio.todo("cellAudioPortOpen(): CELL_AUDIO_PORTATTR_OUT_NO_ROUTE"); - } - if (attr & 0xFFFFFFFFF0EFEFEEULL) - { - cellAudio.todo("cellAudioPortOpen(): unknown attributes (0x%llx)", attr); - } - - // open audio port - const u32 port_index = g_audio.open_port(); - - if (!~port_index) - { - return CELL_AUDIO_ERROR_PORT_FULL; - } - - AudioPortConfig& port = g_audio.ports[port_index]; - - port.channel = (u32)channel; - port.block = (u32)block; - port.attr = attr; - port.addr = g_audio.buffer + AUDIO_PORT_OFFSET * port_index; - port.read_index_addr = g_audio.indexes + sizeof(u64) * port_index; - port.size = port.channel * port.block * AUDIO_SAMPLES * sizeof(float); - port.tag = 0; - - if (port.attr & CELL_AUDIO_PORTATTR_INITLEVEL) - { - port.level = audioParam->level; - } - else - { - port.level = 1.0f; - } - - port.level_set.store({ port.level, 0.0f }); - - *portNum = port_index; - cellAudio.warning("*** audio port opened(nChannel=%d, nBlock=%d, attr=0x%llx, level=%f): port = %d", channel, block, attr, port.level, port_index); - - return CELL_OK; -} - -s32 cellAudioGetPortConfig(u32 portNum, vm::ptr portConfig) -{ - cellAudio.warning("cellAudioGetPortConfig(portNum=%d, portConfig=*0x%x)", portNum, portConfig); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (!portConfig || portNum >= AUDIO_PORT_COUNT) - { - return CELL_AUDIO_ERROR_PARAM; - } - - AudioPortConfig& port = g_audio.ports[portNum]; - - portConfig->readIndexAddr = port.read_index_addr; - - switch (auto state = port.state.load()) - { - case AUDIO_PORT_STATE_CLOSED: portConfig->status = CELL_AUDIO_STATUS_CLOSE; break; - case AUDIO_PORT_STATE_OPENED: portConfig->status = CELL_AUDIO_STATUS_READY; break; - case AUDIO_PORT_STATE_STARTED: portConfig->status = CELL_AUDIO_STATUS_RUN; break; - default: throw EXCEPTION("Invalid port state (%d: %d)", portNum, state); - } - - portConfig->nChannel = port.channel; - portConfig->nBlock = port.block; - portConfig->portSize = port.size; - portConfig->portAddr = port.addr; - return CELL_OK; -} - -s32 cellAudioPortStart(u32 portNum) -{ - cellAudio.warning("cellAudioPortStart(portNum=%d)", portNum); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (portNum >= AUDIO_PORT_COUNT) - { - return CELL_AUDIO_ERROR_PARAM; - } - - switch (auto state = g_audio.ports[portNum].state.compare_and_swap(AUDIO_PORT_STATE_OPENED, AUDIO_PORT_STATE_STARTED)) - { - case AUDIO_PORT_STATE_CLOSED: return CELL_AUDIO_ERROR_PORT_NOT_OPEN; - case AUDIO_PORT_STATE_STARTED: return CELL_AUDIO_ERROR_PORT_ALREADY_RUN; - case AUDIO_PORT_STATE_OPENED: return CELL_OK; - default: throw EXCEPTION("Invalid port state (%d: %d)", portNum, state); - } -} - -s32 cellAudioPortClose(u32 portNum) -{ - cellAudio.warning("cellAudioPortClose(portNum=%d)", portNum); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (portNum >= AUDIO_PORT_COUNT) - { - return CELL_AUDIO_ERROR_PARAM; - } - - switch (auto 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; - default: throw EXCEPTION("Invalid port state (%d: %d)", portNum, state); - } -} - -s32 cellAudioPortStop(u32 portNum) -{ - cellAudio.warning("cellAudioPortStop(portNum=%d)", portNum); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (portNum >= AUDIO_PORT_COUNT) - { - return CELL_AUDIO_ERROR_PARAM; - } - - switch (auto state = g_audio.ports[portNum].state.compare_and_swap(AUDIO_PORT_STATE_STARTED, AUDIO_PORT_STATE_OPENED)) - { - case AUDIO_PORT_STATE_CLOSED: return CELL_AUDIO_ERROR_PORT_NOT_RUN; - case AUDIO_PORT_STATE_STARTED: return CELL_OK; - case AUDIO_PORT_STATE_OPENED: return CELL_AUDIO_ERROR_PORT_NOT_RUN; - default: throw EXCEPTION("Invalid port state (%d: %d)", portNum, state); - } -} - -s32 cellAudioGetPortTimestamp(u32 portNum, u64 tag, vm::ptr stamp) -{ - cellAudio.trace("cellAudioGetPortTimestamp(portNum=%d, tag=0x%llx, stamp=*0x%x)", portNum, tag, stamp); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (portNum >= AUDIO_PORT_COUNT) - { - return CELL_AUDIO_ERROR_PARAM; - } - - AudioPortConfig& port = g_audio.ports[portNum]; - - if (port.state == AUDIO_PORT_STATE_CLOSED) - { - return CELL_AUDIO_ERROR_PORT_NOT_OPEN; - } - - // TODO: check tag (CELL_AUDIO_ERROR_TAG_NOT_FOUND error) - - *stamp = g_audio.start_time + Emu.GetPauseTime() + (port.counter + (tag - port.tag)) * 256000000 / 48000; - - return CELL_OK; -} - -s32 cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr tag) -{ - cellAudio.trace("cellAudioGetPortBlockTag(portNum=%d, blockNo=0x%llx, tag=*0x%x)", portNum, blockNo, tag); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (portNum >= AUDIO_PORT_COUNT) - { - return CELL_AUDIO_ERROR_PARAM; - } - - AudioPortConfig& port = g_audio.ports[portNum]; - - if (port.state == AUDIO_PORT_STATE_CLOSED) - { - return CELL_AUDIO_ERROR_PORT_NOT_OPEN; - } - - if (blockNo >= port.block) - { - return CELL_AUDIO_ERROR_PARAM; - } - - u64 tag_base = port.tag; - if (tag_base % port.block > blockNo) - { - tag_base &= ~(port.block - 1); - tag_base += port.block; - } - else - { - tag_base &= ~(port.block - 1); - } - *tag = tag_base + blockNo; - - return CELL_OK; -} - -s32 cellAudioSetPortLevel(u32 portNum, float level) -{ - cellAudio.trace("cellAudioSetPortLevel(portNum=%d, level=%f)", portNum, level); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (portNum >= AUDIO_PORT_COUNT) - { - return CELL_AUDIO_ERROR_PARAM; - } - - AudioPortConfig& port = g_audio.ports[portNum]; - - if (port.state == AUDIO_PORT_STATE_CLOSED) - { - return CELL_AUDIO_ERROR_PORT_NOT_OPEN; - } - - if (level >= 0.0f) - { - port.level_set.exchange({ level, (port.level - level) / 624.0f }); - } - else - { - cellAudio.todo("cellAudioSetPortLevel(%d): negative level value (%f)", portNum, level); - } - - return CELL_OK; -} - -s32 cellAudioCreateNotifyEventQueue(vm::ptr id, vm::ptr key) -{ - cellAudio.warning("cellAudioCreateNotifyEventQueue(id=*0x%x, key=*0x%x)", id, key); - - for (u64 k = 0; k < 100; k++) - { - const u64 key_value = 0x80004d494f323221ull + k; - - // register key if not used yet - if (const auto queue = Emu.GetEventManager().MakeEventQueue(key_value, SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0, key_value, 32)) - { - *id = queue->id; - *key = key_value; - - return CELL_OK; - } - } - - return CELL_AUDIO_ERROR_EVENT_QUEUE; -} - -s32 cellAudioCreateNotifyEventQueueEx(vm::ptr id, vm::ptr key, u32 iFlags) -{ - cellAudio.todo("cellAudioCreateNotifyEventQueueEx(id=*0x%x, key=*0x%x, iFlags=0x%x)", id, key, iFlags); - - if (iFlags & ~CELL_AUDIO_CREATEEVENTFLAG_SPU) - { - return CELL_AUDIO_ERROR_PARAM; - } - - // TODO - - return CELL_AUDIO_ERROR_EVENT_QUEUE; -} - -s32 cellAudioSetNotifyEventQueue(u64 key) -{ - cellAudio.warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - std::lock_guard lock(g_audio.mutex); - - for (auto k : g_audio.keys) // check for duplicates - { - if (k == key) - { - return CELL_AUDIO_ERROR_TRANS_EVENT; - } - } - - g_audio.keys.emplace_back(key); - - return CELL_OK; -} - -s32 cellAudioSetNotifyEventQueueEx(u64 key, u32 iFlags) -{ - cellAudio.todo("cellAudioSetNotifyEventQueueEx(key=0x%llx, iFlags=0x%x)", key, iFlags); - - // TODO - - return CELL_OK; -} - -s32 cellAudioRemoveNotifyEventQueue(u64 key) -{ - cellAudio.warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - std::lock_guard lock(g_audio.mutex); - - for (auto i = g_audio.keys.begin(); i != g_audio.keys.end(); i++) - { - if (*i == key) - { - g_audio.keys.erase(i); - - return CELL_OK; - } - } - - return CELL_AUDIO_ERROR_TRANS_EVENT; -} - -s32 cellAudioRemoveNotifyEventQueueEx(u64 key, u32 iFlags) -{ - cellAudio.todo("cellAudioRemoveNotifyEventQueueEx(key=0x%llx, iFlags=0x%x)", key, iFlags); - - // TODO - - return CELL_OK; -} - -s32 cellAudioAddData(u32 portNum, vm::ptr src, u32 samples, float volume) -{ - cellAudio.trace("cellAudioAddData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned()) - { - return CELL_AUDIO_ERROR_PARAM; - } - - if (samples != 256) - { - // despite the docs, seems that only fixed value is supported - cellAudio.error("cellAudioAddData(): invalid samples value (%d)", samples); - return CELL_AUDIO_ERROR_PARAM; - } - - const AudioPortConfig& port = g_audio.ports[portNum]; - - const auto dst = vm::ptr::make(port.addr + u32(port.tag % port.block) * port.channel * 256 * SIZE_32(float)); - - for (u32 i = 0; i < samples * port.channel; i++) - { - dst[i] += src[i] * volume; // mix all channels - } - - return CELL_OK; -} - -s32 cellAudioAdd2chData(u32 portNum, vm::ptr src, u32 samples, float volume) -{ - cellAudio.trace("cellAudioAdd2chData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned()) - { - return CELL_AUDIO_ERROR_PARAM; - } - - if (samples != 256) - { - // despite the docs, seems that only fixed value is supported - cellAudio.error("cellAudioAdd2chData(): invalid samples value (%d)", samples); - return CELL_AUDIO_ERROR_PARAM; - } - - const AudioPortConfig& port = g_audio.ports[portNum]; - - const auto dst = vm::ptr::make(port.addr + s32(port.tag % port.block) * port.channel * 256 * SIZE_32(float)); - - if (port.channel == 2) - { - cellAudio.error("cellAudioAdd2chData(portNum=%d): port.channel = 2", portNum); - } - else if (port.channel == 6) - { - for (u32 i = 0; i < samples; i++) - { - dst[i * 6 + 0] += src[i * 2 + 0] * volume; // mix L ch - dst[i * 6 + 1] += src[i * 2 + 1] * volume; // mix R ch - //dst[i * 6 + 2] += 0.0f; // center - //dst[i * 6 + 3] += 0.0f; // LFE - //dst[i * 6 + 4] += 0.0f; // rear L - //dst[i * 6 + 5] += 0.0f; // rear R - } - } - else if (port.channel == 8) - { - for (u32 i = 0; i < samples; i++) - { - dst[i * 8 + 0] += src[i * 2 + 0] * volume; // mix L ch - dst[i * 8 + 1] += src[i * 2 + 1] * volume; // mix R ch - //dst[i * 8 + 2] += 0.0f; // center - //dst[i * 8 + 3] += 0.0f; // LFE - //dst[i * 8 + 4] += 0.0f; // rear L - //dst[i * 8 + 5] += 0.0f; // rear R - //dst[i * 8 + 6] += 0.0f; // side L - //dst[i * 8 + 7] += 0.0f; // side R - } - } - else - { - cellAudio.error("cellAudioAdd2chData(portNum=%d): invalid port.channel value (%d)", portNum, port.channel); - } - - return CELL_OK; -} - -s32 cellAudioAdd6chData(u32 portNum, vm::ptr src, float volume) -{ - cellAudio.trace("cellAudioAdd6chData(portNum=%d, src=*0x%x, volume=%f)", portNum, src, volume); - - if (g_audio.state != AUDIO_STATE_INITIALIZED) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned()) - { - return CELL_AUDIO_ERROR_PARAM; - } - - const AudioPortConfig& port = g_audio.ports[portNum]; - - const auto dst = vm::ptr::make(port.addr + s32(port.tag % port.block) * port.channel * 256 * SIZE_32(float)); - - if (port.channel == 2 || port.channel == 6) - { - cellAudio.error("cellAudioAdd2chData(portNum=%d): port.channel = %d", portNum, port.channel); - } - else if (port.channel == 8) - { - for (u32 i = 0; i < 256; i++) - { - dst[i * 8 + 0] += src[i * 6 + 0] * volume; // mix L ch - dst[i * 8 + 1] += src[i * 6 + 1] * volume; // mix R ch - dst[i * 8 + 2] += src[i * 6 + 2] * volume; // mix center - dst[i * 8 + 3] += src[i * 6 + 3] * volume; // mix LFE - dst[i * 8 + 4] += src[i * 6 + 4] * volume; // mix rear L - dst[i * 8 + 5] += src[i * 6 + 5] * volume; // mix rear R - //dst[i * 8 + 6] += 0.0f; // side L - //dst[i * 8 + 7] += 0.0f; // side R - } - } - else - { - cellAudio.error("cellAudioAdd6chData(portNum=%d): invalid port.channel value (%d)", portNum, port.channel); - } - - return CELL_OK; -} - -s32 cellAudioMiscSetAccessoryVolume(u32 devNum, float volume) -{ - cellAudio.todo("cellAudioMiscSetAccessoryVolume(devNum=%d, volume=%f)", devNum, volume); - return CELL_OK; -} - -s32 cellAudioSendAck(u64 data3) -{ - cellAudio.todo("cellAudioSendAck(data3=0x%llx)", data3); - return CELL_OK; -} - -s32 cellAudioSetPersonalDevice(s32 iPersonalStream, s32 iDevice) -{ - cellAudio.todo("cellAudioSetPersonalDevice(iPersonalStream=%d, iDevice=%d)", iPersonalStream, iDevice); - return CELL_OK; -} - -s32 cellAudioUnsetPersonalDevice(s32 iPersonalStream) -{ - cellAudio.todo("cellAudioUnsetPersonalDevice(iPersonalStream=%d)", iPersonalStream); - return CELL_OK; -} - -Module<> cellAudio("cellAudio", []() -{ - g_audio.state = AUDIO_STATE_NOT_INITIALIZED; - g_audio.buffer = 0; - g_audio.indexes = 0; - - REG_FUNC(cellAudio, cellAudioInit); - REG_FUNC(cellAudio, cellAudioPortClose); - REG_FUNC(cellAudio, cellAudioPortStop); - REG_FUNC(cellAudio, cellAudioGetPortConfig); - REG_FUNC(cellAudio, cellAudioPortStart); - REG_FUNC(cellAudio, cellAudioQuit); - REG_FUNC(cellAudio, cellAudioPortOpen); - REG_FUNC(cellAudio, cellAudioSetPortLevel); - REG_FUNC(cellAudio, cellAudioCreateNotifyEventQueue); - REG_FUNC(cellAudio, cellAudioCreateNotifyEventQueueEx); - REG_FUNC(cellAudio, cellAudioMiscSetAccessoryVolume); - REG_FUNC(cellAudio, cellAudioSetNotifyEventQueue); - REG_FUNC(cellAudio, cellAudioSetNotifyEventQueueEx); - REG_FUNC(cellAudio, cellAudioGetPortTimestamp); - REG_FUNC(cellAudio, cellAudioAdd2chData); - REG_FUNC(cellAudio, cellAudioAdd6chData); - REG_FUNC(cellAudio, cellAudioAddData); - REG_FUNC(cellAudio, cellAudioGetPortBlockTag); - REG_FUNC(cellAudio, cellAudioRemoveNotifyEventQueue); - REG_FUNC(cellAudio, cellAudioRemoveNotifyEventQueueEx); - REG_FUNC(cellAudio, cellAudioSendAck); - REG_FUNC(cellAudio, cellAudioSetPersonalDevice); - REG_FUNC(cellAudio, cellAudioUnsetPersonalDevice); -}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp b/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp deleted file mode 100644 index 170e405e9e..0000000000 --- a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp +++ /dev/null @@ -1,455 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/System.h" -#include "Emu/state.h" -#include "Emu/SysCalls/Modules.h" - -#include "cellSysutil.h" -#include "cellNetCtl.h" - -#ifdef _WIN32 -#include -#include -#include - -#pragma comment(lib, "iphlpapi.lib") -#else -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -extern Module<> cellNetCtl; - -s32 cellNetCtlInit() -{ - cellNetCtl.warning("cellNetCtlInit()"); - - return CELL_OK; -} - -s32 cellNetCtlTerm() -{ - cellNetCtl.warning("cellNetCtlTerm()"); - - return CELL_OK; -} - -s32 cellNetCtlGetState(vm::ptr state) -{ - cellNetCtl.trace("cellNetCtlGetState(state=*0x%x)", state); - - switch (rpcs3::config.misc.net.status.value()) - { - case misc_net_status::ip_obtained: *state = CELL_NET_CTL_STATE_IPObtained; break; - case misc_net_status::obtaining_ip: *state = CELL_NET_CTL_STATE_IPObtaining; break; - case misc_net_status::connecting: *state = CELL_NET_CTL_STATE_Connecting; break; - case misc_net_status::disconnected: *state = CELL_NET_CTL_STATE_Disconnected; break; - - default: *state = CELL_NET_CTL_STATE_Disconnected; break; - } - - return CELL_OK; -} - -s32 cellNetCtlAddHandler(vm::ptr handler, vm::ptr arg, vm::ptr hid) -{ - cellNetCtl.todo("cellNetCtlAddHandler(handler=*0x%x, arg=*0x%x, hid=*0x%x)", handler, arg, hid); - - return CELL_OK; -} - -s32 cellNetCtlDelHandler(s32 hid) -{ - cellNetCtl.todo("cellNetCtlDelHandler(hid=0x%x)", hid); - - return CELL_OK; -} - -s32 cellNetCtlGetInfo(s32 code, vm::ptr info) -{ - cellNetCtl.todo("cellNetCtlGetInfo(code=0x%x (%s), info=*0x%x)", code, InfoCodeToName(code), info); - - if (code == CELL_NET_CTL_INFO_MTU) - { -#ifdef _WIN32 - ULONG bufLen = sizeof(PIP_ADAPTER_ADDRESSES) + 1; - PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(bufLen); - DWORD ret; - - ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &bufLen); - - if (ret == ERROR_BUFFER_OVERFLOW) - { - cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): GetAdaptersAddresses buffer overflow."); - free(pAddresses); - pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(bufLen); - - if (pAddresses == nullptr) - { - cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): Unable to allocate memory for pAddresses."); - return CELL_NET_CTL_ERROR_NET_CABLE_NOT_CONNECTED; - } - } - - ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &bufLen); - - if (ret == NO_ERROR) - { - PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses; - - for (int c = 0; c < rpcs3::config.misc.net._interface.value(); c++) - { - pCurrAddresses = pCurrAddresses->Next; - } - - info->mtu = pCurrAddresses->Mtu; - } - else - { - cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): Call to GetAdaptersAddresses failed. (%d)", ret); - info->mtu = 1500; // Seems to be the default value on Windows 10. - } - - free(pAddresses); -#else - struct ifaddrs *ifaddr, *ifa; - s32 family, n; - - if (getifaddrs(&ifaddr) == -1) - { - cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): Call to getifaddrs returned negative."); - } - - for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) - { - if (ifa->ifa_addr == nullptr) - { - continue; - } - - if (n < rpcs3::config.misc.net._interface.value()) - { - continue; - } - - family = ifa->ifa_addr->sa_family; - - if (family == AF_INET) - { - u32 fd = open("/proc/net/dev", O_RDONLY); - struct ifreq freq; - - if (ioctl(fd, SIOCGIFMTU, &freq) == -1) - { - cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): Call to ioctl failed."); - } - else - { - info->mtu = (u32)freq.ifr_mtu; - } - - close(fd); - } - } - - freeifaddrs(ifaddr); -#endif - } - else if (code == CELL_NET_CTL_INFO_LINK) - { - if (rpcs3::config.misc.net.status.value() == misc_net_status::ip_obtained) - { - info->link = CELL_NET_CTL_LINK_CONNECTED; - } - else - { - info->link = CELL_NET_CTL_LINK_DISCONNECTED; - } - } - else if (code == CELL_NET_CTL_INFO_IP_ADDRESS) - { - // 0.0.0.0 seems to be the default address when no ethernet cables are connected to the PS3 - strcpy_trunc(info->ip_address, "0.0.0.0"); - -#ifdef _WIN32 - ULONG bufLen = sizeof(IP_ADAPTER_INFO); - PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO*)malloc(bufLen); - DWORD ret; - - ret = GetAdaptersInfo(pAdapterInfo, &bufLen); - - if (ret == ERROR_BUFFER_OVERFLOW) - { - cellNetCtl.error("cellNetCtlGetInfo(IP_ADDRESS): GetAdaptersInfo buffer overflow."); - free(pAdapterInfo); - pAdapterInfo = (IP_ADAPTER_INFO*)malloc(bufLen); - - if (pAdapterInfo == nullptr) - { - cellNetCtl.error("cellNetCtlGetInfo(IP_ADDRESS): Unable to allocate memory for pAddresses."); - return CELL_NET_CTL_ERROR_NET_CABLE_NOT_CONNECTED; - } - } - - ret = GetAdaptersInfo(pAdapterInfo, &bufLen); - - if (ret == NO_ERROR) - { - PIP_ADAPTER_INFO pAdapter = pAdapterInfo; - - for (int c = 0; c < rpcs3::config.misc.net._interface.value(); c++) - { - pAdapter = pAdapter->Next; - } - - strcpy_trunc(info->ip_address, pAdapter->IpAddressList.IpAddress.String); - } - else - { - cellNetCtl.error("cellNetCtlGetInfo(IP_ADDRESS): Call to GetAdaptersInfo failed. (%d)", ret); - } - - free(pAdapterInfo); -#else - struct ifaddrs *ifaddr, *ifa; - s32 family, n; - - if (getifaddrs(&ifaddr) == -1) - { - cellNetCtl.error("cellNetCtlGetInfo(IP_ADDRESS): Call to getifaddrs returned negative."); - } - - for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) - { - if (ifa->ifa_addr == nullptr) - { - continue; - } - - if (n < rpcs3::config.misc.net._interface.value()) - { - continue; - } - - family = ifa->ifa_addr->sa_family; - - if (family == AF_INET) - { - strcpy_trunc(info->ip_address, ifa->ifa_addr->sa_data); - } - } - - freeifaddrs(ifaddr); -#endif - } - else if (code == CELL_NET_CTL_INFO_NETMASK) - { -#ifdef _WIN32 - ULONG bufLen = sizeof(IP_ADAPTER_INFO) + 1; - PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)malloc(bufLen); - DWORD ret; - - ret = GetAdaptersInfo(pAdapterInfo, &bufLen); - - if (ret == ERROR_BUFFER_OVERFLOW) - { - cellNetCtl.error("cellNetCtlGetInfo(INFO_NETMASK): GetAdaptersInfo buffer overflow."); - free(pAdapterInfo); - pAdapterInfo = (IP_ADAPTER_INFO*)malloc(bufLen); - - if (pAdapterInfo == nullptr) - { - cellNetCtl.error("cellNetCtlGetInfo(INFO_NETMASK): Unable to allocate memory for pAddresses."); - return CELL_NET_CTL_ERROR_NET_CABLE_NOT_CONNECTED; - } - } - - ret = GetAdaptersInfo(pAdapterInfo, &bufLen); - - if (ret == NO_ERROR) - { - PIP_ADAPTER_INFO pAdapter = pAdapterInfo; - - for (int c = 0; c < rpcs3::config.misc.net._interface.value(); c++) - { - pAdapter = pAdapter->Next; - } - - for (int c = 0; c < 4; c++) - { - info->netmask[c] = (s8)pAdapter->IpAddressList.IpMask.String; - } - } - else - { - cellNetCtl.error("cellNetCtlGetInfo(INFO_NETMASK): Call to GetAdaptersInfo failed. (%d)", ret); - // TODO: Is this the default netmask? - info->netmask[0] = 255; - info->netmask[1] = 255; - info->netmask[2] = 255; - info->netmask[3] = 0; - } - - free(pAdapterInfo); -#else - struct ifaddrs *ifaddr, *ifa; - s32 family, n; - - if (getifaddrs(&ifaddr) == -1) - { - cellNetCtl.error("cellNetCtlGetInfo(INFO_NETMASK): Call to getifaddrs returned negative."); - } - - for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) - { - if (ifa->ifa_addr == nullptr) - { - continue; - } - - if (n < rpcs3::config.misc.net._interface.value()) - { - continue; - } - - family = ifa->ifa_addr->sa_family; - - if (family == AF_INET) - { - strcpy_trunc(info->ip_address, ifa->ifa_netmask->sa_data); - } - } - - freeifaddrs(ifaddr); -#endif - } - - return CELL_OK; -} - -s32 cellNetCtlNetStartDialogLoadAsync(vm::ptr param) -{ - cellNetCtl.error("cellNetCtlNetStartDialogLoadAsync(param=*0x%x)", param); - - // TODO: Actually sign into PSN or an emulated network similar to PSN (ESN) - // TODO: Properly open the dialog prompt for sign in - sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_LOADED, 0); - sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED, 0); - - return CELL_OK; -} - -s32 cellNetCtlNetStartDialogAbortAsync() -{ - cellNetCtl.error("cellNetCtlNetStartDialogAbortAsync()"); - - return CELL_OK; -} - -s32 cellNetCtlNetStartDialogUnloadAsync(vm::ptr result) -{ - cellNetCtl.warning("cellNetCtlNetStartDialogUnloadAsync(result=*0x%x)", result); - - result->result = CELL_NET_CTL_ERROR_DIALOG_CANCELED; - sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_UNLOADED, 0); - - return CELL_OK; -} - -s32 cellNetCtlGetNatInfo(vm::ptr natInfo) -{ - cellNetCtl.todo("cellNetCtlGetNatInfo(natInfo=*0x%x)", natInfo); - - if (natInfo->size == 0) - { - cellNetCtl.error("cellNetCtlGetNatInfo : CELL_NET_CTL_ERROR_INVALID_SIZE"); - return CELL_NET_CTL_ERROR_INVALID_SIZE; - } - - return CELL_OK; -} - -s32 cellGameUpdateInit() -{ - throw EXCEPTION(""); -} - -s32 cellGameUpdateTerm() -{ - throw EXCEPTION(""); -} - - -s32 cellGameUpdateCheckStartAsync() -{ - throw EXCEPTION(""); -} - -s32 cellGameUpdateCheckFinishAsync() -{ - throw EXCEPTION(""); -} - -s32 cellGameUpdateCheckStartWithoutDialogAsync() -{ - throw EXCEPTION(""); -} - -s32 cellGameUpdateCheckAbort() -{ - throw EXCEPTION(""); -} - -s32 cellGameUpdateCheckStartAsyncEx() -{ - throw EXCEPTION(""); -} - -s32 cellGameUpdateCheckFinishAsyncEx() -{ - throw EXCEPTION(""); -} - -s32 cellGameUpdateCheckStartWithoutDialogAsyncEx() -{ - throw EXCEPTION(""); -} - - -Module<> cellNetCtl("cellNetCtl", []() -{ - REG_FUNC(cellNetCtl, cellNetCtlInit); - REG_FUNC(cellNetCtl, cellNetCtlTerm); - - REG_FUNC(cellNetCtl, cellNetCtlGetState); - REG_FUNC(cellNetCtl, cellNetCtlAddHandler); - REG_FUNC(cellNetCtl, cellNetCtlDelHandler); - - REG_FUNC(cellNetCtl, cellNetCtlGetInfo); - - REG_FUNC(cellNetCtl, cellNetCtlNetStartDialogLoadAsync); - REG_FUNC(cellNetCtl, cellNetCtlNetStartDialogAbortAsync); - REG_FUNC(cellNetCtl, cellNetCtlNetStartDialogUnloadAsync); - - REG_FUNC(cellNetCtl, cellNetCtlGetNatInfo); - - REG_FUNC(cellNetCtl, cellGameUpdateInit); - REG_FUNC(cellNetCtl, cellGameUpdateTerm); - - REG_FUNC(cellNetCtl, cellGameUpdateCheckStartAsync); - REG_FUNC(cellNetCtl, cellGameUpdateCheckFinishAsync); - REG_FUNC(cellNetCtl, cellGameUpdateCheckStartWithoutDialogAsync); - REG_FUNC(cellNetCtl, cellGameUpdateCheckAbort); - REG_FUNC(cellNetCtl, cellGameUpdateCheckStartAsyncEx); - REG_FUNC(cellNetCtl, cellGameUpdateCheckFinishAsyncEx); - REG_FUNC(cellNetCtl, cellGameUpdateCheckStartWithoutDialogAsyncEx); -}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp deleted file mode 100644 index da4df9b68e..0000000000 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp +++ /dev/null @@ -1,1287 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/System.h" -#include "Emu/SysCalls/Modules.h" - -#include "cellSysutil.h" -#include "Emu/SysCalls/Modules/cellVideoOut.h" -#include "Emu/RSX/GSManager.h" -#include "Emu/RSX/GSRender.h" -#include "cellResc.h" - -extern Module<> cellResc; - -extern s32 cellVideoOutConfigure(u32 videoOut, vm::ptr config, vm::ptr option, u32 waitForEvent); -extern s32 cellGcmSetFlipMode(u32 mode); -extern void cellGcmSetFlipHandler(vm::ptr handler); -extern void cellGcmSetVBlankHandler(vm::ptr handler); -extern s32 cellGcmAddressToOffset(u32 address, vm::ptr offset); -extern s32 cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height); -extern s32 cellGcmSetPrepareFlip(PPUThread& ppu, vm::ptr ctx, u32 id); -extern s32 cellGcmSetSecondVFrequency(u32 freq); -extern u32 cellGcmGetLabelAddress(u8 index); -extern u32 cellGcmGetTiledPitchSize(u32 size); - -CCellRescInternal* s_rescInternalInstance = nullptr; - -// Local Functions -s32 cellRescGetNumColorBuffers(u32 dstMode, u32 palTemporalMode, u32 reserved); - -// Help Functions -inline bool IsPal() { return s_rescInternalInstance->m_dstMode == CELL_RESC_720x576; } -inline bool IsPal60Hsync() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC); } -inline bool IsPalDrop() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_DROP); } -inline bool IsPalInterpolate() { - return (IsPal() && ((s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE) - || (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_30_DROP) - || (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE))); -} -inline bool IsNotPalInterpolate() { return !IsPalInterpolate(); } -inline bool IsPalTemporal() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode != CELL_RESC_PAL_50); } -inline bool IsNotPalTemporal() { return !IsPalTemporal(); } -inline bool IsNotPal() { return !IsPal(); } -inline bool IsGcmFlip() { - return (IsNotPal() || (IsPal() && (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_50 - || s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC))); -} -inline s32 GetNumColorBuffers(){ return IsPalInterpolate() ? 6 : (IsPalDrop() ? 3 : 2); } -inline bool IsInterlace() { return s_rescInternalInstance->m_initConfig.interlaceMode == CELL_RESC_INTERLACE_FILTER; } -inline bool IsTextureNR() { return !IsInterlace(); } - -static const float -PICTURE_SIZE = (1.0f), -UV_DELTA_PS = (1.f / 8.f), -UV_DELTA_LB = (1.f / 6.f), -XY_DELTA_LB = (1.f / 8.f), -PI = 3.141592741f; - -void BuildupVertexBufferNR() -{ - const float PX_FS = PICTURE_SIZE; - const float PY_FS = PICTURE_SIZE; - - const float UV_HALF = 0.5f; - const float UV_CENTER = 0.5f; - float U_FS = UV_HALF / s_rescInternalInstance->m_ratioAdjX; - float V_FS = UV_HALF / s_rescInternalInstance->m_ratioAdjY; - float U_FS0 = UV_CENTER - U_FS; - float V_FS0 = UV_CENTER - V_FS; - float U_FS1 = UV_CENTER + U_FS; - float V_FS1 = UV_CENTER + V_FS; - float V_LB = (UV_HALF + UV_DELTA_LB) / s_rescInternalInstance->m_ratioAdjY; - float V_LB0 = UV_CENTER - V_LB; - float V_LB1 = UV_CENTER + V_LB; - float U_PS = (UV_HALF - UV_DELTA_PS) / s_rescInternalInstance->m_ratioAdjX; - float U_PS0 = UV_CENTER - U_PS; - float U_PS1 = UV_CENTER + U_PS; - - auto vv = vm::ptr::make(s_rescInternalInstance->m_vertexArrayEA); - - if (s_rescInternalInstance->m_dstMode == CELL_RESC_720x480 || s_rescInternalInstance->m_dstMode == CELL_RESC_720x576) - { - switch((u32)s_rescInternalInstance->m_initConfig.ratioMode) - { - case CELL_RESC_LETTERBOX: - goto NR_LETTERBOX; - case CELL_RESC_PANSCAN: - goto NR_PANSCAN; - default: - goto NR_FULLSCREEN; - } - } - else - { - goto NR_FULLSCREEN; - } - -NR_FULLSCREEN: - vv->Px = -PX_FS; vv->Py = PY_FS; vv->u = U_FS0; vv->v = V_FS0; vv->u2 = 0.0f; vv->v2 = 0.0f; ++vv; - vv->Px = PX_FS; vv->Py = PY_FS; vv->u = U_FS1; vv->v = V_FS0; vv->u2 = 1.0f; vv->v2 = 0.0f; ++vv; - vv->Px = PX_FS; vv->Py = -PY_FS; vv->u = U_FS1; vv->v = V_FS1; vv->u2 = 1.0f; vv->v2 = 1.0f; ++vv; - vv->Px = -PX_FS; vv->Py = -PY_FS; vv->u = U_FS0; vv->v = V_FS1; vv->u2 = 0.0f; vv->v2 = 1.0f; ++vv; - s_rescInternalInstance->m_nVertex = VERTEX_NUMBER_NORMAL; - return; - -NR_LETTERBOX: - vv->Px = -PX_FS; vv->Py = PY_FS; vv->u = U_FS0; vv->v = V_LB0; vv->u2 = 0.0f; vv->v2 = 0.0f; ++vv; - vv->Px = PX_FS; vv->Py = PY_FS; vv->u = U_FS1; vv->v = V_LB0; vv->u2 = 1.0f; vv->v2 = 0.0f; ++vv; - vv->Px = PX_FS; vv->Py = -PY_FS; vv->u = U_FS1; vv->v = V_LB1; vv->u2 = 1.0f; vv->v2 = 1.0f; ++vv; - vv->Px = -PX_FS; vv->Py = -PY_FS; vv->u = U_FS0; vv->v = V_LB1; vv->u2 = 0.0f; vv->v2 = 1.0f; ++vv; - s_rescInternalInstance->m_nVertex = VERTEX_NUMBER_NORMAL; - return; - -NR_PANSCAN: - vv->Px = -PX_FS; vv->Py = PY_FS; vv->u = U_PS0; vv->v = V_FS0; vv->u2 = 0.0f; vv->v2 = 0.0f; ++vv; - vv->Px = PX_FS; vv->Py = PY_FS; vv->u = U_PS1; vv->v = V_FS0; vv->u2 = 1.0f; vv->v2 = 0.0f; ++vv; - vv->Px = PX_FS; vv->Py = -PY_FS; vv->u = U_PS1; vv->v = V_FS1; vv->u2 = 1.0f; vv->v2 = 1.0f; ++vv; - vv->Px = -PX_FS; vv->Py = -PY_FS; vv->u = U_PS0; vv->v = V_FS1; vv->u2 = 0.0f; vv->v2 = 1.0f; ++vv; - s_rescInternalInstance->m_nVertex = VERTEX_NUMBER_NORMAL; - return; -} - -void BuildupVertexBufferUN(s32 srcIdx) -{ - if (s_rescInternalInstance->m_bNewlyAdjustRatio) - { - s_rescInternalInstance->m_srcWidthInterlace = s_rescInternalInstance->m_rescSrc[srcIdx].width; - s_rescInternalInstance->m_srcHeightInterlace = s_rescInternalInstance->m_rescSrc[srcIdx].height; - s_rescInternalInstance->m_bNewlyAdjustRatio = false; - } - else - { - if (s_rescInternalInstance->m_srcWidthInterlace == s_rescInternalInstance->m_rescSrc[srcIdx].width - && s_rescInternalInstance->m_srcHeightInterlace == s_rescInternalInstance->m_rescSrc[srcIdx].height) - { - return; - } - else - { - s_rescInternalInstance->m_srcWidthInterlace = s_rescInternalInstance->m_rescSrc[srcIdx].width; - s_rescInternalInstance->m_srcHeightInterlace = s_rescInternalInstance->m_rescSrc[srcIdx].height; - } - } - - const float PX_FS = PICTURE_SIZE; - const float PY_FS = PICTURE_SIZE; - - float U_HALF = s_rescInternalInstance->m_rescSrc[srcIdx].width * 0.5f; - float V_HALF = s_rescInternalInstance->m_rescSrc[srcIdx].height * 0.5f; - float U_CENTER = U_HALF; - float V_CENTER = V_HALF; - float U_FS = U_HALF / s_rescInternalInstance->m_ratioAdjX; - float V_FS = V_HALF / s_rescInternalInstance->m_ratioAdjY; - float U_FS0 = U_CENTER - U_FS; - float V_FS0 = V_CENTER - V_FS; - float U_FS1 = U_CENTER + U_FS; - float V_FS1 = V_CENTER + V_FS; - float V_LB = V_HALF * (1.f + 2.f*UV_DELTA_LB) / s_rescInternalInstance->m_ratioAdjY; - float V_LB0 = V_CENTER - V_LB; - float V_LB1 = V_CENTER + V_LB; - float U_PS = U_HALF * (1.f - 2.f*UV_DELTA_PS) / s_rescInternalInstance->m_ratioAdjX; - float U_PS0 = U_CENTER - U_PS; - float U_PS1 = U_CENTER + U_PS; - float U2_FS0 = 0.0f; - float V2_FS0 = 0.0f; - float U2_FS1 = (float)s_rescInternalInstance->m_dstWidth; - float V2_FS1 = (float)s_rescInternalInstance->m_dstHeight; - - auto vv = vm::ptr::make(s_rescInternalInstance->m_vertexArrayEA); - - if (s_rescInternalInstance->m_dstMode == CELL_RESC_720x480 || s_rescInternalInstance->m_dstMode == CELL_RESC_720x576) - { - switch((u32)s_rescInternalInstance->m_initConfig.ratioMode) - { - case CELL_RESC_LETTERBOX: - goto UN_LETTERBOX; - case CELL_RESC_PANSCAN: - goto UN_PANSCAN; - default: - goto UN_FULLSCREEN; - } - } - else - { - goto UN_FULLSCREEN; - } - -UN_FULLSCREEN: - vv->Px = -PX_FS; vv->Py = PY_FS; vv->u = U_FS0; vv->v = V_FS0; vv->u2 = U2_FS0; vv->v2 = V2_FS0; ++vv; - vv->Px = PX_FS; vv->Py = PY_FS; vv->u = U_FS1; vv->v = V_FS0; vv->u2 = U2_FS1; vv->v2 = V2_FS0; ++vv; - vv->Px = PX_FS; vv->Py = -PY_FS; vv->u = U_FS1; vv->v = V_FS1; vv->u2 = U2_FS1; vv->v2 = V2_FS1; ++vv; - vv->Px = -PX_FS; vv->Py = -PY_FS; vv->u = U_FS0; vv->v = V_FS1; vv->u2 = U2_FS0; vv->v2 = V2_FS1; ++vv; - s_rescInternalInstance->m_nVertex = VERTEX_NUMBER_NORMAL; - return; - -UN_LETTERBOX: - vv->Px = -PX_FS; vv->Py = PY_FS; vv->u = U_FS0; vv->v = V_LB0; vv->u2 = U2_FS0; vv->v2 = V2_FS0; ++vv; - vv->Px = PX_FS; vv->Py = PY_FS; vv->u = U_FS1; vv->v = V_LB0; vv->u2 = U2_FS1; vv->v2 = V2_FS0; ++vv; - vv->Px = PX_FS; vv->Py = -PY_FS; vv->u = U_FS1; vv->v = V_LB1; vv->u2 = U2_FS1; vv->v2 = V2_FS1; ++vv; - vv->Px = -PX_FS; vv->Py = -PY_FS; vv->u = U_FS0; vv->v = V_LB1; vv->u2 = U2_FS0; vv->v2 = V2_FS1; ++vv; - s_rescInternalInstance->m_nVertex = VERTEX_NUMBER_NORMAL; - return; - -UN_PANSCAN: - vv->Px = -PX_FS; vv->Py = PY_FS; vv->u = U_PS0; vv->v = V_FS0; vv->u2 = U2_FS0; vv->v2 = V2_FS0; ++vv; - vv->Px = PX_FS; vv->Py = PY_FS; vv->u = U_PS1; vv->v = V_FS0; vv->u2 = U2_FS1; vv->v2 = V2_FS0; ++vv; - vv->Px = PX_FS; vv->Py = -PY_FS; vv->u = U_PS1; vv->v = V_FS1; vv->u2 = U2_FS1; vv->v2 = V2_FS1; ++vv; - vv->Px = -PX_FS; vv->Py = -PY_FS; vv->u = U_PS0; vv->v = V_FS1; vv->u2 = U2_FS0; vv->v2 = V2_FS1; ++vv; - s_rescInternalInstance->m_nVertex = VERTEX_NUMBER_NORMAL; - return; -} - -inline s32 InternalVersion(vm::ptr conf) -{ - switch ((u32)conf->size) - { - case 20: - return 1; - case 24: - return 2; - case 28: - return 3; - default: return -1; - } -} - -inline s32 InternalVersion() { - switch ((u32)s_rescInternalInstance->m_initConfig.size) - { - case 20: - return 1; - case 24: - return 2; - case 28: - return 3; - default: - return -1; - } -} - -u8 RescBufferMode2SysutilResolutionId(u32 bufferMode) -{ - switch (bufferMode) - { - case CELL_RESC_720x576: - return CELL_VIDEO_OUT_RESOLUTION_576; - case CELL_RESC_1280x720: - return CELL_VIDEO_OUT_RESOLUTION_720; - case CELL_RESC_1920x1080: - return CELL_VIDEO_OUT_RESOLUTION_1080; - default: - return CELL_VIDEO_OUT_RESOLUTION_480; - } -} - -u8 RescDstFormat2SysutilFormat(u32 dstFormat) -{ - switch (dstFormat) - { - case CELL_RESC_SURFACE_F_W16Z16Y16X16: - return CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_R16G16B16X16_FLOAT; - default: - return CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8; - } -} - -u8 GcmSurfaceFormat2GcmTextureFormat(u8 surfaceFormat, u8 surfaceType) -{ - u8 result = 0; - - switch (rsx::to_surface_color_format(surfaceFormat)) - { - case rsx::surface_color_format::a8r8g8b8: - result = CELL_GCM_TEXTURE_A8R8G8B8; - break; - case rsx::surface_color_format::w16z16y16x16: - result = CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT; - break; - default: - return 0xFF; //Error - } - - switch (surfaceType) - { - case CELL_GCM_SURFACE_PITCH: - result |= CELL_GCM_TEXTURE_LN; - break; - case CELL_GCM_SURFACE_SWIZZLE: - result |= CELL_GCM_TEXTURE_SZ; - break; - default: - return 0xFF; //Error - } - - result |= CELL_GCM_TEXTURE_NR; - - return result; -} - -s32 GetRescDestsIndex(u32 dstMode) -{ - switch(dstMode) - { - case CELL_RESC_720x480: - return 0; - case CELL_RESC_720x576: - return 1; - case CELL_RESC_1280x720: - return 2; - case CELL_RESC_1920x1080: - return 3; - default: - return -1; - } -} - -void GetScreenSize(u32 mode, s32 *width, s32 *height) -{ - switch (mode) - { - case CELL_RESC_720x480: - *width = 720; *height = 480; - break; - case CELL_RESC_720x576: - *width = 720; *height = 576; - break; - case CELL_RESC_1280x720: - *width = 1280; *height = 720; - break; - case CELL_RESC_1920x1080: - *width = 1920; *height = 1080; - break; - default: - *width = *height = 0; - break; - } -} - -s32 CalculateSurfaceByteSize(u32 mode, CellRescDsts *dsts) -{ - s32 width, height; - GetScreenSize(mode, &width, &height); - return dsts->pitch * roundup(height, dsts->heightAlign); -} - -s32 CalculateMaxColorBuffersSize() -{ - s32 oneBufSize, bufNum, totalBufSize, maxBufSize; - maxBufSize = 0; - - for (u32 bufMode = CELL_RESC_720x480; bufMode <= CELL_RESC_1920x1080; bufMode <<= 1) - { - if (s_rescInternalInstance->m_initConfig.supportModes & bufMode) - { - oneBufSize = CalculateSurfaceByteSize(bufMode, &(s_rescInternalInstance->m_rescDsts[GetRescDestsIndex(bufMode)])); - bufNum = cellRescGetNumColorBuffers(bufMode, s_rescInternalInstance->m_initConfig.palTemporalMode, 0); - totalBufSize = oneBufSize * bufNum; - maxBufSize = (maxBufSize > totalBufSize) ? maxBufSize : totalBufSize; - } - } - - return maxBufSize; -} - -bool CheckInitConfig(vm::ptr initConfig) -{ - if ((initConfig->resourcePolicy & ~((u32)0x3)) || (initConfig->supportModes & 0xF) == 0 || (initConfig->ratioMode > 2) || (initConfig->palTemporalMode > 5)) - { - return false; - } - - if ( InternalVersion() >= 2 ) - { - if (InternalVersion() == 2 && initConfig->interlaceMode > 1) - { - return false; - } - } - - if ( InternalVersion() >= 3 ) - { - if ((initConfig->interlaceMode > 4) || (initConfig->flipMode > 1)) - { - return false; - } - } - - return true; -} - -void InitMembers() -{ - s_rescInternalInstance->m_dstMode = (CellRescBufferMode)0; - s_rescInternalInstance->m_interlaceElement = CELL_RESC_ELEMENT_FLOAT; - s_rescInternalInstance->m_colorBuffersEA = 0; - s_rescInternalInstance->m_vertexArrayEA = 0; - s_rescInternalInstance->m_fragmentUcodeEA = 0; - s_rescInternalInstance->m_interlaceTableEA = 0; - s_rescInternalInstance->m_bufIdFront = 0; - s_rescInternalInstance->m_dstWidth = 0; - s_rescInternalInstance->m_dstHeight = 0; - s_rescInternalInstance->m_dstPitch = 0; - s_rescInternalInstance->m_srcWidthInterlace = 0; - s_rescInternalInstance->m_srcHeightInterlace = 0; - s_rescInternalInstance->m_dstBufInterval = 0; - s_rescInternalInstance->m_nVertex = 0; - s_rescInternalInstance->m_ratioAdjX = 1.f; - s_rescInternalInstance->m_ratioAdjY = 1.f; - s_rescInternalInstance->m_interlaceTableLength = 32; - s_rescInternalInstance->m_bInitialized = false; - s_rescInternalInstance->m_bNewlyAdjustRatio = false; - - s_rescInternalInstance->s_applicationVBlankHandler.set(0); - s_rescInternalInstance->s_applicationFlipHandler.set(0); - - //E PAL related variables - //s_rescInternalInstance->m_intrThread50 = 0; - //s_rescInternalInstance->m_lastDummyFlip = 0; - //s_rescInternalInstance->m_lastVsync60 = 0; - //s_rescInternalInstance->m_lastVsync50 = 0; - s_rescInternalInstance->m_bufIdFrontPrevDrop = 2; - s_rescInternalInstance->m_bufIdPalMidPrev = 4; - s_rescInternalInstance->m_bufIdPalMidNow = 5; - //s_rescInternalInstance->m_cgpTvalue = 0; - s_rescInternalInstance->m_isDummyFlipped = true; - s_rescInternalInstance->m_flexRatio = 0.f; // interpolate - s_rescInternalInstance->m_commandIdxCaF = 1; - s_rescInternalInstance->m_rcvdCmdIdx = 0; - - //s_rescInternalInstance->m_lastV60.idx = 0; - //s_rescInternalInstance->m_lastV60.time = Util::GetSystemTime(); - //s_rescInternalInstance->m_lastV50.idx = 0; - //s_rescInternalInstance->m_lastV50.time = Util::GetSystemTime(); - - //s_rescInternalInstance->m_feedback.interval60 = 1; - - for (s32 i = 0; im_rescSrc[i].format = 0; - s_rescInternalInstance->m_rescSrc[i].pitch = 0; - s_rescInternalInstance->m_rescSrc[i].width = 0; - s_rescInternalInstance->m_rescSrc[i].height = 0; - s_rescInternalInstance->m_rescSrc[i].offset = 0; - } - - for (s32 i = 0; im_dstOffsets[i] = 0; - } - - for (s32 i = 0; im_cgParamIndex[i] = 0xFF; - } - { - s_rescInternalInstance->m_rescDsts[0].format = CELL_RESC_SURFACE_A8R8G8B8; - s_rescInternalInstance->m_rescDsts[0].pitch = cellGcmGetTiledPitchSize(720 * 4); - s_rescInternalInstance->m_rescDsts[0].heightAlign = 8; - s_rescInternalInstance->m_rescDsts[1].format = CELL_RESC_SURFACE_A8R8G8B8; - s_rescInternalInstance->m_rescDsts[1].pitch = cellGcmGetTiledPitchSize(720 * 4); - s_rescInternalInstance->m_rescDsts[1].heightAlign = 8; - s_rescInternalInstance->m_rescDsts[2].format = CELL_RESC_SURFACE_A8R8G8B8; - s_rescInternalInstance->m_rescDsts[2].pitch = cellGcmGetTiledPitchSize(1280 * 4); - s_rescInternalInstance->m_rescDsts[2].heightAlign = 8; - s_rescInternalInstance->m_rescDsts[3].format = CELL_RESC_SURFACE_A8R8G8B8; - s_rescInternalInstance->m_rescDsts[3].pitch = cellGcmGetTiledPitchSize(1920 * 4); - s_rescInternalInstance->m_rescDsts[3].heightAlign = 8; - } -} - -void SetupRsxRenderingStates(vm::ptr& cntxt) -{ - //TODO: use cntxt - GSRender& r = Emu.GetGSManager().GetRender(); - - // FIXME: only RSX Thread can write rsx::method_registers - // Others threads must fill the command buffer or use another - // mechanism. - -// rsx::method_registers[NV4097_SET_COLOR_MASK] = -1; -// rsx::method_registers[NV4097_SET_DEPTH_MASK] = 0; -// rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE] = false; -// rsx::method_registers[NV4097_SET_BLEND_ENABLE] = false; -// rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] = false; -// r.m_set_logic_op = false; -// rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE] = false; -// r.m_set_depth_bounds_test = false; -// rsx::method_registers[NV4097_SET_DEPTH_TEST_ENABLE] = false; -// r.m_set_poly_offset_fill = false; -// r.m_set_stencil_test = false; -// r.m_set_two_sided_stencil_test_enable = false; -// r.m_set_two_side_light_enable = false; -// r.m_set_point_sprite_control = false; -// r.m_set_dither = true; -// r.m_set_shade_mode = true; r.m_shade_mode = CELL_GCM_SMOOTH; -// r.m_set_frequency_divider_operation = CELL_GCM_FREQUENCY_DIVIDE; - -// rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] = s_rescInternalInstance->m_dstWidth << 16; -// rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] = s_rescInternalInstance->m_dstHeight << 16; - -// r.m_set_scissor_horizontal = r.m_set_scissor_vertical = true; -// r.m_scissor_x = 0; -// r.m_scissor_y = 0; -// r.m_scissor_w = s_rescInternalInstance->m_dstWidth; -// r.m_scissor_h = s_rescInternalInstance->m_dstHeight; - -// r.m_width = s_rescInternalInstance->m_dstWidth; -// r.m_height = s_rescInternalInstance->m_dstHeight; - -// r.m_surface_depth_format = 2; -// rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET] = 1; - - if (IsPalInterpolate()) - { - //MRT - //GcmCmdTypePrefix::cellGcmSetColorMaskMrt(con, CELL_GCM_COLOR_MASK_MRT1_A | CELL_GCM_COLOR_MASK_MRT1_R | CELL_GCM_COLOR_MASK_MRT1_G | CELL_GCM_COLOR_MASK_MRT1_B); - } -} - -void SetupVertexArrays(vm::ptr& cntxt) -{ - GSRender& r = Emu.GetGSManager().GetRender(); - - //TODO -} - -void SetupSurfaces(vm::ptr& cntxt) -{ - bool isMrt; - u32 dstOffset0, dstOffset1; - - if (IsNotPalInterpolate()) - { - isMrt = false; - dstOffset0 = s_rescInternalInstance->m_dstOffsets[s_rescInternalInstance->m_bufIdFront]; - dstOffset1 = 0; - } - else - { - isMrt = true; - dstOffset0 = s_rescInternalInstance->m_dstOffsets[s_rescInternalInstance->m_bufIdFront]; - dstOffset1 = s_rescInternalInstance->m_dstOffsets[s_rescInternalInstance->m_bufIdPalMidNow]; - } - - GSRender& r = Emu.GetGSManager().GetRender(); - - // FIXME: only RSX Thread can write rsx::method_registers - // Others threads must fill the command buffer or use another - // mechanism. - -// r.m_surface_type = CELL_GCM_SURFACE_PITCH; -// r.m_surface_antialias = CELL_GCM_SURFACE_CENTER_1; -// r.m_surface_color_format = (u8)s_rescInternalInstance->m_pRescDsts->format; -/* rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET] = (!isMrt) ? CELL_GCM_SURFACE_TARGET_0 : CELL_GCM_SURFACE_TARGET_MRT1; - //surface.colorLocation[0] = CELL_GCM_LOCATION_LOCAL; - rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET] = dstOffset0; - rsx::method_registers[NV4097_SET_SURFACE_PITCH_A] = s_rescInternalInstance->m_dstPitch; - //surface.colorLocation[1] = CELL_GCM_LOCATION_LOCAL; - rsx::method_registers[NV4097_SET_SURFACE_COLOR_BOFFSET] = (!isMrt) ? 0 : dstOffset1; - rsx::method_registers[NV4097_SET_SURFACE_PITCH_B] = (!isMrt) ? 64 : s_rescInternalInstance->m_dstPitch; - //surface.colorLocation[2] = CELL_GCM_LOCATION_LOCAL; - rsx::method_registers[NV4097_SET_SURFACE_COLOR_COFFSET] = 0; - rsx::method_registers[NV4097_SET_SURFACE_PITCH_C] = 64; - //surface.colorLocation[3] = CELL_GCM_LOCATION_LOCAL; - rsx::method_registers[NV4097_SET_SURFACE_COLOR_DOFFSET] = 0; - rsx::method_registers[NV4097_SET_SURFACE_PITCH_D] = 64; -// r.m_surface_depth_format = CELL_GCM_SURFACE_Z24S8; - //surface.depthLocation = CELL_GCM_LOCATION_LOCAL; - rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET]; - rsx::method_registers[NV4097_SET_SURFACE_PITCH_Z] = 64; -// r.m_surface_width = s_rescInternalInstance->m_dstWidth; -// r.m_surface_height = s_rescInternalInstance->m_dstHeight; -// r.m_surface_clip_x = 0;*/ -// r.m_surface_clip_y = 0; -} - -// Module<> Functions -s32 cellRescInit(vm::ptr initConfig) -{ - cellResc.warning("cellRescInit(initConfig=*0x%x)", initConfig); - - if (s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescInit : CELL_RESC_ERROR_REINITIALIZED"); - return CELL_RESC_ERROR_REINITIALIZED; - } - - if (InternalVersion(initConfig) == -1 || !CheckInitConfig(initConfig)) - { - cellResc.error("cellRescInit : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - InitMembers(); - s_rescInternalInstance->m_initConfig = *initConfig; // TODO: This may be incompatible with older binaries - s_rescInternalInstance->m_bInitialized = true; - - return CELL_OK; -} - -void cellRescExit() -{ - cellResc.warning("cellRescExit()"); - - if (!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescExit(): not initialized"); - return; - } - - if (IsPalTemporal()) - { - cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_DISABLE); - cellGcmSetVBlankHandler(vm::null); - //GcmSysTypePrefix::cellGcmSetSecondVHandler(NULL); - - if (IsPalInterpolate()) - { - // TODO: ExitSystemResource() - //s32 ret = ExitSystemResource(); - //if (ret != CELL_OK) - //{ - // cellResc.error("failed to clean up system resources.. continue. 0x%x\n", ret); - //} - } - } - - s_rescInternalInstance->m_bInitialized = false; -} - -s32 cellRescVideoOutResolutionId2RescBufferMode(u32 resolutionId, vm::ptr bufferMode) -{ - cellResc.trace("cellRescVideoOutResolutionId2RescBufferMode(resolutionId=%d, bufferMode=*0x%x)", resolutionId, bufferMode); - - switch (resolutionId) - { - case CELL_VIDEO_OUT_RESOLUTION_1080: - *bufferMode = CELL_RESC_1920x1080; - break; - case CELL_VIDEO_OUT_RESOLUTION_720: - *bufferMode = CELL_RESC_1280x720; - break; - case CELL_VIDEO_OUT_RESOLUTION_480: - *bufferMode = CELL_RESC_720x480; - break; - case CELL_VIDEO_OUT_RESOLUTION_576: - *bufferMode = CELL_RESC_720x576; - break; - default: - cellResc.error("cellRescVideoOutResolutionId2RescBufferMod : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - return CELL_OK; -} - -s32 cellRescSetDsts(u32 dstsMode, vm::ptr dsts) -{ - cellResc.trace("cellRescSetDsts(dstsMode=%d, dsts=*0x%x)", dstsMode, dsts); - - if (!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescSetDst : CELL_RESC_ERROR_NOT_INITIALIZED"); - return CELL_RESC_ERROR_NOT_INITIALIZED; - } - - if ((dstsMode != CELL_RESC_720x480) && (dstsMode != CELL_RESC_720x576) && (dstsMode != CELL_RESC_1280x720) && (dstsMode != CELL_RESC_1920x1080)) - { - cellResc.error("cellRescSetDsts : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - s_rescInternalInstance->m_rescDsts[GetRescDestsIndex(dstsMode)] = *dsts; - - return CELL_OK; -} - -void SetVBlankHandler(vm::ptr handler) -{ - if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0) - { - // If this function is called before SetDisplayMode, handler should be stored and set it properly later in SetDisplayMode. - s_rescInternalInstance->s_applicationVBlankHandler = handler; - return; - } - - if (IsNotPalTemporal()) - { - cellGcmSetVBlankHandler(handler); - s_rescInternalInstance->s_applicationVBlankHandler.set(0); - } - else if (IsPal60Hsync()) - { - //cellGcmSetSecondVHandler(handler); - s_rescInternalInstance->s_applicationVBlankHandler.set(0); - } - else - { - s_rescInternalInstance->s_applicationVBlankHandler = handler; - } -} - - -void SetFlipHandler(vm::ptr handler) -{ - if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0) - { - // If this function is called before SetDisplayMode, handler should be stored and set it properly later in SetDisplayMode. - s_rescInternalInstance->s_applicationFlipHandler = handler; - return; - } - - if (IsGcmFlip()) - { - cellGcmSetFlipHandler(handler); - s_rescInternalInstance->s_applicationFlipHandler.set(0); - } - else - { - s_rescInternalInstance->s_applicationFlipHandler = handler; - } -} - -s32 cellRescSetDisplayMode(u32 displayMode) -{ - cellResc.warning("cellRescSetDisplayMode(displayMode=%d)", displayMode); - - if (!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescSetDisplayMode : CELL_RESC_ERROR_NOT_INITIALIZED"); - return CELL_RESC_ERROR_NOT_INITIALIZED; - } - - if (!(s_rescInternalInstance->m_initConfig.supportModes & displayMode)) - { - cellResc.error("cellRescSetDisplayMode : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - if ((displayMode != CELL_RESC_720x480) && (displayMode != CELL_RESC_720x576) && - (displayMode != CELL_RESC_1280x720) && (displayMode != CELL_RESC_1920x1080)) - { - cellResc.error("cellRescSetDisplayMode : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - s_rescInternalInstance->m_dstMode = displayMode; - - if ((IsPalInterpolate() || IsPalDrop()) && s_rescInternalInstance->m_initConfig.flipMode == CELL_RESC_DISPLAY_HSYNC) - { - cellResc.error("cellRescSetDisplayMode : CELL_RESC_ERROR_BAD_COMBINATIONT"); - return CELL_RESC_ERROR_BAD_COMBINATION; - } - - if (IsPal60Hsync() && s_rescInternalInstance->m_initConfig.flipMode==CELL_RESC_DISPLAY_VSYNC) - { - cellResc.error("cellRescSetDisplayMode : CELL_RESC_ERROR_BAD_COMBINATIONT"); - return CELL_RESC_ERROR_BAD_COMBINATION; - } - - s_rescInternalInstance->m_pRescDsts = &s_rescInternalInstance->m_rescDsts[GetRescDestsIndex(displayMode)]; - GetScreenSize(s_rescInternalInstance->m_dstMode, &(s_rescInternalInstance->m_dstWidth), &(s_rescInternalInstance->m_dstHeight)); - - s_rescInternalInstance->m_dstPitch = s_rescInternalInstance->m_pRescDsts->pitch; - s_rescInternalInstance->m_dstBufInterval = s_rescInternalInstance->m_dstPitch * roundup(s_rescInternalInstance->m_dstHeight, s_rescInternalInstance->m_pRescDsts->heightAlign); - - /*if (IsPalInterpolate()) { - if(IsInterlace()) m_pCFragmentShader = m_pCFragmentShaderArray[RESC_SHADER_DEFAULT_INTERLACE_PAL]; - else m_pCFragmentShader = m_pCFragmentShaderArray[RESC_SHADER_DEFAULT_BILINEAR_PAL]; - } else { - if(IsInterlace()) m_pCFragmentShader = m_pCFragmentShaderArray[RESC_SHADER_DEFAULT_INTERLACE]; - else m_pCFragmentShader = m_pCFragmentShaderArray[RESC_SHADER_DEFAULT_BILINEAR]; - }*/ - - vm::var videocfg; - videocfg->resolutionId = RescBufferMode2SysutilResolutionId(s_rescInternalInstance->m_dstMode); - videocfg->format = RescDstFormat2SysutilFormat(s_rescInternalInstance->m_pRescDsts->format ); - videocfg->aspect = CELL_VIDEO_OUT_ASPECT_AUTO; - videocfg->pitch = s_rescInternalInstance->m_dstPitch; - - cellVideoOutConfigure(CELL_VIDEO_OUT_PRIMARY, videocfg, vm::null, 0); - - if (IsPalInterpolate()) - { - //s32 ret = InitSystemResource(); - //if (ret) return ret; - //InitLabels(); - cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); - //cellGcmSetVBlankHandler(IntrHandler50); - //cellGcmSetSecondVHandler(IntrHandler60); - cellGcmSetFlipHandler(vm::null); - } - else if (IsPalDrop()) - { - //InitLabels(); - cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); - cellGcmSetVBlankHandler(vm::null); - //cellGcmSetSecondVHandler(IntrHandler60Drop); - cellGcmSetFlipHandler(vm::null); - } - else if (IsPal60Hsync()) - { - cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); - cellGcmSetVBlankHandler(vm::null); - } - - if (s_rescInternalInstance->s_applicationVBlankHandler) SetVBlankHandler(s_rescInternalInstance->s_applicationVBlankHandler); - if (s_rescInternalInstance->s_applicationFlipHandler) SetFlipHandler(s_rescInternalInstance->s_applicationFlipHandler); - cellGcmSetFlipMode((s_rescInternalInstance->m_initConfig.flipMode == CELL_RESC_DISPLAY_VSYNC) ? CELL_GCM_DISPLAY_VSYNC : CELL_GCM_DISPLAY_HSYNC); - - return CELL_OK; -} - -s32 cellRescAdjustAspectRatio(float horizontal, float vertical) -{ - cellResc.warning("cellRescAdjustAspectRatio(horizontal=%f, vertical=%f)", horizontal, vertical); - - if (!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescAdjustAspectRatio : CELL_RESC_ERROR_NOT_INITIALIZED"); - return CELL_RESC_ERROR_NOT_INITIALIZED; - } - - if ((horizontal < 0.5f || 2.f < horizontal) || (vertical < 0.5f || 2.f < vertical)) - { - cellResc.error("cellRescAdjustAspectRatio : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - s_rescInternalInstance->m_ratioAdjX = horizontal; - s_rescInternalInstance->m_ratioAdjY = vertical; - - if (s_rescInternalInstance->m_vertexArrayEA) - { - if (IsTextureNR()) - { - BuildupVertexBufferNR(); - } - else - { - s_rescInternalInstance->m_bNewlyAdjustRatio = true; - } - } - - return CELL_OK; -} - -s32 cellRescSetPalInterpolateDropFlexRatio(float ratio) -{ - cellResc.warning("cellRescSetPalInterpolateDropFlexRatio(ratio=%f)", ratio); - - if (!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescSetPalInterpolateDropFlexRatio : CELL_RESC_ERROR_NOT_INITIALIZED"); - return CELL_RESC_ERROR_NOT_INITIALIZED; - } - - if (ratio < 0.f || 1.f < ratio) - { - cellResc.error("cellRescSetPalInterpolateDropFlexRatio : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - s_rescInternalInstance->m_flexRatio = ratio; - - return CELL_OK; -} - -s32 cellRescGetBufferSize(vm::ptr colorBuffers, vm::ptr vertexArray, vm::ptr fragmentShader) -{ - cellResc.warning("cellRescGetBufferSize(colorBuffers=*0x%x, vertexArray=*0x%x, fragmentShader=*0x%x)", colorBuffers, vertexArray, fragmentShader); - - if (!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescGetBufferSize : CELL_RESC_ERROR_NOT_INITIALIZED"); - return CELL_RESC_ERROR_NOT_INITIALIZED; - } - - s32 colorBuffersSize, vertexArraySize, fragmentUcodeSize; - if (s_rescInternalInstance->m_initConfig.resourcePolicy & CELL_RESC_MINIMUM_VRAM) - { - colorBuffersSize = s_rescInternalInstance->m_dstBufInterval * GetNumColorBuffers(); - vertexArraySize = 0x180; //sizeof(RescVertex_t) * VERTEX_NUMBER_RESERVED; - //fragmentUcodeSize = m_pCFragmentShader->GetUcodeSize(); - fragmentUcodeSize = 0x300; - } - else //CELL_RESC_CONSTANT_VRAM - { - colorBuffersSize = CalculateMaxColorBuffersSize(); - vertexArraySize = 0x180; //sizeof(RescVertex_t) * VERTEX_NUMBER_RESERVED; - fragmentUcodeSize = 0x300; - } - - if (colorBuffers) - { - *colorBuffers = colorBuffersSize; - } - - if (vertexArray) - { - *vertexArray = vertexArraySize; - } - - if (fragmentShader) - { - *fragmentShader = fragmentUcodeSize; - } - - return CELL_OK; -} - -s32 cellRescGetNumColorBuffers(u32 dstMode, u32 palTemporalMode, u32 reserved) -{ - cellResc.trace("cellRescGetNumColorBuffers(dstMode=%d, palTemporalMode=%d, reserved=%d)", dstMode, palTemporalMode, reserved); - - if (reserved != 0) - { - cellResc.error("cellRescGetNumColorBuffers : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - return dstMode==CELL_RESC_720x576 - ? ((palTemporalMode==CELL_RESC_PAL_60_INTERPOLATE || - palTemporalMode==CELL_RESC_PAL_60_INTERPOLATE_30_DROP || - palTemporalMode==CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE) - ? 6 - : (palTemporalMode==CELL_RESC_PAL_60_DROP - ? 3 - : 2)) - : 2; -} - -s32 cellRescGcmSurface2RescSrc(vm::ptr gcmSurface, vm::ptr rescSrc) -{ - cellResc.trace("cellRescGcmSurface2RescSrc(gcmSurface=*0x%x, rescSrc=*0x%x)", gcmSurface, rescSrc); - - u8 textureFormat = GcmSurfaceFormat2GcmTextureFormat(gcmSurface->colorFormat, gcmSurface->type); - s32 xW = 1, xH = 1; - - switch(rsx::to_surface_antialiasing(gcmSurface->antialias)) - { - case rsx::surface_antialiasing::square_rotated_4_samples: - xW=xH=2; - break; - case rsx::surface_antialiasing::square_centered_4_samples: - xW=xH=2; - break; - case rsx::surface_antialiasing::diagonal_centered_2_samples: - xW=2; - break; - default: - break; - } - - rescSrc->format = textureFormat; - rescSrc->pitch = gcmSurface->colorPitch[0]; - rescSrc->width = gcmSurface->width * xW; - rescSrc->height = gcmSurface->height * xH; - rescSrc->offset = gcmSurface->colorOffset[0]; - - return CELL_OK; -} - -s32 cellRescSetSrc(s32 idx, vm::ptr src) -{ - cellResc.trace("cellRescSetSrc(idx=0x%x, src=*0x%x)", idx, src); - - if(!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescSetSrc : CELL_RESC_ERROR_NOT_INITIALIZED"); - return CELL_RESC_ERROR_NOT_INITIALIZED; - } - - if (idx < 0 || idx >= SRC_BUFFER_NUM || src->width < 1 || src->width > 4096 || src->height < 1 || src->height > 4096) - { - cellResc.error("cellRescSetSrc : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - cellResc.trace(" *** format=0x%x", src->format); - cellResc.trace(" *** pitch=%d", src->pitch); - cellResc.trace(" *** width=%d", src->width); - cellResc.trace(" *** height=%d", src->height); - cellResc.trace(" *** offset=0x%x", src->offset); - - s_rescInternalInstance->m_rescSrc[idx] = *src; - - cellGcmSetDisplayBuffer(idx, src->offset, src->pitch, src->width, src->height); - - return 0; -} - -s32 cellRescSetConvertAndFlip(PPUThread& ppu, vm::ptr cntxt, s32 idx) -{ - cellResc.trace("cellRescSetConvertAndFlip(cntxt=*0x%x, idx=0x%x)", cntxt, idx); - - if(!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescSetConvertAndFlip : CELL_RESC_ERROR_NOT_INITIALIZED"); - return CELL_RESC_ERROR_NOT_INITIALIZED; - } - - if(idx < 0 || SRC_BUFFER_NUM <= idx) - { - cellResc.error("cellRescSetConvertAndFlip : CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - - if (!IsTextureNR()) - { - BuildupVertexBufferUN(idx); - } - - // Setup GPU internal status - SetupRsxRenderingStates(cntxt); - - // Setup vertex array pointers - SetupVertexArrays(cntxt); - - // Setup surface - SetupSurfaces(cntxt); - - //TODO: ? - - cellGcmSetPrepareFlip(ppu, cntxt, idx); - - return CELL_OK; -} - -s32 cellRescSetWaitFlip() -{ - cellResc.warning("cellRescSetWaitFlip()"); - - // TODO: emit RSX command for "wait flip" operation - - return CELL_OK; -} - -s32 cellRescSetBufferAddress(vm::ptr colorBuffers, vm::ptr vertexArray, vm::ptr fragmentShader) -{ - cellResc.warning("cellRescSetBufferAddress(colorBuffers=*0x%x, vertexArray=*0x%x, fragmentShader=*0x%x)", colorBuffers, vertexArray, fragmentShader); - - if(!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescSetBufferAddress : CELL_RESC_ERROR_NOT_INITIALIZED"); - return CELL_RESC_ERROR_NOT_INITIALIZED; - } - - if(colorBuffers.addr() % COLOR_BUFFER_ALIGNMENT || vertexArray.addr() % VERTEX_BUFFER_ALIGNMENT || fragmentShader.addr() % FRAGMENT_SHADER_ALIGNMENT) - { - cellResc.error("cellRescSetBufferAddress : CELL_RESC_ERROR_BAD_ALIGNMENT"); - return CELL_RESC_ERROR_BAD_ALIGNMENT; - } - - s_rescInternalInstance->m_colorBuffersEA = colorBuffers.addr(); - s_rescInternalInstance->m_vertexArrayEA = vertexArray.addr(); - s_rescInternalInstance->m_fragmentUcodeEA = fragmentShader.addr(); - - vm::var dstOffset; - cellGcmAddressToOffset(s_rescInternalInstance->m_colorBuffersEA, dstOffset); - - for (s32 i=0; im_dstOffsets[i] = *dstOffset + i * s_rescInternalInstance->m_dstBufInterval; - } - - for (s32 i=0; im_dstOffsets[i], s_rescInternalInstance->m_dstPitch, s_rescInternalInstance->m_dstWidth, s_rescInternalInstance->m_dstHeight); - if (ret) return ret; - } - - if (IsTextureNR()) - { - BuildupVertexBufferNR(); - } - - //TODO: ? - - return CELL_OK; -} - -void cellRescSetFlipHandler(vm::ptr handler) -{ - cellResc.warning("cellRescSetFlipHandler(handler=*0x%x)", handler); - - Emu.GetGSManager().GetRender().flip_handler = handler; -} - -void cellRescResetFlipStatus() -{ - cellResc.trace("cellRescResetFlipStatus()"); - - Emu.GetGSManager().GetRender().flip_status = 1; -} - -s32 cellRescGetFlipStatus() -{ - cellResc.trace("cellRescGetFlipStatus()"); - - return Emu.GetGSManager().GetRender().flip_status; -} - -s32 cellRescGetRegisterCount() -{ - UNIMPLEMENTED_FUNC(cellResc); - return CELL_OK; -} - -u64 cellRescGetLastFlipTime() -{ - cellResc.trace("cellRescGetLastFlipTime()"); - - return Emu.GetGSManager().GetRender().last_flip_time; -} - -s32 cellRescSetRegisterCount() -{ - UNIMPLEMENTED_FUNC(cellResc); - return CELL_OK; -} - -void cellRescSetVBlankHandler(vm::ptr handler) -{ - cellResc.warning("cellRescSetVBlankHandler(handler=*0x%x)", handler); - - Emu.GetGSManager().GetRender().vblank_handler = handler; -} - -u16 FloatToHalf(float val) -{ - u8 *tmp = (u8*)&val; - u32 bits = ((u32)tmp[0] << 24) | ((u32)tmp[1] << 16) | ((u32)tmp[2] << 8) | (u32)tmp[3]; - - if (bits == 0) - { - return 0; - } - s32 e = ((bits & 0x7f800000) >> 23) - 127 + 15; - if (e < 0) - { - return 0; - } - else if (e > 31) - { - e = 31; - } - u32 s = bits & 0x80000000; - u32 m = bits & 0x007fffff; - - return ((s >> 16) & 0x8000) | ((e << 10) & 0x7c00) | ((m >> 13) & 0x03ff); -} - -static void blackman(float window[]) -{ - const float x0 = ((1.f * 2.f*PI) / 5.f) - PI; - const float x1 = ((2.f * 2.f*PI) / 5.f) - PI; - const float x2 = ((3.f * 2.f*PI) / 5.f) - PI; - const float x3 = ((4.f * 2.f*PI) / 5.f) - PI; - - const float a0 = 0.42f + (0.50f * cosf(x0)) + (0.08f * cosf(2.f*x0)); - const float a1 = 0.42f + (0.50f * cosf(x1)) + (0.08f * cosf(2.f*x1)); - const float a2 = 0.42f + (0.50f * cosf(x2)) + (0.08f * cosf(2.f*x2)); - const float a3 = 0.42f + (0.50f * cosf(x3)) + (0.08f * cosf(2.f*x3)); - - window[0] = ((100.f - SEVIRITY) / 100.f + SEVIRITY / 100.f*a0); - window[1] = ((100.f - SEVIRITY) / 100.f + SEVIRITY / 100.f*a1); - window[2] = ((100.f - SEVIRITY) / 100.f + SEVIRITY / 100.f*a2); - window[3] = ((100.f - SEVIRITY) / 100.f + SEVIRITY / 100.f*a3); -} - -s32 CreateInterlaceTable(u32 ea_addr, float srcH, float dstH, CellRescTableElement depth, s32 length) -{ - float phi[4], transient[4]; - float y_fraction; - float bandwidth = 0.5f / (srcH / dstH); - float phi_b = 2.f * PI * bandwidth; - float window[4]; - auto buf16 = vm::ptr::make(ea_addr); - auto buf32 = vm::ptr::make(ea_addr); - - blackman(window); - - for (s32 i = 0; i 1E-10) ? (sinf(phi[0]) / phi[0] * window[0]) : window[0]; - transient[1] = (fabsf(phi[1]) > 1E-10) ? (sinf(phi[1]) / phi[1] * window[1]) : window[1]; - transient[2] = (fabsf(phi[2]) > 1E-10) ? (sinf(phi[2]) / phi[2] * window[2]) : window[2]; - transient[3] = (fabsf(phi[3]) > 1E-10) ? (sinf(phi[3]) / phi[3] * window[3]) : window[3]; - - float total4 = transient[0] + transient[1] + transient[2] + transient[3]; - - if (depth == CELL_RESC_ELEMENT_HALF) - { - buf16[0] = FloatToHalf(transient[0] / total4); - buf16[1] = FloatToHalf(transient[1] / total4); - buf16[2] = FloatToHalf(transient[2] / total4); - buf16[3] = FloatToHalf(transient[3] / total4); - buf16 += 4; - } - else - { - buf32[0] = transient[0] / total4; - buf32[1] = transient[1] / total4; - buf32[2] = transient[2] / total4; - buf32[3] = transient[3] / total4; - buf32 += 4; - } - } - return CELL_OK; -} - -s32 cellRescCreateInterlaceTable(u32 ea_addr, float srcH, CellRescTableElement depth, s32 length) -{ - cellResc.warning("cellRescCreateInterlaceTable(ea_addr=0x%x, srcH=%f, depth=%d, length=%d)", ea_addr, srcH, depth, length); - - if (!s_rescInternalInstance->m_bInitialized) - { - cellResc.error("cellRescCreateInterlaceTable: CELL_RESC_ERROR_NOT_INITIALIZED"); - return CELL_RESC_ERROR_NOT_INITIALIZED; - } - - if ((ea_addr == 0) || (srcH <= 0.f) || (!(depth == CELL_RESC_ELEMENT_HALF || depth == CELL_RESC_ELEMENT_FLOAT)) || (length <= 0)) - { - cellResc.error("cellRescCreateInterlaceTable: CELL_RESC_ERROR_BAD_ARGUMENT"); - return CELL_RESC_ERROR_BAD_ARGUMENT; - } - - if (s_rescInternalInstance->m_dstHeight == 0) - { - cellResc.error("cellRescCreateInterlaceTable: CELL_RESC_ERROR_BAD_COMBINATION"); - return CELL_RESC_ERROR_BAD_COMBINATION; - } - - float ratioModeCoefficient = (s_rescInternalInstance->m_initConfig.ratioMode != CELL_RESC_LETTERBOX) ? 1.f : (1.f - 2.f * XY_DELTA_LB); - float dstH = s_rescInternalInstance->m_dstHeight * ratioModeCoefficient * s_rescInternalInstance->m_ratioAdjY; - - if (s32 retValue = CreateInterlaceTable(ea_addr, srcH, dstH, depth, length)) - { - return retValue; - } - else - { - s_rescInternalInstance->m_interlaceTableEA = ea_addr; - s_rescInternalInstance->m_interlaceElement = depth; - s_rescInternalInstance->m_interlaceTableLength = length; - return CELL_OK; - } -} - - -Module<> cellResc("cellResc", []() -{ - s_rescInternalInstance = new CCellRescInternal(); - - cellResc.on_stop = []() - { - delete s_rescInternalInstance; - }; - - REG_FUNC(cellResc, cellRescSetConvertAndFlip); - REG_FUNC(cellResc, cellRescSetWaitFlip); - REG_FUNC(cellResc, cellRescSetFlipHandler); - REG_FUNC(cellResc, cellRescGcmSurface2RescSrc); - REG_FUNC(cellResc, cellRescGetNumColorBuffers); - REG_FUNC(cellResc, cellRescSetDsts); - REG_FUNC(cellResc, cellRescResetFlipStatus); - REG_FUNC(cellResc, cellRescSetPalInterpolateDropFlexRatio); - REG_FUNC(cellResc, cellRescGetRegisterCount); - REG_FUNC(cellResc, cellRescAdjustAspectRatio); - REG_FUNC(cellResc, cellRescSetDisplayMode); - REG_FUNC(cellResc, cellRescExit); - REG_FUNC(cellResc, cellRescInit); - REG_FUNC(cellResc, cellRescGetBufferSize); - REG_FUNC(cellResc, cellRescGetLastFlipTime); - REG_FUNC(cellResc, cellRescSetSrc); - REG_FUNC(cellResc, cellRescSetRegisterCount); - REG_FUNC(cellResc, cellRescSetBufferAddress); - REG_FUNC(cellResc, cellRescGetFlipStatus); - REG_FUNC(cellResc, cellRescVideoOutResolutionId2RescBufferMode); - REG_FUNC(cellResc, cellRescSetVBlankHandler); - REG_FUNC(cellResc, cellRescCreateInterlaceTable); -}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellRtc.cpp b/rpcs3/Emu/SysCalls/Modules/cellRtc.cpp deleted file mode 100644 index d36da41c37..0000000000 --- a/rpcs3/Emu/SysCalls/Modules/cellRtc.cpp +++ /dev/null @@ -1,488 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" - -#include "Utilities/rTime.h" -#include "cellRtc.h" - -extern Module<> cellRtc; - -s64 convertToUNIXTime(u16 seconds, u16 minutes, u16 hours, u16 days, s32 years) -{ - return (s64)seconds + (s64)minutes * 60 + (s64)hours * 3600 + (s64)days * 86400 + - (s64)(years - 70) * 31536000 + (s64)((years - 69) / 4) * 86400 - - (s64)((years - 1) / 100) * 86400 + (s64)((years + 299) / 400) * 86400; -} - -u64 convertToWin32FILETIME(u16 seconds, u16 minutes, u16 hours, u16 days, s32 years) -{ - s64 unixtime = convertToUNIXTime(seconds, minutes, hours, days, years); - u64 win32time = u64(unixtime) * u64(10000000) + u64(116444736000000000); - u64 win32filetime = win32time | win32time >> 32; - return win32filetime; -} - -s32 cellRtcGetCurrentTick(vm::ptr pTick) -{ - cellRtc.trace("cellRtcGetCurrentTick(pTick=*0x%x)", pTick); - - rDateTime unow = rDateTime::UNow(); - pTick->tick = unow.GetTicks(); - return CELL_OK; -} - -s32 cellRtcGetCurrentClock(vm::ptr pClock, s32 iTimeZone) -{ - cellRtc.trace("cellRtcGetCurrentClock(pClock=*0x%x, time_zone=%d)", pClock, iTimeZone); - - rDateTime unow = rDateTime::UNow(); - - // Add time_zone as offset in minutes. - rTimeSpan tz = rTimeSpan(0, (long) iTimeZone, 0, 0); - unow.Add(tz); - - pClock->year = unow.GetYear(rDateTime::TZ::UTC); - pClock->month = unow.GetMonth(rDateTime::TZ::UTC); - pClock->day = unow.GetDay(rDateTime::TZ::UTC); - pClock->hour = unow.GetHour(rDateTime::TZ::UTC); - pClock->minute = unow.GetMinute(rDateTime::TZ::UTC); - pClock->second = unow.GetSecond(rDateTime::TZ::UTC); - pClock->microsecond = unow.GetMillisecond(rDateTime::TZ::UTC) * 1000; - - return CELL_OK; -} - -s32 cellRtcGetCurrentClockLocalTime(vm::ptr pClock) -{ - cellRtc.trace("cellRtcGetCurrentClockLocalTime(pClock=*0x%x)", pClock); - - rDateTime unow = rDateTime::UNow(); - - pClock->year = unow.GetYear(rDateTime::TZ::Local); - pClock->month = unow.GetMonth(rDateTime::TZ::Local); - pClock->day = unow.GetDay(rDateTime::TZ::Local); - pClock->hour = unow.GetHour(rDateTime::TZ::Local); - pClock->minute = unow.GetMinute(rDateTime::TZ::Local); - pClock->second = unow.GetSecond(rDateTime::TZ::Local); - pClock->microsecond = unow.GetMillisecond(rDateTime::TZ::Local) * 1000; - - return CELL_OK; -} - -s32 cellRtcFormatRfc2822(vm::ptr pszDateTime, vm::ptr pUtc, s32 iTimeZone) -{ - cellRtc.trace("cellRtcFormatRfc2822(pszDateTime=*0x%x, pUtc=*0x%x, time_zone=%d)", pszDateTime, pUtc, iTimeZone); - - // Add time_zone as offset in minutes. - rTimeSpan tz = rTimeSpan(0, (long) iTimeZone, 0, 0); - - // Get date from ticks + tz. - rDateTime date = rDateTime((time_t)pUtc->tick); - date.Add(tz); - - // Format date string in RFC2822 format (e.g.: Mon, 01 Jan 1990 12:00:00 +0000). - const std::string str = date.Format("%a, %d %b %Y %T %z", rDateTime::TZ::UTC); - memcpy(pszDateTime.get_ptr(), str.c_str(), str.size() + 1); - - return CELL_OK; -} - -s32 cellRtcFormatRfc2822LocalTime(vm::ptr pszDateTime, vm::ptr pUtc) -{ - cellRtc.trace("cellRtcFormatRfc2822LocalTime(pszDateTime=*0x%x, pUtc=*0x%x)", pszDateTime, pUtc); - - // Get date from ticks. - rDateTime date = rDateTime((time_t)pUtc->tick); - - // Format date string in RFC2822 format (e.g.: Mon, 01 Jan 1990 12:00:00 +0000). - const std::string str = date.Format("%a, %d %b %Y %T %z", rDateTime::TZ::Local); - memcpy(pszDateTime.get_ptr(), str.c_str(), str.size() + 1); - - return CELL_OK; -} - -s32 cellRtcFormatRfc3339(vm::ptr pszDateTime, vm::ptr pUtc, s32 iTimeZone) -{ - cellRtc.trace("cellRtcFormatRfc3339(pszDateTime=*0x%x, pUtc=*0x%x, iTimeZone=%d)", pszDateTime, pUtc, iTimeZone); - - // Add time_zone as offset in minutes. - rTimeSpan tz = rTimeSpan(0, (long) iTimeZone, 0, 0); - - // Get date from ticks + tz. - rDateTime date = rDateTime((time_t)pUtc->tick); - date.Add(tz); - - // Format date string in RFC3339 format (e.g.: 1990-01-01T12:00:00.00Z). - const std::string str = date.Format("%FT%T.%zZ", rDateTime::TZ::UTC); - memcpy(pszDateTime.get_ptr(), str.c_str(), str.size() + 1); - - return CELL_OK; -} - -s32 cellRtcFormatRfc3339LocalTime(vm::ptr pszDateTime, vm::ptr pUtc) -{ - cellRtc.trace("cellRtcFormatRfc3339LocalTime(pszDateTime=*0x%x, pUtc=*0x%x)", pszDateTime, pUtc); - - // Get date from ticks. - rDateTime date = rDateTime((time_t) pUtc->tick); - - // Format date string in RFC3339 format (e.g.: 1990-01-01T12:00:00.00Z). - const std::string str = date.Format("%FT%T.%zZ", rDateTime::TZ::Local); - memcpy(pszDateTime.get_ptr(), str.c_str(), str.size() + 1); - - return CELL_OK; -} - -s32 cellRtcParseDateTime(vm::ptr pUtc, vm::cptr pszDateTime) -{ - cellRtc.trace("cellRtcParseDateTime(pUtc=*0x%x, pszDateTime=*0x%x)", pUtc, pszDateTime); - - // Get date from formatted string. - rDateTime date; - date.ParseDateTime(pszDateTime.get_ptr()); - - pUtc->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcParseRfc3339(vm::ptr pUtc, vm::cptr pszDateTime) -{ - cellRtc.trace("cellRtcParseRfc3339(pUtc=*0x%x, pszDateTime=*0x%x)", pUtc, pszDateTime); - - // Get date from RFC3339 formatted string. - rDateTime date; - date.ParseDateTime(pszDateTime.get_ptr()); - - pUtc->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcGetTick(vm::ptr pTime, vm::ptr pTick) -{ - cellRtc.trace("cellRtcGetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick); - - rDateTime datetime = rDateTime(pTime->day, (rDateTime::Month)pTime->month.value(), pTime->year, pTime->hour, pTime->minute, pTime->second, (pTime->microsecond / 1000)); - pTick->tick = datetime.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcSetTick(vm::ptr pTime, vm::ptr pTick) -{ - cellRtc.trace("cellRtcSetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick); - - rDateTime date = rDateTime((time_t)pTick->tick); - - pTime->year = date.GetYear(rDateTime::TZ::UTC); - pTime->month = date.GetMonth(rDateTime::TZ::UTC); - pTime->day = date.GetDay(rDateTime::TZ::UTC); - pTime->hour = date.GetHour(rDateTime::TZ::UTC); - pTime->minute = date.GetMinute(rDateTime::TZ::UTC); - pTime->second = date.GetSecond(rDateTime::TZ::UTC); - pTime->microsecond = date.GetMillisecond(rDateTime::TZ::UTC) * 1000; - - return CELL_OK; -} - -s32 cellRtcTickAddTicks(vm::ptr pTick0, vm::ptr pTick1, s64 lAdd) -{ - cellRtc.trace("cellRtcTickAddTicks(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld)", pTick0, pTick1, lAdd); - - pTick0->tick = pTick1->tick + lAdd; - return CELL_OK; -} - -s32 cellRtcTickAddMicroseconds(vm::ptr pTick0, vm::ptr pTick1, s64 lAdd) -{ - cellRtc.trace("cellRtcTickAddMicroseconds(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld)", pTick0, pTick1, lAdd); - - rDateTime date = rDateTime((time_t)pTick1->tick); - rTimeSpan microseconds = rTimeSpan(0, 0, 0, lAdd / 1000); - date.Add(microseconds); - pTick0->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcTickAddSeconds(vm::ptr pTick0, vm::ptr pTick1, s64 lAdd) -{ - cellRtc.trace("cellRtcTickAddSeconds(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld)", pTick0, pTick1, lAdd); - - rDateTime date = rDateTime((time_t)pTick1->tick); - rTimeSpan seconds = rTimeSpan(0, 0, lAdd, 0); - date.Add(seconds); - pTick0->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcTickAddMinutes(vm::ptr pTick0, vm::ptr pTick1, s64 lAdd) -{ - cellRtc.trace("cellRtcTickAddMinutes(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld)", pTick0, pTick1, lAdd); - - rDateTime date = rDateTime((time_t)pTick1->tick); - rTimeSpan minutes = rTimeSpan(0, lAdd, 0, 0); // ??? - date.Add(minutes); - pTick0->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcTickAddHours(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) -{ - cellRtc.trace("cellRtcTickAddHours(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); - - rDateTime date = rDateTime((time_t)pTick1->tick); - rTimeSpan hours = rTimeSpan(iAdd, 0, 0, 0); // ??? - date.Add(hours); - pTick0->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcTickAddDays(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) -{ - cellRtc.trace("cellRtcTickAddDays(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); - - rDateTime date = rDateTime((time_t)pTick1->tick); - rDateSpan days = rDateSpan(0, 0, 0, iAdd); // ??? - date.Add(days); - pTick0->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcTickAddWeeks(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) -{ - cellRtc.trace("cellRtcTickAddWeeks(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); - - rDateTime date = rDateTime((time_t)pTick1->tick); - rDateSpan weeks = rDateSpan(0, 0, iAdd, 0); - date.Add(weeks); - pTick0->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcTickAddMonths(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) -{ - cellRtc.trace("cellRtcTickAddMonths(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); - - rDateTime date = rDateTime((time_t)pTick1->tick); - rDateSpan months = rDateSpan(0, iAdd, 0, 0); - date.Add(months); - pTick0->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcTickAddYears(vm::ptr pTick0, vm::ptr pTick1, s32 iAdd) -{ - cellRtc.trace("cellRtcTickAddYears(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd); - - rDateTime date = rDateTime((time_t)pTick1->tick); - rDateSpan years = rDateSpan(iAdd, 0, 0, 0); - date.Add(years); - pTick0->tick = date.GetTicks(); - - return CELL_OK; -} - -s32 cellRtcConvertUtcToLocalTime(vm::ptr pUtc, vm::ptr pLocalTime) -{ - cellRtc.trace("cellRtcConvertUtcToLocalTime(pUtc=*0x%x, pLocalTime=*0x%x)", pUtc, pLocalTime); - - rDateTime time = rDateTime((time_t)pUtc->tick); - rDateTime local_time = time.FromUTC(false); - pLocalTime->tick = local_time.GetTicks(); - return CELL_OK; -} - -s32 cellRtcConvertLocalTimeToUtc(vm::ptr pLocalTime, vm::ptr pUtc) -{ - cellRtc.trace("cellRtcConvertLocalTimeToUtc(pLocalTime=*0x%x, pUtc=*0x%x)", pLocalTime, pUtc); - - rDateTime time = rDateTime((time_t)pLocalTime->tick); - rDateTime utc_time = time.ToUTC(false); - pUtc->tick = utc_time.GetTicks(); - return CELL_OK; -} - -s32 cellRtcGetDosTime(vm::ptr pDateTime, vm::ptr puiDosTime) -{ - cellRtc.trace("cellRtcGetDosTime(pDateTime=*0x%x, puiDosTime=*0x%x)", pDateTime, puiDosTime); - - // Convert to DOS time. - rDateTime date_time = rDateTime(pDateTime->day, (rDateTime::Month)pDateTime->month.value(), pDateTime->year, pDateTime->hour, pDateTime->minute, pDateTime->second, (pDateTime->microsecond / 1000)); - *puiDosTime = date_time.GetAsDOS(); - - return CELL_OK; -} - -s32 cellRtcGetTime_t(vm::ptr pDateTime, vm::ptr piTime) -{ - cellRtc.trace("cellRtcGetTime_t(pDateTime=*0x%x, piTime=*0x%x)", pDateTime, piTime); - - // Convert to POSIX time_t. - rDateTime date_time = rDateTime(pDateTime->day, (rDateTime::Month)pDateTime->month.value(), pDateTime->year, pDateTime->hour, pDateTime->minute, pDateTime->second, (pDateTime->microsecond / 1000)); - *piTime = convertToUNIXTime(date_time.GetSecond(rDateTime::TZ::UTC), date_time.GetMinute(rDateTime::TZ::UTC), - date_time.GetHour(rDateTime::TZ::UTC), date_time.GetDay(rDateTime::TZ::UTC), date_time.GetYear(rDateTime::TZ::UTC)); - - return CELL_OK; -} - -s32 cellRtcGetWin32FileTime(vm::ptr pDateTime, vm::ptr pulWin32FileTime) -{ - cellRtc.trace("cellRtcGetWin32FileTime(pDateTime=*0x%x, pulWin32FileTime=*0x%x)", pDateTime, pulWin32FileTime); - - // Convert to WIN32 FILETIME. - rDateTime date_time = rDateTime(pDateTime->day, (rDateTime::Month)pDateTime->month.value(), pDateTime->year, pDateTime->hour, pDateTime->minute, pDateTime->second, (pDateTime->microsecond / 1000)); - *pulWin32FileTime = convertToWin32FILETIME(date_time.GetSecond(rDateTime::TZ::UTC), date_time.GetMinute(rDateTime::TZ::UTC), - date_time.GetHour(rDateTime::TZ::UTC), date_time.GetDay(rDateTime::TZ::UTC), date_time.GetYear(rDateTime::TZ::UTC)); - - return CELL_OK; -} - -s32 cellRtcSetDosTime(vm::ptr pDateTime, u32 uiDosTime) -{ - cellRtc.trace("cellRtcSetDosTime(pDateTime=*0x%x, uiDosTime=0x%x)", pDateTime, uiDosTime); - - rDateTime date_time; - rDateTime dos_time = date_time.SetFromDOS(uiDosTime); - - pDateTime->year = dos_time.GetYear(rDateTime::TZ::UTC); - pDateTime->month = dos_time.GetMonth(rDateTime::TZ::UTC); - pDateTime->day = dos_time.GetDay(rDateTime::TZ::UTC); - pDateTime->hour = dos_time.GetHour(rDateTime::TZ::UTC); - pDateTime->minute = dos_time.GetMinute(rDateTime::TZ::UTC); - pDateTime->second = dos_time.GetSecond(rDateTime::TZ::UTC); - pDateTime->microsecond = dos_time.GetMillisecond(rDateTime::TZ::UTC) * 1000; - - return CELL_OK; -} - -s32 cellRtcSetTime_t(vm::ptr pDateTime, u64 iTime) -{ - cellRtc.trace("cellRtcSetTime_t(pDateTime=*0x%x, iTime=0x%llx)", pDateTime, iTime); - - rDateTime date_time = rDateTime((time_t)iTime); - - pDateTime->year = date_time.GetYear(rDateTime::TZ::UTC); - pDateTime->month = date_time.GetMonth(rDateTime::TZ::UTC); - pDateTime->day = date_time.GetDay(rDateTime::TZ::UTC); - pDateTime->hour = date_time.GetHour(rDateTime::TZ::UTC); - pDateTime->minute = date_time.GetMinute(rDateTime::TZ::UTC); - pDateTime->second = date_time.GetSecond(rDateTime::TZ::UTC); - pDateTime->microsecond = date_time.GetMillisecond(rDateTime::TZ::UTC) * 1000; - - return CELL_OK; -} - -s32 cellRtcSetWin32FileTime(vm::ptr pDateTime, u64 ulWin32FileTime) -{ - cellRtc.trace("cellRtcSetWin32FileTime(pDateTime=*0x%x, ulWin32FileTime=0x%llx)", pDateTime, ulWin32FileTime); - - rDateTime date_time = rDateTime((time_t)ulWin32FileTime); - - pDateTime->year = date_time.GetYear(rDateTime::TZ::UTC); - pDateTime->month = date_time.GetMonth(rDateTime::TZ::UTC); - pDateTime->day = date_time.GetDay(rDateTime::TZ::UTC); - pDateTime->hour = date_time.GetHour(rDateTime::TZ::UTC); - pDateTime->minute = date_time.GetMinute(rDateTime::TZ::UTC); - pDateTime->second = date_time.GetSecond(rDateTime::TZ::UTC); - pDateTime->microsecond = date_time.GetMillisecond(rDateTime::TZ::UTC) * 1000; - - return CELL_OK; -} - -s32 cellRtcIsLeapYear(s32 year) -{ - cellRtc.trace("cellRtcIsLeapYear(year=%d)", year); - - rDateTime datetime; - return datetime.IsLeapYear(year, rDateTime::Gregorian); -} - -s32 cellRtcGetDaysInMonth(s32 year, s32 month) -{ - cellRtc.trace("cellRtcGetDaysInMonth(year=%d, month=%d)", year, month); - - rDateTime datetime; - return datetime.GetNumberOfDays((rDateTime::Month) month, year, rDateTime::Gregorian); -} - -s32 cellRtcGetDayOfWeek(s32 year, s32 month, s32 day) -{ - cellRtc.trace("cellRtcGetDayOfWeek(year=%d, month=%d, day=%d)", year, month, day); - - rDateTime datetime; - datetime.SetToWeekDay((rDateTime::WeekDay) day, 1, (rDateTime::Month) month, year); - return datetime.GetWeekDay(); -} - -s32 cellRtcCheckValid(vm::ptr pTime) -{ - cellRtc.trace("cellRtcCheckValid(pTime=*0x%x)", pTime); - - if ((pTime->year < 1) || (pTime->year > 9999)) return CELL_RTC_ERROR_INVALID_YEAR; - else if ((pTime->month < 1) || (pTime->month > 12)) return CELL_RTC_ERROR_INVALID_MONTH; - else if ((pTime->day < 1) || (pTime->day > 31)) return CELL_RTC_ERROR_INVALID_DAY; - else if (pTime->hour > 23) return CELL_RTC_ERROR_INVALID_HOUR; - else if (pTime->minute > 59) return CELL_RTC_ERROR_INVALID_MINUTE; - else if (pTime->second > 59) return CELL_RTC_ERROR_INVALID_SECOND; - else if (pTime->microsecond > 999999) return CELL_RTC_ERROR_INVALID_MICROSECOND; - else return CELL_OK; -} - -s32 cellRtcCompareTick(vm::ptr pTick0, vm::ptr pTick1) -{ - cellRtc.trace("cellRtcCompareTick(pTick0=*0x%x, pTick1=*0x%x)", pTick0, pTick1); - - if (pTick0->tick < pTick1->tick) return -1; - else if (pTick0->tick > pTick1->tick) return 1; - else return CELL_OK; -} - -Module<> cellRtc("cellRtc", []() -{ - REG_FUNC(cellRtc, cellRtcGetCurrentTick); - REG_FUNC(cellRtc, cellRtcGetCurrentClock); - REG_FUNC(cellRtc, cellRtcGetCurrentClockLocalTime); - - REG_FUNC(cellRtc, cellRtcFormatRfc2822); - REG_FUNC(cellRtc, cellRtcFormatRfc2822LocalTime); - REG_FUNC(cellRtc, cellRtcFormatRfc3339); - REG_FUNC(cellRtc, cellRtcFormatRfc3339LocalTime); - REG_FUNC(cellRtc, cellRtcParseDateTime); - REG_FUNC(cellRtc, cellRtcParseRfc3339); - - REG_FUNC(cellRtc, cellRtcGetTick); - REG_FUNC(cellRtc, cellRtcSetTick); - REG_FUNC(cellRtc, cellRtcTickAddTicks); - REG_FUNC(cellRtc, cellRtcTickAddMicroseconds); - REG_FUNC(cellRtc, cellRtcTickAddSeconds); - REG_FUNC(cellRtc, cellRtcTickAddMinutes); - REG_FUNC(cellRtc, cellRtcTickAddHours); - REG_FUNC(cellRtc, cellRtcTickAddDays); - REG_FUNC(cellRtc, cellRtcTickAddWeeks); - REG_FUNC(cellRtc, cellRtcTickAddMonths); - REG_FUNC(cellRtc, cellRtcTickAddYears); - REG_FUNC(cellRtc, cellRtcConvertUtcToLocalTime); - REG_FUNC(cellRtc, cellRtcConvertLocalTimeToUtc); - - REG_FUNC(cellRtc, cellRtcGetDosTime); - REG_FUNC(cellRtc, cellRtcGetTime_t); - REG_FUNC(cellRtc, cellRtcGetWin32FileTime); - REG_FUNC(cellRtc, cellRtcSetDosTime); - REG_FUNC(cellRtc, cellRtcSetTime_t); - REG_FUNC(cellRtc, cellRtcSetWin32FileTime); - - REG_FUNC(cellRtc, cellRtcIsLeapYear); - REG_FUNC(cellRtc, cellRtcGetDaysInMonth); - REG_FUNC(cellRtc, cellRtcGetDayOfWeek); - REG_FUNC(cellRtc, cellRtcCheckValid); - - REG_FUNC(cellRtc, cellRtcCompareTick); -}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp deleted file mode 100644 index 506eb4ba9a..0000000000 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ /dev/null @@ -1,1715 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/System.h" -#include "Emu/Cell/SPUThread.h" -#include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/lv2/sys_sync.h" -#include "Emu/SysCalls/lv2/sys_lwmutex.h" -#include "Emu/SysCalls/lv2/sys_lwcond.h" -#include "Emu/SysCalls/lv2/sys_spu.h" -#include "Emu/SysCalls/Modules/cellSpurs.h" -#include "Loader/ELF32.h" -#include "Emu/FS/vfsStreamMemory.h" - -//---------------------------------------------------------------------------- -// Externs -//---------------------------------------------------------------------------- - -extern Module<> cellSpurs; - -//---------------------------------------------------------------------------- -// Function prototypes -//---------------------------------------------------------------------------- - -// -// SPURS utility functions -// -static void cellSpursModulePutTrace(CellSpursTracePacket * packet, u32 dmaTagId); -static u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status); -static void cellSpursModuleExit(SPUThread & spu); - -static bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag); -static u32 spursDmaGetCompletionStatus(SPUThread & spu, u32 tagMask); -static u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll = true); -static void spursHalt(SPUThread & spu); - -// -// SPURS kernel functions -// -static bool spursKernel1SelectWorkload(SPUThread & spu); -static bool spursKernel2SelectWorkload(SPUThread & spu); -static void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus); -static bool spursKernelWorkloadExit(SPUThread & spu); -bool spursKernelEntry(SPUThread & spu); - -// -// SPURS system workload functions -// -static bool spursSysServiceEntry(SPUThread & spu); -// TODO: Exit -static void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt); -static void spursSysServiceMain(SPUThread & spu, u32 pollStatus); -static void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt); -static void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt); -// TODO: Deactivate workload -static void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelContext * ctxt, u32 wklShutdownBitSet); -static void spursSysServiceTraceSaveCount(SPUThread & spu, SpursKernelContext * ctxt); -static void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32 arg2, u32 arg3, u32 forceNotify); -// TODO: Deactivate trace -// TODO: System workload entry -static void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelContext * ctxt); - -// -// SPURS taskset policy module functions -// -static bool spursTasksetEntry(SPUThread & spu); -static bool spursTasksetSyscallEntry(SPUThread & spu); -static void spursTasksetResumeTask(SPUThread & spu); -static void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs); -static s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting); -static void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus); -static bool spursTasksetPollStatus(SPUThread & spu); -static void spursTasksetExit(SPUThread & spu); -static void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args); -static s32 spursTasketSaveTaskContext(SPUThread & spu); -static void spursTasksetDispatch(SPUThread & spu); -static s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args); -static void spursTasksetInit(SPUThread & spu, u32 pollStatus); -static s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments); - -//---------------------------------------------------------------------------- -// SPURS utility functions -//---------------------------------------------------------------------------- - -/// Output trace information -void cellSpursModulePutTrace(CellSpursTracePacket * packet, u32 dmaTagId) { - // TODO: Implement this -} - -/// Check for execution right requests -u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status) { - auto ctxt = vm::_ptr(spu.offset + 0x100); - - spu.gpr[3]._u32[3] = 1; - if (ctxt->spurs->flags1 & SF1_32_WORKLOADS) { - spursKernel2SelectWorkload(spu); - } else { - spursKernel1SelectWorkload(spu); - } - - auto result = spu.gpr[3]._u64[1]; - if (status) { - *status = (u32)result; - } - - u32 wklId = result >> 32; - return wklId == ctxt->wklCurrentId ? 0 : 1; -} - -/// Exit current workload -void cellSpursModuleExit(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x100); - spu.pc = ctxt->exitToKernelAddr - 4; - throw SpursModuleExit(); -} - -/// Execute a DMA operation -bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag) { - spu.set_ch_value(MFC_LSA, lsa); - spu.set_ch_value(MFC_EAH, (u32)(ea >> 32)); - spu.set_ch_value(MFC_EAL, (u32)(ea)); - spu.set_ch_value(MFC_Size, size); - spu.set_ch_value(MFC_TagID, tag); - spu.set_ch_value(MFC_Cmd, cmd); - - if (cmd == MFC_GETLLAR_CMD || cmd == MFC_PUTLLC_CMD || cmd == MFC_PUTLLUC_CMD) { - u32 rv; - - rv = spu.get_ch_value(MFC_RdAtomicStat); - auto success = rv ? true : false; - success = cmd == MFC_PUTLLC_CMD ? !success : success; - return success; - } - - return true; -} - -/// Get the status of DMA operations -u32 spursDmaGetCompletionStatus(SPUThread & spu, u32 tagMask) { - spu.set_ch_value(MFC_WrTagMask, tagMask); - spu.set_ch_value(MFC_WrTagUpdate, MFC_TAG_UPDATE_IMMEDIATE); - return spu.get_ch_value(MFC_RdTagStat); -} - -/// Wait for DMA operations to complete -u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll) { - spu.set_ch_value(MFC_WrTagMask, tagMask); - spu.set_ch_value(MFC_WrTagUpdate, waitForAll ? MFC_TAG_UPDATE_ALL : MFC_TAG_UPDATE_ANY); - return spu.get_ch_value(MFC_RdTagStat); -} - -/// Halt the SPU -void spursHalt(SPUThread & spu) { - spu.halt(); -} - -//---------------------------------------------------------------------------- -// SPURS kernel functions -//---------------------------------------------------------------------------- - -/// Select a workload to run -bool spursKernel1SelectWorkload(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x100); - - // The first and only argument to this function is a boolean that is set to false if the function - // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. - // If the first argument is true then the shared data is not updated with the result. - const auto isPoll = spu.gpr[3]._u32[3]; - - u32 wklSelectedId; - u32 pollStatus; - - vm::reservation_op(VM_CAST(ctxt->spurs.addr()), 128, [&]() { - // lock the first 0x80 bytes of spurs - auto spurs = ctxt->spurs.get_ptr_priv(); - - // Calculate the contention (number of SPUs used) for each workload - u8 contention[CELL_SPURS_MAX_WORKLOAD]; - u8 pendingContention[CELL_SPURS_MAX_WORKLOAD]; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - contention[i] = spurs->wklCurrentContention[i] - ctxt->wklLocContention[i]; - - // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably - // to prevent unnecessary jumps to the kernel - if (isPoll) { - pendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; - if (i != ctxt->wklCurrentId) { - contention[i] += pendingContention[i]; - } - } - } - - wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - pollStatus = 0; - - // The system service has the highest priority. Select the system service if - // the system service message bit for this SPU is set. - if (spurs->sysSrvMessage & (1 << ctxt->spuNum)) { - ctxt->spuIdling = 0; - if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - // Clear the message bit - spurs->sysSrvMessage.raw() &= ~(1 << ctxt->spuNum); - } - } else { - // Caclulate the scheduling weight for each workload - u16 maxWeight = 0; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i); - u16 wklSignal = spurs->wklSignal1.load() & (0x8000 >> i); - u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver == i ? 1 : 0 : 0; - u8 readyCount = spurs->wklReadyCount1[i] > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].load(); - u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i] > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].load(); - u8 requestCount = readyCount + idleSpuCount; - - // For a workload to be considered for scheduling: - // 1. Its priority must not be 0 - // 2. The number of SPUs used by it must be less than the max contention for that workload - // 3. The workload should be in runnable state - // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) - // OR the workload must be signalled - // OR the workload flag is 0 and the workload is configured as the wokload flag receiver - if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i] > contention[i]) { - if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) { - // The scheduling weight of the workload is formed from the following parameters in decreasing order of priority: - // 1. Wokload signal set or workload flag or ready count > contention - // 2. Priority of the workload on the SPU - // 3. Is the workload the last selected workload - // 4. Minimum contention of the workload - // 5. Number of SPUs that are being used by the workload (lesser the number, more the weight) - // 6. Is the workload executable same as the currently loaded executable - // 7. The workload id (lesser the number, more the weight) - u16 weight = (wklFlag || wklSignal || (readyCount > contention[i])) ? 0x8000 : 0; - weight |= (u16)(ctxt->priority[i] & 0x7F) << 16; - weight |= i == ctxt->wklCurrentId ? 0x80 : 0x00; - weight |= (contention[i] > 0 && spurs->wklMinContention[i] > contention[i]) ? 0x40 : 0x00; - weight |= ((CELL_SPURS_MAX_SPU - contention[i]) & 0x0F) << 2; - weight |= ctxt->wklUniqueId[i] == ctxt->wklCurrentId ? 0x02 : 0x00; - weight |= 0x01; - - // In case of a tie the lower numbered workload is chosen - if (weight > maxWeight) { - wklSelectedId = i; - maxWeight = weight; - pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; - pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; - pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; - } - } - } - } - - // Not sure what this does. Possibly mark the SPU as idle/in use. - ctxt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; - - if (!isPoll || wklSelectedId == ctxt->wklCurrentId) { - // Clear workload signal for the selected workload - spurs->wklSignal1.raw() &= ~(0x8000 >> wklSelectedId); - spurs->wklSignal2.raw() &= ~(0x80000000u >> wklSelectedId); - - // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s - if (wklSelectedId == spurs->wklFlagReceiver) { - spurs->wklFlag.flag = -1; - } - } - } - - if (!isPoll) { - // Called by kernel - // Increment the contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - contention[wklSelectedId]++; - } - - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - spurs->wklCurrentContention[i] = contention[i]; - spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; - ctxt->wklLocContention[i] = 0; - ctxt->wklLocPendingContention[i] = 0; - } - - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - ctxt->wklLocContention[wklSelectedId] = 1; - } - - ctxt->wklCurrentId = wklSelectedId; - } else if (wklSelectedId != ctxt->wklCurrentId) { - // Not called by kernel but a context switch is required - // Increment the pending contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - pendingContention[wklSelectedId]++; - } - - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - spurs->wklPendingContention[i] = pendingContention[i]; - ctxt->wklLocPendingContention[i] = 0; - } - - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - ctxt->wklLocPendingContention[wklSelectedId] = 1; - } - } else { - // Not called by kernel and no context switch is required - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; - ctxt->wklLocPendingContention[i] = 0; - } - } - - std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); - }); - - u64 result = (u64)wklSelectedId << 32; - result |= pollStatus; - spu.gpr[3]._u64[1] = result; - return true; -} - -/// Select a workload to run -bool spursKernel2SelectWorkload(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x100); - - // The first and only argument to this function is a boolean that is set to false if the function - // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. - // If the first argument is true then the shared data is not updated with the result. - const auto isPoll = spu.gpr[3]._u32[3]; - - u32 wklSelectedId; - u32 pollStatus; - - vm::reservation_op(VM_CAST(ctxt->spurs.addr()), 128, [&]() { - // lock the first 0x80 bytes of spurs - auto spurs = ctxt->spurs.get_ptr_priv(); - - // Calculate the contention (number of SPUs used) for each workload - u8 contention[CELL_SPURS_MAX_WORKLOAD2]; - u8 pendingContention[CELL_SPURS_MAX_WORKLOAD2]; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { - contention[i] = spurs->wklCurrentContention[i & 0x0F] - ctxt->wklLocContention[i & 0x0F]; - contention[i] = i < CELL_SPURS_MAX_WORKLOAD ? contention[i] & 0x0F : contention[i] >> 4; - - // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably - // to prevent unnecessary jumps to the kernel - if (isPoll) { - pendingContention[i] = spurs->wklPendingContention[i & 0x0F] - ctxt->wklLocPendingContention[i & 0x0F]; - pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4; - if (i != ctxt->wklCurrentId) { - contention[i] += pendingContention[i]; - } - } - } - - wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - pollStatus = 0; - - // The system service has the highest priority. Select the system service if - // the system service message bit for this SPU is set. - if (spurs->sysSrvMessage & (1 << ctxt->spuNum)) { - // Not sure what this does. Possibly Mark the SPU as in use. - ctxt->spuIdling = 0; - if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - // Clear the message bit - spurs->sysSrvMessage.raw() &= ~(1 << ctxt->spuNum); - } - } else { - // Caclulate the scheduling weight for each workload - u8 maxWeight = 0; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { - auto j = i & 0x0F; - u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); - u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4; - u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j] & 0x0F : spurs->wklMaxContention[j] >> 4; - u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.load() & (0x8000 >> j) : spurs->wklSignal2.load() & (0x8000 >> j); - u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver == i ? 1 : 0 : 0; - u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j] : spurs->wklIdleSpuCountOrReadyCount2[j]; - - // For a workload to be considered for scheduling: - // 1. Its priority must be greater than 0 - // 2. The number of SPUs used by it must be less than the max contention for that workload - // 3. The workload should be in runnable state - // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) - // OR the workload must be signalled - // OR the workload flag is 0 and the workload is configured as the wokload receiver - if (runnable && priority > 0 && maxContention > contention[i]) { - if (wklFlag || wklSignal || readyCount > contention[i]) { - // The scheduling weight of the workload is equal to the priority of the workload for the SPU. - // The current workload is given a sligtly higher weight presumably to reduce the number of context switches. - // In case of a tie the lower numbered workload is chosen. - u8 weight = priority << 4; - if (ctxt->wklCurrentId == i) { - weight |= 0x04; - } - - if (weight > maxWeight) { - wklSelectedId = i; - maxWeight = weight; - pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; - pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; - pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; - } - } - } - } - - // Not sure what this does. Possibly mark the SPU as idle/in use. - ctxt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; - - if (!isPoll || wklSelectedId == ctxt->wklCurrentId) { - // Clear workload signal for the selected workload - spurs->wklSignal1.raw() &= ~(0x8000 >> wklSelectedId); - spurs->wklSignal2.raw() &= ~(0x80000000u >> wklSelectedId); - - // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s - if (wklSelectedId == spurs->wklFlagReceiver) { - spurs->wklFlag.flag = -1; - } - } - } - - if (!isPoll) { - // Called by kernel - // Increment the contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - contention[wklSelectedId]++; - } - - for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { - spurs->wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4); - spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; - ctxt->wklLocContention[i] = 0; - ctxt->wklLocPendingContention[i] = 0; - } - - ctxt->wklLocContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; - ctxt->wklCurrentId = wklSelectedId; - } else if (wklSelectedId != ctxt->wklCurrentId) { - // Not called by kernel but a context switch is required - // Increment the pending contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - pendingContention[wklSelectedId]++; - } - - for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { - spurs->wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4); - ctxt->wklLocPendingContention[i] = 0; - } - - ctxt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; - } else { - // Not called by kernel and no context switch is required - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i]; - ctxt->wklLocPendingContention[i] = 0; - } - } - - std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); - }); - - u64 result = (u64)wklSelectedId << 32; - result |= pollStatus; - spu.gpr[3]._u64[1] = result; - return true; -} - -/// SPURS kernel dispatch workload -void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) { - auto ctxt = vm::_ptr(spu.offset + 0x100); - auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false; - - auto pollStatus = (u32)widAndPollStatus; - auto wid = (u32)(widAndPollStatus >> 32); - - // DMA in the workload info for the selected workload - auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? &ctxt->spurs->wklInfo1[wid] : - wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &ctxt->spurs->wklInfo2[wid & 0xf] : - &ctxt->spurs->wklInfoSysSrv; - - std::memcpy(vm::base(spu.offset + 0x3FFE0), wklInfoOffset, 0x20); - - // Load the workload to LS - auto wklInfo = vm::_ptr(spu.offset + 0x3FFE0); - if (ctxt->wklCurrentAddr != wklInfo->addr) { - switch (wklInfo->addr.addr()) { - case SPURS_IMG_ADDR_SYS_SRV_WORKLOAD: - spu.RegisterHleFunction(0xA00, spursSysServiceEntry); - break; - case SPURS_IMG_ADDR_TASKSET_PM: - spu.RegisterHleFunction(0xA00, spursTasksetEntry); - break; - default: - std::memcpy(vm::base(spu.offset + 0xA00), wklInfo->addr.get_ptr(), wklInfo->size); - break; - } - - ctxt->wklCurrentAddr = wklInfo->addr; - ctxt->wklCurrentUniqueId = wklInfo->uniqueId; - } - - if (!isKernel2) { - ctxt->moduleId[0] = 0; - ctxt->moduleId[1] = 0; - } - - // Run workload - spu.gpr[0]._u32[3] = ctxt->exitToKernelAddr; - spu.gpr[1]._u32[3] = 0x3FFB0; - spu.gpr[3]._u32[3] = 0x100; - spu.gpr[4]._u64[1] = wklInfo->arg; - spu.gpr[5]._u32[3] = pollStatus; - spu.pc = 0xA00 - 4; -} - -/// SPURS kernel workload exit -bool spursKernelWorkloadExit(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x100); - auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false; - - // Select next workload to run - spu.gpr[3].clear(); - if (isKernel2) { - spursKernel2SelectWorkload(spu); - } else { - spursKernel1SelectWorkload(spu); - } - - spursKernelDispatchWorkload(spu, spu.gpr[3]._u64[1]); - return false; -} - -/// SPURS kernel entry point -bool spursKernelEntry(SPUThread & spu) { - while (true) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - CHECK_EMU_STATUS; - } - - auto ctxt = vm::_ptr(spu.offset + 0x100); - memset(ctxt, 0, sizeof(SpursKernelContext)); - - // Save arguments - ctxt->spuNum = spu.gpr[3]._u32[3]; - ctxt->spurs.set(spu.gpr[4]._u64[1]); - - auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false; - - // Initialise the SPURS context to its initial values - ctxt->dmaTagId = CELL_SPURS_KERNEL_DMA_TAG_ID; - ctxt->wklCurrentUniqueId = 0x20; - ctxt->wklCurrentId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - ctxt->exitToKernelAddr = isKernel2 ? CELL_SPURS_KERNEL2_EXIT_ADDR : CELL_SPURS_KERNEL1_EXIT_ADDR; - ctxt->selectWorkloadAddr = isKernel2 ? CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR : CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR; - if (!isKernel2) { - ctxt->x1F0 = 0xF0020000; - ctxt->x200 = 0x20000; - ctxt->guid[0] = 0x423A3A02; - ctxt->guid[1] = 0x43F43A82; - ctxt->guid[2] = 0x43F26502; - ctxt->guid[3] = 0x420EB382; - } else { - ctxt->guid[0] = 0x43A08402; - ctxt->guid[1] = 0x43FB0A82; - ctxt->guid[2] = 0x435E9302; - ctxt->guid[3] = 0x43A3C982; - } - - // Register SPURS kernel HLE functions - spu.UnregisterHleFunctions(0, 0x40000/*LS_BOTTOM*/); - spu.RegisterHleFunction(isKernel2 ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR, spursKernelEntry); - spu.RegisterHleFunction(ctxt->exitToKernelAddr, spursKernelWorkloadExit); - spu.RegisterHleFunction(ctxt->selectWorkloadAddr, isKernel2 ? spursKernel2SelectWorkload : spursKernel1SelectWorkload); - - // Start the system service - spursKernelDispatchWorkload(spu, ((u64)CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) << 32); - return false; -} - -//---------------------------------------------------------------------------- -// SPURS system workload functions -//---------------------------------------------------------------------------- - -/// Entry point of the system service -bool spursSysServiceEntry(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + spu.gpr[3]._u32[3]); - auto arg = spu.gpr[4]._u64[1]; - auto pollStatus = spu.gpr[5]._u32[3]; - - try { - if (ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - spursSysServiceMain(spu, pollStatus); - } else { - // TODO: If we reach here it means the current workload was preempted to start the - // system workload. Need to implement this. - } - - cellSpursModuleExit(spu); - } - - catch (SpursModuleExit) { - } - - return false; -} - -/// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled -void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) { - bool shouldExit; - - std::unique_lock lock(spu.mutex, std::defer_lock); - - while (true) { - vm::reservation_acquire(vm::base(spu.offset + 0x100), VM_CAST(ctxt->spurs.addr()), 128); - auto spurs = vm::_ptr(spu.offset + 0x100); - - // Find the number of SPUs that are idling in this SPURS instance - u32 nIdlingSpus = 0; - for (u32 i = 0; i < 8; i++) { - if (spurs->spuIdling & (1 << i)) { - nIdlingSpus++; - } - } - - bool allSpusIdle = nIdlingSpus == spurs->nSpus ? true: false; - bool exitIfNoWork = spurs->flags1 & SF1_EXIT_IF_NO_WORK ? true : false; - shouldExit = allSpusIdle && exitIfNoWork; - - // Check if any workloads can be scheduled - bool foundReadyWorkload = false; - if (spurs->sysSrvMessage & (1 << ctxt->spuNum)) { - foundReadyWorkload = true; - } else { - if (spurs->flags1 & SF1_32_WORKLOADS) { - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { - u32 j = i & 0x0F; - u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); - u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4; - u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j] & 0x0F : spurs->wklMaxContention[j] >> 4; - u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklCurrentContention[j] & 0x0F : spurs->wklCurrentContention[j] >> 4; - u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.load() & (0x8000 >> j) : spurs->wklSignal2.load() & (0x8000 >> j); - u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver == i ? 1 : 0 : 0; - u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j] : spurs->wklIdleSpuCountOrReadyCount2[j]; - - if (runnable && priority > 0 && maxContention > contention) { - if (wklFlag || wklSignal || readyCount > contention) { - foundReadyWorkload = true; - break; - } - } - } - } else { - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i); - u16 wklSignal = spurs->wklSignal1.load() & (0x8000 >> i); - u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver == i ? 1 : 0 : 0; - u8 readyCount = spurs->wklReadyCount1[i] > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].load(); - u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i] > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].load(); - u8 requestCount = readyCount + idleSpuCount; - - if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i] > spurs->wklCurrentContention[i]) { - if (wklFlag || wklSignal || (readyCount != 0 && requestCount > spurs->wklCurrentContention[i])) { - foundReadyWorkload = true; - break; - } - } - } - } - } - - bool spuIdling = spurs->spuIdling & (1 << ctxt->spuNum) ? true : false; - if (foundReadyWorkload && shouldExit == false) { - spurs->spuIdling &= ~(1 << ctxt->spuNum); - } else { - spurs->spuIdling |= 1 << ctxt->spuNum; - } - - // If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events. - if (spuIdling && shouldExit == false && foundReadyWorkload == false) { - // The system service blocks by making a reservation and waiting on the lock line reservation lost event. - CHECK_EMU_STATUS; - if (!lock) lock.lock(); - spu.cv.wait_for(lock, std::chrono::milliseconds(1)); - continue; - } - - if (vm::reservation_update(VM_CAST(ctxt->spurs.addr()), vm::base(spu.offset + 0x100), 128) && (shouldExit || foundReadyWorkload)) { - break; - } - } - - if (shouldExit) { - // TODO: exit spu thread group - } -} - -/// Main function for the system service -void spursSysServiceMain(SPUThread & spu, u32 pollStatus) { - auto ctxt = vm::_ptr(spu.offset + 0x100); - - if (!ctxt->spurs.aligned()) { - assert(!"spursSysServiceMain(): invalid spurs alignment"); - spursHalt(spu); - } - - // Initialise the system service if this is the first time its being started on this SPU - if (ctxt->sysSrvInitialised == 0) { - ctxt->sysSrvInitialised = 1; - - vm::reservation_acquire(vm::base(spu.offset + 0x100), VM_CAST(ctxt->spurs.addr()), 128); - - vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() { - auto spurs = ctxt->spurs.get_ptr_priv(); - - // Halt if already initialised - if (spurs->sysSrvOnSpu & (1 << ctxt->spuNum)) { - assert(!"spursSysServiceMain(): already initialized"); - spursHalt(spu); - } - - spurs->sysSrvOnSpu |= 1 << ctxt->spuNum; - - std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); - }); - - ctxt->traceBuffer = 0; - ctxt->traceMsgCount = -1; - spursSysServiceTraceUpdate(spu, ctxt, 1, 1, 0); - spursSysServiceCleanupAfterSystemWorkload(spu, ctxt); - - // Trace - SERVICE: INIT - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; - pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_INIT; - cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - } - - // Trace - START: Module='SYS ' - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_START; - memcpy(pkt.data.start.module, "SYS ", 4); - pkt.data.start.level = 1; // Policy module - pkt.data.start.ls = 0xA00 >> 2; - cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - - while (true) { - CHECK_EMU_STATUS; - // Process requests for the system service - spursSysServiceProcessRequests(spu, ctxt); - -poll: - if (cellSpursModulePollStatus(spu, nullptr)) { - // Trace - SERVICE: EXIT - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; - pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_EXIT; - cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - - // Trace - STOP: GUID - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; - pkt.data.stop = SPURS_GUID_SYS_WKL; - cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - - //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); - break; - } - - // If we reach here it means that either there are more system service messages to be processed - // or there are no workloads that can be scheduled. - - // If the SPU is not idling then process the remaining system service messages - if (ctxt->spuIdling == 0) { - continue; - } - - // If we reach here it means that the SPU is idling - - // Trace - SERVICE: WAIT - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; - pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_WAIT; - cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - - spursSysServiceIdleHandler(spu, ctxt); - CHECK_EMU_STATUS; - - goto poll; - } -} - -/// Process any requests -void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt) { - bool updateTrace = false; - bool updateWorkload = false; - bool terminate = false; - - vm::reservation_op(VM_CAST(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() { - auto spurs = ctxt->spurs.get_ptr_priv(); - - // Terminate request - if (spurs->sysSrvMsgTerminate & (1 << ctxt->spuNum)) { - spurs->sysSrvOnSpu &= ~(1 << ctxt->spuNum); - terminate = true; - } - - // Update workload message - if (spurs->sysSrvMsgUpdateWorkload & (1 << ctxt->spuNum)) { - spurs->sysSrvMsgUpdateWorkload &= ~(1 << ctxt->spuNum); - updateWorkload = true; - } - - // Update trace message - if (spurs->sysSrvTrace.load().sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) { - updateTrace = true; - } - - std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); - }); - - // Process update workload message - if (updateWorkload) { - spursSysServiceActivateWorkload(spu, ctxt); - } - - // Process update trace message - if (updateTrace) { - spursSysServiceTraceUpdate(spu, ctxt, 1, 0, 0); - } - - // Process terminate request - if (terminate) { - // TODO: Rest of the terminate processing - } -} - -/// Activate a workload -void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt) { - auto spurs = vm::_ptr(spu.offset + 0x100); - std::memcpy(vm::base(spu.offset + 0x30000), ctxt->spurs->wklInfo1, 0x200); - if (spurs->flags1 & SF1_32_WORKLOADS) { - std::memcpy(vm::base(spu.offset + 0x30200), ctxt->spurs->wklInfo2, 0x200); - } - - u32 wklShutdownBitSet = 0; - ctxt->wklRunnable1 = 0; - ctxt->wklRunnable2 = 0; - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - auto wklInfo1 = vm::_ptr(spu.offset + 0x30000); - - // Copy the priority of the workload for this SPU and its unique id to the LS - ctxt->priority[i] = wklInfo1[i].priority[ctxt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[ctxt->spuNum]; - ctxt->wklUniqueId[i] = wklInfo1[i].uniqueId; - - if (spurs->flags1 & SF1_32_WORKLOADS) { - auto wklInfo2 = vm::_ptr(spu.offset + 0x30200); - - // Copy the priority of the workload for this SPU to the LS - if (wklInfo2[i].priority[ctxt->spuNum]) { - ctxt->priority[i] |= (0x10 - wklInfo2[i].priority[ctxt->spuNum]) << 4; - } - } - } - - vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() { - auto spurs = ctxt->spurs.get_ptr_priv(); - - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - // Update workload status and runnable flag based on the workload state - auto wklStatus = spurs->wklStatus1[i]; - if (spurs->wklState1[i] == SPURS_WKL_STATE_RUNNABLE) { - spurs->wklStatus1[i] |= 1 << ctxt->spuNum; - ctxt->wklRunnable1 |= 0x8000 >> i; - } else { - spurs->wklStatus1[i] &= ~(1 << ctxt->spuNum); - } - - // If the workload is shutting down and if this is the last SPU from which it is being removed then - // add it to the shutdown bit set - if (spurs->wklState1[i] == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus1[i] == 0)) { - spurs->wklState1[i] = SPURS_WKL_STATE_REMOVABLE; - wklShutdownBitSet |= 0x80000000u >> i; - } - } - - if (spurs->flags1 & SF1_32_WORKLOADS) { - // Update workload status and runnable flag based on the workload state - wklStatus = spurs->wklStatus2[i]; - if (spurs->wklState2[i] == SPURS_WKL_STATE_RUNNABLE) { - spurs->wklStatus2[i] |= 1 << ctxt->spuNum; - ctxt->wklRunnable2 |= 0x8000 >> i; - } else { - spurs->wklStatus2[i] &= ~(1 << ctxt->spuNum); - } - - // If the workload is shutting down and if this is the last SPU from which it is being removed then - // add it to the shutdown bit set - if (spurs->wklState2[i] == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus2[i] == 0)) { - spurs->wklState2[i] = SPURS_WKL_STATE_REMOVABLE; - wklShutdownBitSet |= 0x8000 >> i; - } - } - } - } - - std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); - }); - - if (wklShutdownBitSet) { - spursSysServiceUpdateShutdownCompletionEvents(spu, ctxt, wklShutdownBitSet); - } -} - -/// Update shutdown completion events -void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelContext * ctxt, u32 wklShutdownBitSet) { - // Mark the workloads in wklShutdownBitSet as completed and also generate a bit set of the completed - // workloads that have a shutdown completion hook registered - u32 wklNotifyBitSet; - u8 spuPort; - vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() { - auto spurs = ctxt->spurs.get_ptr_priv(); - - wklNotifyBitSet = 0; - spuPort = spurs->spuPort;; - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - if (wklShutdownBitSet & (0x80000000u >> i)) { - spurs->wklEvent1[i] |= 0x01; - if (spurs->wklEvent1[i] & 0x02 || spurs->wklEvent1[i] & 0x10) { - wklNotifyBitSet |= 0x80000000u >> i; - } - } - - if (wklShutdownBitSet & (0x8000 >> i)) { - spurs->wklEvent2[i] |= 0x01; - if (spurs->wklEvent2[i] & 0x02 || spurs->wklEvent2[i] & 0x10) { - wklNotifyBitSet |= 0x8000 >> i; - } - } - } - - std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); - }); - - if (wklNotifyBitSet) { - // TODO: sys_spu_thread_send_event(spuPort, 0, wklNotifyMask); - } -} - -/// Update the trace count for this SPU -void spursSysServiceTraceSaveCount(SPUThread & spu, SpursKernelContext * ctxt) { - if (ctxt->traceBuffer) { - auto traceInfo = vm::ptr::make((u32)(ctxt->traceBuffer - (ctxt->spurs->traceStartIndex[ctxt->spuNum] << 4))); - traceInfo->count[ctxt->spuNum] = ctxt->traceMsgCount; - } -} - -/// Update trace control -void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32 arg2, u32 arg3, u32 forceNotify) { - bool notify; - - u8 sysSrvMsgUpdateTrace; - vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() { - auto spurs = ctxt->spurs.get_ptr_priv(); - auto& trace = spurs->sysSrvTrace.raw(); - - sysSrvMsgUpdateTrace = trace.sysSrvMsgUpdateTrace; - trace.sysSrvMsgUpdateTrace &= ~(1 << ctxt->spuNum); - trace.sysSrvTraceInitialised &= ~(1 << ctxt->spuNum); - trace.sysSrvTraceInitialised |= arg2 << ctxt->spuNum; - - notify = false; - if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) && (spurs->sysSrvTrace.load().sysSrvMsgUpdateTrace == 0) && (spurs->sysSrvTrace.load().sysSrvNotifyUpdateTraceComplete != 0)) { - trace.sysSrvNotifyUpdateTraceComplete = 0; - notify = true; - } - - if (forceNotify && spurs->sysSrvTrace.load().sysSrvNotifyUpdateTraceComplete != 0) { - trace.sysSrvNotifyUpdateTraceComplete = 0; - notify = true; - } - - std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); - }); - - // Get trace parameters from CellSpurs and store them in the LS - if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) || (arg3 != 0)) { - vm::reservation_acquire(vm::base(spu.offset + 0x80), ctxt->spurs.ptr(&CellSpurs::traceBuffer).addr(), 128); - auto spurs = vm::_ptr(spu.offset + 0x80 - OFFSET_32(CellSpurs, traceBuffer)); - - if (ctxt->traceMsgCount != 0xFF || spurs->traceBuffer.addr() == 0) { - spursSysServiceTraceSaveCount(spu, ctxt); - } else { - std::memcpy(vm::base(spu.offset + 0x2C00), vm::base(spurs->traceBuffer.addr() & -0x4), 0x80); - auto traceBuffer = vm::_ptr(spu.offset + 0x2C00); - ctxt->traceMsgCount = traceBuffer->count[ctxt->spuNum]; - } - - ctxt->traceBuffer = spurs->traceBuffer.addr() + (spurs->traceStartIndex[ctxt->spuNum] << 4); - ctxt->traceMaxCount = spurs->traceStartIndex[1] - spurs->traceStartIndex[0]; - if (ctxt->traceBuffer == 0) { - ctxt->traceMsgCount = 0; - } - } - - if (notify) { - auto spurs = vm::_ptr(spu.offset + 0x2D80 - OFFSET_32(CellSpurs, wklState1)); - sys_spu_thread_send_event(spu, spurs->spuPort, 2, 0); - } -} - -/// Restore state after executing the system workload -void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelContext * ctxt) { - u8 wklId; - - bool do_return = false; - - vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() { - auto spurs = ctxt->spurs.get_ptr_priv(); - - if (spurs->sysSrvPreemptWklId[ctxt->spuNum] == 0xFF) { - do_return = true; - return; - } - - wklId = spurs->sysSrvPreemptWklId[ctxt->spuNum]; - spurs->sysSrvPreemptWklId[ctxt->spuNum] = 0xFF; - - std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); - }); - - if (do_return) return; - - spursSysServiceActivateWorkload(spu, ctxt); - - vm::reservation_op(VM_CAST(ctxt->spurs.addr()), 128, [&]() { - auto spurs = ctxt->spurs.get_ptr_priv(); - - if (wklId >= CELL_SPURS_MAX_WORKLOAD) { - spurs->wklCurrentContention[wklId & 0x0F] -= 0x10; - spurs->wklReadyCount1[wklId & 0x0F].raw() -= 1; - } else { - spurs->wklCurrentContention[wklId & 0x0F] -= 0x01; - spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].raw() -= 1; - } - - std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); - }); - - // Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace - // uses the current worload id to determine the workload to which the trace belongs - auto wklIdSaved = ctxt->wklCurrentId; - ctxt->wklCurrentId = wklId; - - // Trace - STOP: GUID - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; - pkt.data.stop = SPURS_GUID_SYS_WKL; - cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - - ctxt->wklCurrentId = wklIdSaved; -} - -//---------------------------------------------------------------------------- -// SPURS taskset policy module functions -//---------------------------------------------------------------------------- - -enum SpursTasksetRequest { - SPURS_TASKSET_REQUEST_POLL_SIGNAL = -1, - SPURS_TASKSET_REQUEST_DESTROY_TASK = 0, - SPURS_TASKSET_REQUEST_YIELD_TASK = 1, - SPURS_TASKSET_REQUEST_WAIT_SIGNAL = 2, - SPURS_TASKSET_REQUEST_POLL = 3, - SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG = 4, - SPURS_TASKSET_REQUEST_SELECT_TASK = 5, - SPURS_TASKSET_REQUEST_RECV_WKL_FLAG = 6, -}; - -/// Taskset PM entry point -bool spursTasksetEntry(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - auto kernelCtxt = vm::_ptr(spu.offset + spu.gpr[3]._u32[3]); - - auto arg = spu.gpr[4]._u64[1]; - auto pollStatus = spu.gpr[5]._u32[3]; - - // Initialise memory and save args - memset(ctxt, 0, sizeof(*ctxt)); - ctxt->taskset.set(arg); - memcpy(ctxt->moduleId, "SPURSTASK MODULE", sizeof(ctxt->moduleId)); - ctxt->kernelMgmtAddr = spu.gpr[3]._u32[3]; - ctxt->syscallAddr = CELL_SPURS_TASKSET_PM_SYSCALL_ADDR; - ctxt->spuNum = kernelCtxt->spuNum; - ctxt->dmaTagId = kernelCtxt->dmaTagId; - ctxt->taskId = 0xFFFFFFFF; - - // Register SPURS takset policy module HLE functions - spu.UnregisterHleFunctions(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, 0x40000/*LS_BOTTOM*/); - spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry); - spu.RegisterHleFunction(ctxt->syscallAddr, spursTasksetSyscallEntry); - - try { - // Initialise the taskset policy module - spursTasksetInit(spu, pollStatus); - - // Dispatch - spursTasksetDispatch(spu); - } - - catch (SpursModuleExit) { - } - - return false; -} - -/// Entry point into the Taskset PM for task syscalls -bool spursTasksetSyscallEntry(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - - try { - // Save task context - ctxt->savedContextLr = spu.gpr[0]; - ctxt->savedContextSp = spu.gpr[1]; - for (auto i = 0; i < 48; i++) { - ctxt->savedContextR80ToR127[i] = spu.gpr[80 + i]; - } - - // Handle the syscall - spu.gpr[3]._u32[3] = spursTasksetProcessSyscall(spu, spu.gpr[3]._u32[3], spu.gpr[4]._u32[3]); - - // Resume the previously executing task if the syscall did not cause a context switch - throw EXCEPTION("Broken (TODO)"); - //if (spu.m_is_branch == false) { - // spursTasksetResumeTask(spu); - //} - } - - catch (SpursModuleExit) { - } - - return false; -} - -/// Resume a task -void spursTasksetResumeTask(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - - // Restore task context - spu.gpr[0] = ctxt->savedContextLr; - spu.gpr[1] = ctxt->savedContextSp; - for (auto i = 0; i < 48; i++) { - spu.gpr[80 + i] = ctxt->savedContextR80ToR127[i]; - } - - spu.pc = spu.gpr[0]._u32[3] - 4; -} - -/// Start a task -void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - auto taskset = vm::_ptr(spu.offset + 0x2700); - - spu.gpr[2].clear(); - spu.gpr[3] = v128::from64r(taskArgs._u64[0], taskArgs._u64[1]); - spu.gpr[4]._u64[1] = taskset->args; - spu.gpr[4]._u64[0] = taskset->spurs.addr(); - for (auto i = 5; i < 128; i++) { - spu.gpr[i].clear(); - } - - spu.pc = ctxt->savedContextLr.value()._u32[3] - 4; -} - -/// Process a request and update the state of the taskset -s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting) { - auto kernelCtxt = vm::_ptr(spu.offset + 0x100); - auto ctxt = vm::_ptr(spu.offset + 0x2700); - - s32 rc = CELL_OK; - s32 numNewlyReadyTasks; - vm::reservation_op(VM_CAST(ctxt->taskset.addr()), 128, [&]() { - auto taskset = ctxt->taskset.get_ptr_priv(); - - // Verify taskset state is valid - be_t _0(v128::from32(0)); - if ((taskset->waiting & taskset->running) != _0 || (taskset->ready & taskset->pending_ready) != _0 || - ((taskset->running | taskset->ready | taskset->pending_ready | taskset->signalled | taskset->waiting) & ~taskset->enabled) != _0) { - assert(!"Invalid taskset state"); - spursHalt(spu); - } - - // Find the number of tasks that have become ready since the last iteration - auto newlyReadyTasks = (taskset->signalled | taskset->pending_ready) & ~taskset->ready.value(); - numNewlyReadyTasks = 0; - for (auto i = 0; i < 128; i++) { - if (newlyReadyTasks._bit[i]) { - numNewlyReadyTasks++; - } - } - - v128 readyButNotRunning; - u8 selectedTaskId; - v128 running = taskset->running.value(); - v128 waiting = taskset->waiting.value(); - v128 enabled = taskset->enabled.value(); - v128 signalled = (taskset->signalled & (taskset->ready | taskset->pending_ready)); - v128 ready = (taskset->signalled | taskset->ready | taskset->pending_ready); - - switch (request) { - case SPURS_TASKSET_REQUEST_POLL_SIGNAL: - rc = signalled._bit[ctxt->taskId] ? 1 : 0; - signalled._bit[ctxt->taskId] = false; - break; - case SPURS_TASKSET_REQUEST_DESTROY_TASK: - numNewlyReadyTasks--; - running._bit[ctxt->taskId] = false; - enabled._bit[ctxt->taskId] = false; - signalled._bit[ctxt->taskId] = false; - ready._bit[ctxt->taskId] = false; - break; - case SPURS_TASKSET_REQUEST_YIELD_TASK: - running._bit[ctxt->taskId] = false; - waiting._bit[ctxt->taskId] = true; - break; - case SPURS_TASKSET_REQUEST_WAIT_SIGNAL: - if (signalled._bit[ctxt->taskId] == false) { - numNewlyReadyTasks--; - running._bit[ctxt->taskId] = false; - waiting._bit[ctxt->taskId] = true; - signalled._bit[ctxt->taskId] = false; - ready._bit[ctxt->taskId] = false; - } - break; - case SPURS_TASKSET_REQUEST_POLL: - readyButNotRunning = ready & ~running; - if (taskset->wkl_flag_wait_task < CELL_SPURS_MAX_TASK) { - readyButNotRunning = readyButNotRunning & ~(v128::fromBit(taskset->wkl_flag_wait_task)); - } - - rc = readyButNotRunning != _0 ? 1 : 0; - break; - case SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG: - if (taskset->wkl_flag_wait_task == 0x81) { - // A workload flag is already pending so consume it - taskset->wkl_flag_wait_task = 0x80; - rc = 0; - } else if (taskset->wkl_flag_wait_task == 0x80) { - // No tasks are waiting for the workload flag. Mark this task as waiting for the workload flag. - taskset->wkl_flag_wait_task = ctxt->taskId; - running._bit[ctxt->taskId] = false; - waiting._bit[ctxt->taskId] = true; - rc = 1; - numNewlyReadyTasks--; - } else { - // Another task is already waiting for the workload signal - rc = CELL_SPURS_TASK_ERROR_BUSY; - } - break; - case SPURS_TASKSET_REQUEST_SELECT_TASK: - readyButNotRunning = ready & ~running; - if (taskset->wkl_flag_wait_task < CELL_SPURS_MAX_TASK) { - readyButNotRunning = readyButNotRunning & ~(v128::fromBit(taskset->wkl_flag_wait_task)); - } - - // Select a task from the readyButNotRunning set to run. Start from the task after the last scheduled task to ensure fairness. - for (selectedTaskId = taskset->last_scheduled_task + 1; selectedTaskId < 128; selectedTaskId++) { - if (readyButNotRunning._bit[selectedTaskId]) { - break; - } - } - - if (selectedTaskId == 128) { - for (selectedTaskId = 0; selectedTaskId < taskset->last_scheduled_task + 1; selectedTaskId++) { - if (readyButNotRunning._bit[selectedTaskId]) { - break; - } - } - - if (selectedTaskId == taskset->last_scheduled_task + 1) { - selectedTaskId = CELL_SPURS_MAX_TASK; - } - } - - *taskId = selectedTaskId; - *isWaiting = waiting._bit[selectedTaskId < CELL_SPURS_MAX_TASK ? selectedTaskId : 0] ? 1 : 0; - if (selectedTaskId != CELL_SPURS_MAX_TASK) { - taskset->last_scheduled_task = selectedTaskId; - running._bit[selectedTaskId] = true; - waiting._bit[selectedTaskId] = false; - } - break; - case SPURS_TASKSET_REQUEST_RECV_WKL_FLAG: - if (taskset->wkl_flag_wait_task < CELL_SPURS_MAX_TASK) { - // There is a task waiting for the workload flag - taskset->wkl_flag_wait_task = 0x80; - rc = 1; - numNewlyReadyTasks++; - } else { - // No tasks are waiting for the workload flag - taskset->wkl_flag_wait_task = 0x81; - rc = 0; - } - break; - default: - assert(!"Unknown taskset request"); - spursHalt(spu); - } - - taskset->pending_ready = _0; - taskset->running = running; - taskset->waiting = waiting; - taskset->enabled = enabled; - taskset->signalled = signalled; - taskset->ready = ready; - - std::memcpy(vm::base(spu.offset + 0x2700), taskset, 128); - }); - - // Increment the ready count of the workload by the number of tasks that have become ready - vm::reservation_op(VM_CAST(kernelCtxt->spurs.addr()), 128, [&]() { - auto spurs = kernelCtxt->spurs.get_ptr_priv(); - - s32 readyCount = kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[kernelCtxt->wklCurrentId].load() : spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].load(); - readyCount += numNewlyReadyTasks; - readyCount = readyCount < 0 ? 0 : readyCount > 0xFF ? 0xFF : readyCount; - - if (kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD) { - spurs->wklReadyCount1[kernelCtxt->wklCurrentId] = readyCount; - } else { - spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F] = readyCount; - } - - std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); - }); - - return rc; -} - -/// Process pollStatus received from the SPURS kernel -void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus) { - if (pollStatus & CELL_SPURS_MODULE_POLL_STATUS_FLAG) { - spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_RECV_WKL_FLAG, nullptr, nullptr); - } -} - -/// Check execution rights -bool spursTasksetPollStatus(SPUThread & spu) { - u32 pollStatus; - - if (cellSpursModulePollStatus(spu, &pollStatus)) { - return true; - } - - spursTasksetProcessPollStatus(spu, pollStatus); - return false; -} - -/// Exit the Taskset PM -void spursTasksetExit(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - - // Trace - STOP - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = 0x54; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_STOP - pkt.data.stop = SPURS_GUID_TASKSET_PM; - cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - - // Not sure why this check exists. Perhaps to check for memory corruption. - if (memcmp(ctxt->moduleId, "SPURSTASK MODULE", 16) != 0) { - //spursHalt(spu); - assert(!"spursTasksetExit(): memory corruption"); - } - - cellSpursModuleExit(spu); -} - -/// Invoked when a task exits -void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - - std::memcpy(vm::base(spu.offset + 0x10000), vm::base(addr & -0x80), (addr & 0x7F) << 11); - - spu.gpr[3]._u64[1] = ctxt->taskset.addr(); - spu.gpr[4]._u32[3] = taskId; - spu.gpr[5]._u32[3] = exitCode; - spu.gpr[6]._u64[1] = args; - spu.fast_call(0x10000); -} - -/// Save the context of a task -s32 spursTasketSaveTaskContext(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - auto taskInfo = vm::_ptr(spu.offset + 0x2780); - - //spursDmaWaitForCompletion(spu, 0xFFFFFFFF); - - if (taskInfo->context_save_storage_and_alloc_ls_blocks == 0) { - return CELL_SPURS_TASK_ERROR_STAT; - } - - u32 allocLsBlocks = taskInfo->context_save_storage_and_alloc_ls_blocks & 0x7F; - u32 lsBlocks = 0; - v128 ls_pattern = v128::from64r(taskInfo->ls_pattern._u64[0], taskInfo->ls_pattern._u64[1]); - for (auto i = 0; i < 128; i++) { - if (ls_pattern._bit[i]) { - lsBlocks++; - } - } - - if (lsBlocks > allocLsBlocks) { - return CELL_SPURS_TASK_ERROR_STAT; - } - - // Make sure the stack is area is specified in the ls pattern - for (auto i = (ctxt->savedContextSp.value()._u32[3]) >> 11; i < 128; i++) { - if (ls_pattern._bit[i] == false) { - return CELL_SPURS_TASK_ERROR_STAT; - } - } - - // Get the processor context - v128 r; - spu.fpscr.Read(r); - ctxt->savedContextFpscr = r; - ctxt->savedSpuWriteEventMask = spu.get_ch_value(SPU_RdEventMask); - ctxt->savedWriteTagGroupQueryMask = spu.get_ch_value(MFC_RdTagMask); - - // Store the processor context - const u32 contextSaveStorage = VM_CAST(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80); - std::memcpy(vm::base(contextSaveStorage), vm::base(spu.offset + 0x2C80), 0x380); - - // Save LS context - for (auto i = 6; i < 128; i++) { - if (ls_pattern._bit[i]) { - // TODO: Combine DMA requests for consecutive blocks into a single request - std::memcpy(vm::base(contextSaveStorage + 0x400 + ((i - 6) << 11)), vm::base(spu.offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), 0x800); - } - } - - //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); - return CELL_OK; -} - -/// Taskset dispatcher -void spursTasksetDispatch(SPUThread & spu) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - auto taskset = vm::_ptr(spu.offset + 0x2700); - - u32 taskId; - u32 isWaiting; - spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_SELECT_TASK, &taskId, &isWaiting); - if (taskId >= CELL_SPURS_MAX_TASK) { - spursTasksetExit(spu); - return; - } - - ctxt->taskId = taskId; - - // DMA in the task info for the selected task - std::memcpy(vm::base(spu.offset + 0x2780), &ctxt->taskset->task_info[taskId], sizeof(CellSpursTaskset::TaskInfo)); - auto taskInfo = vm::_ptr(spu.offset + 0x2780); - auto elfAddr = taskInfo->elf.addr().value(); - taskInfo->elf.set(taskInfo->elf.addr() & 0xFFFFFFFFFFFFFFF8); - - // Trace - Task: Incident=dispatch - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_TASK; - pkt.data.task.incident = CELL_SPURS_TRACE_TASK_DISPATCH; - pkt.data.task.taskId = taskId; - cellSpursModulePutTrace(&pkt, CELL_SPURS_KERNEL_DMA_TAG_ID); - - if (isWaiting == 0) { - // If we reach here it means that the task is being started and not being resumed - std::memset(vm::base(spu.offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); - ctxt->guidAddr = CELL_SPURS_TASK_TOP; - - u32 entryPoint; - u32 lowestLoadAddr; - if (spursTasksetLoadElf(spu, &entryPoint, &lowestLoadAddr, taskInfo->elf.addr(), false) != CELL_OK) { - assert(!"spursTaskLoadElf() failed"); - spursHalt(spu); - } - - //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); - - ctxt->savedContextLr = v128::from32r(entryPoint); - ctxt->guidAddr = lowestLoadAddr; - ctxt->tasksetMgmtAddr = 0x2700; - ctxt->x2FC0 = 0; - ctxt->taskExitCode = isWaiting; - ctxt->x2FD4 = elfAddr & 5; // TODO: Figure this out - - if ((elfAddr & 5) == 1) { - std::memcpy(vm::base(spu.offset + 0x2FC0), &((CellSpursTaskset2*)(ctxt->taskset.get_ptr()))->task_exit_code[taskId], 0x10); - } - - // Trace - GUID - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_GUID; - pkt.data.guid = 0; // TODO: Put GUID of taskId here - cellSpursModulePutTrace(&pkt, 0x1F); - - if (elfAddr & 2) { // TODO: Figure this out - spu.status |= SPU_STATUS_STOPPED_BY_STOP; - spu.stop(); - return; - } - - spursTasksetStartTask(spu, taskInfo->args); - } else { - if (taskset->enable_clear_ls) { - std::memset(vm::base(spu.offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); - } - - // If the entire LS is saved then there is no need to load the ELF as it will be be saved in the context save area as well - v128 ls_pattern = v128::from64r(taskInfo->ls_pattern._u64[0], taskInfo->ls_pattern._u64[1]); - if (ls_pattern != v128::from64r(0x03FFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull)) { - // Load the ELF - u32 entryPoint; - if (spursTasksetLoadElf(spu, &entryPoint, nullptr, taskInfo->elf.addr(), true) != CELL_OK) { - assert(!"spursTasksetLoadElf() failed"); - spursHalt(spu); - } - } - - // Load saved context from main memory to LS - const u32 contextSaveStorage = VM_CAST(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80); - std::memcpy(vm::base(spu.offset + 0x2C80), vm::base(contextSaveStorage), 0x380); - for (auto i = 6; i < 128; i++) { - if (ls_pattern._bit[i]) { - // TODO: Combine DMA requests for consecutive blocks into a single request - std::memcpy(vm::base(spu.offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), vm::base(contextSaveStorage + 0x400 + ((i - 6) << 11)), 0x800); - } - } - - //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); - - // Restore saved registers - spu.fpscr.Write(ctxt->savedContextFpscr.value()); - spu.set_ch_value(MFC_WrTagMask, ctxt->savedWriteTagGroupQueryMask); - spu.set_ch_value(SPU_WrEventMask, ctxt->savedSpuWriteEventMask); - - // Trace - GUID - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_GUID; - pkt.data.guid = 0; // TODO: Put GUID of taskId here - cellSpursModulePutTrace(&pkt, 0x1F); - - if (elfAddr & 2) { // TODO: Figure this out - spu.status |= SPU_STATUS_STOPPED_BY_STOP; - spu.stop(); - return; - } - - spu.gpr[3].clear(); - spursTasksetResumeTask(spu); - } -} - -/// Process a syscall request -s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - auto taskset = vm::_ptr(spu.offset + 0x2700); - - // If the 0x10 bit is set in syscallNum then its the 2nd version of the - // syscall (e.g. cellSpursYield2 instead of cellSpursYield) and so don't wait - // for DMA completion - if ((syscallNum & 0x10) == 0) { - //spursDmaWaitForCompletion(spu, 0xFFFFFFFF); - } - - s32 rc = 0; - u32 incident = 0; - switch (syscallNum & 0x0F) { - case CELL_SPURS_TASK_SYSCALL_EXIT: - if (ctxt->x2FD4 == 4 || (ctxt->x2FC0 & 0xFFFFFFFF) != 0) { // TODO: Figure this out - if (ctxt->x2FD4 != 4) { - spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_DESTROY_TASK, nullptr, nullptr); - } - - const u64 addr = ctxt->x2FD4 == 4 ? taskset->x78 : ctxt->x2FC0; - const u64 args = ctxt->x2FD4 == 4 ? 0 : ctxt->x2FC8.value(); - spursTasksetOnTaskExit(spu, addr, ctxt->taskId, ctxt->taskExitCode, args); - } - - incident = CELL_SPURS_TRACE_TASK_EXIT; - break; - case CELL_SPURS_TASK_SYSCALL_YIELD: - if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_POLL, nullptr, nullptr)) { - // If we reach here then it means that either another task can be scheduled or another workload can be scheduled - // Save the context of the current task - rc = spursTasketSaveTaskContext(spu); - if (rc == CELL_OK) { - spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_YIELD_TASK, nullptr, nullptr); - incident = CELL_SPURS_TRACE_TASK_YIELD; - } - } - break; - case CELL_SPURS_TASK_SYSCALL_WAIT_SIGNAL: - if (spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_POLL_SIGNAL, nullptr, nullptr) == 0) { - rc = spursTasketSaveTaskContext(spu); - if (rc == CELL_OK) { - if (spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_WAIT_SIGNAL, nullptr, nullptr) == 0) { - incident = CELL_SPURS_TRACE_TASK_WAIT; - } - } - } - break; - case CELL_SPURS_TASK_SYSCALL_POLL: - rc = spursTasksetPollStatus(spu) ? CELL_SPURS_TASK_POLL_FOUND_WORKLOAD : 0; - rc |= spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_POLL, nullptr, nullptr) ? CELL_SPURS_TASK_POLL_FOUND_TASK : 0; - break; - case CELL_SPURS_TASK_SYSCALL_RECV_WKL_FLAG: - if (args == 0) { // TODO: Figure this out - assert(!"args == 0"); - //spursHalt(spu); - } - - if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG, nullptr, nullptr) != 1) { - rc = spursTasketSaveTaskContext(spu); - if (rc == CELL_OK) { - incident = CELL_SPURS_TRACE_TASK_WAIT; - } - } - break; - default: - rc = CELL_SPURS_TASK_ERROR_NOSYS; - break; - } - - if (incident) { - // Trace - TASK - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_TASK; - pkt.data.task.incident = incident; - pkt.data.task.taskId = ctxt->taskId; - cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - - // Clear the GUID of the task - std::memset(vm::base(spu.offset + ctxt->guidAddr), 0, 0x10); - - if (spursTasksetPollStatus(spu)) { - spursTasksetExit(spu); - } else { - spursTasksetDispatch(spu); - } - } - - return rc; -} - -/// Initialise the Taskset PM -void spursTasksetInit(SPUThread & spu, u32 pollStatus) { - auto ctxt = vm::_ptr(spu.offset + 0x2700); - auto kernelCtxt = vm::_ptr(spu.offset + 0x100); - - kernelCtxt->moduleId[0] = 'T'; - kernelCtxt->moduleId[1] = 'K'; - - // Trace - START: Module='TKST' - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = 0x52; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_START - memcpy(pkt.data.start.module, "TKST", 4); - pkt.data.start.level = 2; - pkt.data.start.ls = 0xA00 >> 2; - cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - - spursTasksetProcessPollStatus(spu, pollStatus); -} - -/// Load an ELF -s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments) { - if (elfAddr == 0 || (elfAddr & 0x0F) != 0) { - return CELL_SPURS_TASK_ERROR_INVAL; - } - - vfsStreamMemory stream(VM_CAST(elfAddr)); - loader::handlers::elf32 loader; - auto rc = loader.init(stream); - if (rc != loader::handler::ok) { - return CELL_SPURS_TASK_ERROR_NOEXEC; - } - - u32 _lowestLoadAddr = CELL_SPURS_TASK_BOTTOM; - for (auto & phdr : loader.m_phdrs) { - if (phdr.data_be.p_paddr >= CELL_SPURS_TASK_BOTTOM) { - break; - } - - if (phdr.data_be.p_type == 1/*PT_LOAD*/) { - if (skipWriteableSegments == false || (phdr.data_be.p_flags & 2/*PF_W*/) == 0) { - if (phdr.data_be.p_vaddr < CELL_SPURS_TASK_TOP || - phdr.data_be.p_vaddr + phdr.data_be.p_memsz > CELL_SPURS_TASK_BOTTOM) { - return CELL_SPURS_TASK_ERROR_FAULT; - } - - _lowestLoadAddr > phdr.data_be.p_vaddr ? _lowestLoadAddr = phdr.data_be.p_vaddr : _lowestLoadAddr; - } - } - } - - loader.load_data(spu.offset, skipWriteableSegments); - *entryPoint = loader.m_ehdr.data_be.e_entry; - if (*lowestLoadAddr) { - *lowestLoadAddr = _lowestLoadAddr; - } - - return CELL_OK; -} diff --git a/rpcs3/Emu/SysCalls/Modules/cellVideoExport.cpp b/rpcs3/Emu/SysCalls/Modules/cellVideoExport.cpp deleted file mode 100644 index c70757f56f..0000000000 --- a/rpcs3/Emu/SysCalls/Modules/cellVideoExport.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" - -extern Module<> cellVideoExport; - -s32 cellVideoExportProgress() -{ - throw EXCEPTION(""); -} - -s32 cellVideoExportInitialize2() -{ - throw EXCEPTION(""); -} - -s32 cellVideoExportInitialize() -{ - throw EXCEPTION(""); -} - -s32 cellVideoExportFromFileWithCopy() -{ - throw EXCEPTION(""); -} - -s32 cellVideoExportFromFile() -{ - throw EXCEPTION(""); -} - -s32 cellVideoExportFinalize() -{ - throw EXCEPTION(""); -} - - -Module<> cellVideoExport("cellVideoExport", []() -{ - REG_FUNC(cellVideoExport, cellVideoExportProgress); - REG_FUNC(cellVideoExport, cellVideoExportInitialize2); - REG_FUNC(cellVideoExport, cellVideoExportInitialize); - REG_FUNC(cellVideoExport, cellVideoExportFromFileWithCopy); - REG_FUNC(cellVideoExport, cellVideoExportFromFile); - REG_FUNC(cellVideoExport, cellVideoExportFinalize); -}); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVideoOut.cpp b/rpcs3/Emu/SysCalls/Modules/cellVideoOut.cpp deleted file mode 100644 index 4649a164b7..0000000000 --- a/rpcs3/Emu/SysCalls/Modules/cellVideoOut.cpp +++ /dev/null @@ -1,206 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/System.h" -#include "Emu/state.h" -#include "Emu/SysCalls/Modules.h" - -#include "Emu/RSX/GSManager.h" -#include "cellVideoOut.h" - -extern Module<> cellSysutil; - -s32 cellVideoOutGetState(u32 videoOut, u32 deviceIndex, vm::ptr state) -{ - cellSysutil.trace("cellVideoOutGetState(videoOut=%d, deviceIndex=%d, state=*0x%x)", videoOut, deviceIndex, state); - - if (deviceIndex) return CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND; - - switch (videoOut) - { - case CELL_VIDEO_OUT_PRIMARY: - state->state = Emu.GetGSManager().GetState(); - state->colorSpace = Emu.GetGSManager().GetColorSpace(); - state->displayMode.resolutionId = Emu.GetGSManager().GetInfo().mode.resolutionId; - state->displayMode.scanMode = Emu.GetGSManager().GetInfo().mode.scanMode; - state->displayMode.conversion = Emu.GetGSManager().GetInfo().mode.conversion; - state->displayMode.aspect = Emu.GetGSManager().GetInfo().mode.aspect; - state->displayMode.refreshRates = Emu.GetGSManager().GetInfo().mode.refreshRates; - return CELL_OK; - - case CELL_VIDEO_OUT_SECONDARY: - *state = { CELL_VIDEO_OUT_OUTPUT_STATE_DISABLED }; // ??? - return CELL_OK; - } - - return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; -} - -s32 cellVideoOutGetResolution(u32 resolutionId, vm::ptr resolution) -{ - cellSysutil.trace("cellVideoOutGetResolution(resolutionId=%d, resolution=*0x%x)", resolutionId, resolution); - - u32 num = ResolutionIdToNum(resolutionId); - if (!num) - return CELL_EINVAL; - - resolution->width = ResolutionTable[num].width; - resolution->height = ResolutionTable[num].height; - - return CELL_OK; -} - -s32 cellVideoOutConfigure(u32 videoOut, vm::ptr config, vm::ptr option, u32 waitForEvent) -{ - cellSysutil.warning("cellVideoOutConfigure(videoOut=%d, config=*0x%x, option=*0x%x, waitForEvent=%d)", videoOut, config, option, waitForEvent); - - switch (videoOut) - { - case CELL_VIDEO_OUT_PRIMARY: - if (config->resolutionId) - { - Emu.GetGSManager().GetInfo().mode.resolutionId = config->resolutionId; - } - - Emu.GetGSManager().GetInfo().mode.format = config->format; - - if (config->aspect) - { - Emu.GetGSManager().GetInfo().mode.aspect = config->aspect; - } - - if (config->pitch) - { - Emu.GetGSManager().GetInfo().mode.pitch = config->pitch; - } - - return CELL_OK; - - case CELL_VIDEO_OUT_SECONDARY: - return CELL_OK; - } - - return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; -} - -s32 cellVideoOutGetConfiguration(u32 videoOut, vm::ptr config, vm::ptr option) -{ - cellSysutil.warning("cellVideoOutGetConfiguration(videoOut=%d, config=*0x%x, option=*0x%x)", videoOut, config, option); - - if (option) *option = {}; - *config = {}; - - switch (videoOut) - { - case CELL_VIDEO_OUT_PRIMARY: - config->resolutionId = Emu.GetGSManager().GetInfo().mode.resolutionId; - config->format = Emu.GetGSManager().GetInfo().mode.format; - config->aspect = Emu.GetGSManager().GetInfo().mode.aspect; - config->pitch = Emu.GetGSManager().GetInfo().mode.pitch; - - return CELL_OK; - - case CELL_VIDEO_OUT_SECONDARY: - - return CELL_OK; - } - - return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; -} - -s32 cellVideoOutGetDeviceInfo(u32 videoOut, u32 deviceIndex, vm::ptr info) -{ - cellSysutil.warning("cellVideoOutGetDeviceInfo(videoOut=%d, deviceIndex=%d, info=*0x%x)", videoOut, deviceIndex, info); - - if (deviceIndex) return CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND; - - // Use standard dummy values for now. - info->portType = CELL_VIDEO_OUT_PORT_HDMI; - info->colorSpace = Emu.GetGSManager().GetColorSpace(); - info->latency = 1000; - info->availableModeCount = 1; - info->state = CELL_VIDEO_OUT_DEVICE_STATE_AVAILABLE; - info->rgbOutputRange = 1; - info->colorInfo.blueX = 0xFFFF; - info->colorInfo.blueY = 0xFFFF; - info->colorInfo.greenX = 0xFFFF; - info->colorInfo.greenY = 0xFFFF; - info->colorInfo.redX = 0xFFFF; - info->colorInfo.redY = 0xFFFF; - info->colorInfo.whiteX = 0xFFFF; - info->colorInfo.whiteY = 0xFFFF; - info->colorInfo.gamma = 100; - info->availableModes[0].aspect = 0; - info->availableModes[0].conversion = 0; - info->availableModes[0].refreshRates = 0xF; - info->availableModes[0].resolutionId = 1; - info->availableModes[0].scanMode = 0; - - return CELL_OK; -} - -s32 cellVideoOutGetNumberOfDevice(u32 videoOut) -{ - cellSysutil.warning("cellVideoOutGetNumberOfDevice(videoOut=%d)", videoOut); - - switch (videoOut) - { - case CELL_VIDEO_OUT_PRIMARY: return 1; - case CELL_VIDEO_OUT_SECONDARY: return 0; - } - - return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; -} - -s32 cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 aspect, u32 option) -{ - cellSysutil.warning("cellVideoOutGetResolutionAvailability(videoOut=%d, resolutionId=0x%x, aspect=%d, option=%d)", videoOut, resolutionId, aspect, option); - - if (!rpcs3::config.rsx._3dtv.value() && (resolutionId == CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING || resolutionId == CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING || - resolutionId == CELL_VIDEO_OUT_RESOLUTION_960x720_3D_FRAME_PACKING || resolutionId == CELL_VIDEO_OUT_RESOLUTION_800x720_3D_FRAME_PACKING || - resolutionId == CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING)) - return 0; - - switch (videoOut) - { - case CELL_VIDEO_OUT_PRIMARY: return 1; - case CELL_VIDEO_OUT_SECONDARY: return 0; - } - - return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; -} - -s32 cellVideoOutGetConvertCursorColorInfo() -{ - throw EXCEPTION(""); -} - -s32 cellVideoOutDebugSetMonitorType() -{ - throw EXCEPTION(""); -} - -s32 cellVideoOutRegisterCallback() -{ - throw EXCEPTION(""); -} - -s32 cellVideoOutUnregisterCallback() -{ - throw EXCEPTION(""); -} - - -void cellSysutil_VideoOut_init() -{ - REG_FUNC(cellSysutil, cellVideoOutGetState); - REG_FUNC(cellSysutil, cellVideoOutGetResolution); - REG_FUNC(cellSysutil, cellVideoOutConfigure); - REG_FUNC(cellSysutil, cellVideoOutGetConfiguration); - REG_FUNC(cellSysutil, cellVideoOutGetDeviceInfo); - REG_FUNC(cellSysutil, cellVideoOutGetNumberOfDevice); - REG_FUNC(cellSysutil, cellVideoOutGetResolutionAvailability); - REG_FUNC(cellSysutil, cellVideoOutGetConvertCursorColorInfo); - REG_FUNC(cellSysutil, cellVideoOutDebugSetMonitorType); - REG_FUNC(cellSysutil, cellVideoOutRegisterCallback); - REG_FUNC(cellSysutil, cellVideoOutUnregisterCallback); -} diff --git a/rpcs3/Emu/SysCalls/Modules/cellVideoOut.h b/rpcs3/Emu/SysCalls/Modules/cellVideoOut.h deleted file mode 100644 index 84541bbee6..0000000000 --- a/rpcs3/Emu/SysCalls/Modules/cellVideoOut.h +++ /dev/null @@ -1,282 +0,0 @@ -#pragma once - -// Video Out Error Codes -enum -{ - CELL_VIDEO_OUT_ERROR_NOT_IMPLEMENTED = 0x8002b220, - CELL_VIDEO_OUT_ERROR_ILLEGAL_CONFIGURATION = 0x8002b221, - CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER = 0x8002b222, - CELL_VIDEO_OUT_ERROR_PARAMETER_OUT_OF_RANGE = 0x8002b223, - CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND = 0x8002b224, - CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT = 0x8002b225, - CELL_VIDEO_OUT_ERROR_UNSUPPORTED_DISPLAY_MODE = 0x8002b226, - CELL_VIDEO_OUT_ERROR_CONDITION_BUSY = 0x8002b227, - CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET = 0x8002b228, -}; - -enum CellVideoOut -{ - CELL_VIDEO_OUT_PRIMARY = 0, - CELL_VIDEO_OUT_SECONDARY = 1, -}; - -enum CellVideoOutResolutionId -{ - CELL_VIDEO_OUT_RESOLUTION_UNDEFINED = 0, - CELL_VIDEO_OUT_RESOLUTION_1080 = 1, - CELL_VIDEO_OUT_RESOLUTION_720 = 2, - CELL_VIDEO_OUT_RESOLUTION_480 = 4, - CELL_VIDEO_OUT_RESOLUTION_576 = 5, - CELL_VIDEO_OUT_RESOLUTION_1600x1080 = 10, - CELL_VIDEO_OUT_RESOLUTION_1440x1080 = 11, - CELL_VIDEO_OUT_RESOLUTION_1280x1080 = 12, - CELL_VIDEO_OUT_RESOLUTION_960x1080 = 13, - CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING = 0x81, - CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING = 0x88, - CELL_VIDEO_OUT_RESOLUTION_960x720_3D_FRAME_PACKING = 0x89, - CELL_VIDEO_OUT_RESOLUTION_800x720_3D_FRAME_PACKING = 0x8a, - CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING = 0x8b, - CELL_VIDEO_OUT_RESOLUTION_720_SIMULVIEW_FRAME_PACKING = 0x91, -}; - -enum CellVideoOutScanMode -{ - CELL_VIDEO_OUT_SCAN_MODE_INTERLACE, - CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE, -}; - -enum CellVideoOutScanMode2 -{ - CELL_VIDEO_OUT_SCAN_MODE2_AUTO, - CELL_VIDEO_OUT_SCAN_MODE2_INTERLACE, - CELL_VIDEO_OUT_SCAN_MODE2_PROGRESSIVE, -}; - -enum CellVideoOutRefreshRate -{ - CELL_VIDEO_OUT_REFRESH_RATE_AUTO = 0x0000, - CELL_VIDEO_OUT_REFRESH_RATE_59_94HZ = 0x0001, - CELL_VIDEO_OUT_REFRESH_RATE_50HZ = 0x0002, - CELL_VIDEO_OUT_REFRESH_RATE_60HZ = 0x0004, - CELL_VIDEO_OUT_REFRESH_RATE_30HZ = 0x0008 -}; - -enum CellVideoOutPortType -{ - CELL_VIDEO_OUT_PORT_NONE = 0x00, - CELL_VIDEO_OUT_PORT_HDMI = 0x01, - CELL_VIDEO_OUT_PORT_NETWORK = 0x41, - CELL_VIDEO_OUT_PORT_COMPOSITE_S = 0x81, - CELL_VIDEO_OUT_PORT_D = 0x82, - CELL_VIDEO_OUT_PORT_COMPONENT = 0x83, - CELL_VIDEO_OUT_PORT_RGB = 0x84, - CELL_VIDEO_OUT_PORT_AVMULTI_SCART = 0x85, - CELL_VIDEO_OUT_PORT_DSUB = 0x86 -}; - -enum CellVideoOutDisplayAspect -{ - CELL_VIDEO_OUT_ASPECT_AUTO, - CELL_VIDEO_OUT_ASPECT_4_3, - CELL_VIDEO_OUT_ASPECT_16_9, -}; - -enum CellVideoOutBufferColorFormat -{ - CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8, - CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8B8G8R8, - CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_R16G16B16X16_FLOAT, -}; - -enum CellVideoOutOutputState -{ - CELL_VIDEO_OUT_OUTPUT_STATE_ENABLED, - CELL_VIDEO_OUT_OUTPUT_STATE_DISABLED, - CELL_VIDEO_OUT_OUTPUT_STATE_PREPARING, -}; - -enum CellVideoOutDeviceState -{ - CELL_VIDEO_OUT_DEVICE_STATE_UNAVAILABLE, - CELL_VIDEO_OUT_DEVICE_STATE_AVAILABLE, -}; - -enum CellVideoOutColorSpace -{ - CELL_VIDEO_OUT_COLOR_SPACE_RGB = 0x01, - CELL_VIDEO_OUT_COLOR_SPACE_YUV = 0x02, - CELL_VIDEO_OUT_COLOR_SPACE_XVYCC = 0x04, -}; - -enum CellVideoOutDebugMonitorType -{ - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_UNDEFINED = 0, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_480I_59_94HZ = 1, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_576I_50HZ = 2, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_480P_59_94HZ = 3, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_576P_50HZ = 4, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_1080I_59_94HZ = 5, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_720P_59_94HZ = 7, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_1080P_59_94HZ = 9, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_WXGA_60HZ = 11, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_SXGA_60HZ = 12, - CELL_VIDEO_OUT_DEBUG_MONITOR_TYPE_WUXGA_60HZ = 13 -}; - -struct CellVideoOutColorInfo -{ - u16 redX; - u16 redY; - u16 greenX; - u16 greenY; - u16 blueX; - u16 blueY; - u16 whiteX; - u16 whiteY; - u32 gamma; -}; - -struct CellVideoOutKSVList -{ - u8 ksv[32*5]; - u8 reserved[4]; - u32 count; -}; - -enum CellVideoOutDisplayConversion -{ - CELL_VIDEO_OUT_DISPLAY_CONVERSION_NONE = 0x00, - CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_WXGA = 0x01, - CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_SXGA = 0x02, - CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_WUXGA = 0x03, - CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_1080 = 0x05, - CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_REMOTEPLAY = 0x10, - CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_720_3D_FRAME_PACKING = 0x80, -}; - -struct CellVideoOutDisplayMode -{ - u8 resolutionId; - u8 scanMode; - u8 conversion; - u8 aspect; - u8 reserved[2]; - be_t refreshRates; -}; - -struct CellVideoOutResolution -{ - be_t width; - be_t height; -}; - -struct CellVideoOutDeviceInfo -{ - u8 portType; - u8 colorSpace; - u16 latency; - u8 availableModeCount; - u8 state; - u8 rgbOutputRange; - u8 reserved[5]; - CellVideoOutColorInfo colorInfo; - CellVideoOutDisplayMode availableModes[32]; - CellVideoOutKSVList ksvList; -}; - -struct CellVideoOutState -{ - u8 state; - u8 colorSpace; - u8 reserved[6]; - CellVideoOutDisplayMode displayMode; -}; - -struct CellVideoOutConfiguration -{ - u8 resolutionId; - u8 format; - u8 aspect; - u8 reserved[9]; - be_t pitch; -}; - -struct CellVideoOutOption -{ - be_t reserved; -}; - -enum CellVideoOutEvent -{ - CELL_VIDEO_OUT_EVENT_DEVICE_CHANGED, - CELL_VIDEO_OUT_EVENT_OUTPUT_DISABLED, - CELL_VIDEO_OUT_EVENT_DEVICE_AUTHENTICATED, - CELL_VIDEO_OUT_EVENT_OUTPUT_ENABLED, -}; - -enum CellVideoOutCopyControl -{ - CELL_VIDEO_OUT_COPY_CONTROL_COPY_FREE, - CELL_VIDEO_OUT_COPY_CONTROL_COPY_ONCE, - CELL_VIDEO_OUT_COPY_CONTROL_COPY_NEVER, -}; - -enum CellVideoOutRGBOutputRange -{ - CELL_VIDEO_OUT_RGB_OUTPUT_RANGE_LIMITED, - CELL_VIDEO_OUT_RGB_OUTPUT_RANGE_FULL, -}; - -static const CellVideoOutResolution ResolutionTable[] = -{ - { 0xffff, 0xffff }, //0 - 0 - { 1920, 1080 }, //1 - 1 - { 1280, 720 }, //2 - 2 - { 720, 480 }, //4 - 3 - { 720, 576 }, //5 - 4 - { 1600, 1080 }, //10 - 5 - { 1440, 1080 }, //11 - 6 - { 1280, 1080 }, //12 - 7 - { 960, 1080 }, //13 - 8 -}; - -inline static u32 ResolutionIdToNum(u32 id) -{ - static const u32 res[] = - { - 0, //0 - 1, //1 - 2, //2 - 0, //3 - 3, //4 - 4, //5 - 0, //6 - 0, //7 - 0, //8 - 0, //9 - 5, //10 - 6, //11 - 7, //12 - 8, //13 - }; - - return id <= 13 ? res[id] : 0; -} - -inline static u32 ResolutionNumToId(u32 num) -{ - static const u32 res[] = - { - 0, //0 - 1, //1 - 2, //2 - 4, //3 - 5, //4 - 10, //5 - 11, //6 - 12, //7 - 13, //8 - }; - - return num <= 8 ? res[num] : 0; -} diff --git a/rpcs3/Emu/SysCalls/Modules/cellVideoUpload.cpp b/rpcs3/Emu/SysCalls/Modules/cellVideoUpload.cpp deleted file mode 100644 index a6d7c3862c..0000000000 --- a/rpcs3/Emu/SysCalls/Modules/cellVideoUpload.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/SysCalls/Modules.h" - -extern Module<> cellVideoUpload; - -s32 cellVideoUploadInitialize() -{ - throw EXCEPTION(""); -} - -Module<> cellVideoUpload("cellVideoUpload", []() -{ - REG_FUNC(cellVideoUpload, cellVideoUploadInitialize); -});