mirror of
https://github.com/BillyOutlast/aps3e.git
synced 2026-02-04 03:01:22 +01:00
sync
This commit is contained in:
@@ -72,7 +72,7 @@ extern std::shared_ptr<CPUDisAsm> make_disasm(const cpu_thread* cpu, shared_ptr<
|
||||
result->set_cpu_handle(std::move(handle));
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
template <>
|
||||
void fmt_class_string<cheat_type>::format(std::string& out, u64 arg)
|
||||
{
|
||||
@@ -94,7 +94,7 @@ void fmt_class_string<cheat_type>::format(std::string& out, u64 arg)
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
template <>
|
||||
void fmt_class_string<std::chrono::sys_time<typename std::chrono::system_clock::duration>>::format(std::string& out, u64 arg)
|
||||
{
|
||||
@@ -182,7 +182,7 @@ __attribute__((constructor)) static void init_localized_strings()
|
||||
|
||||
class android_save_dialog:public SaveDialogBase{
|
||||
public:
|
||||
s32 ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) override
|
||||
s32 ShowSaveDataList(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) override
|
||||
{
|
||||
LOGI("ShowSaveDataList(save_entries=%d, focused=%d, op=0x%x, listSet=*0x%x, enable_overlay=%d)", save_entries.size(), focused, op, listSet, enable_overlay);
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "util/asm.hpp"
|
||||
|
||||
|
||||
@@ -1,10 +1,32 @@
|
||||
#include "stdafx.h"
|
||||
#include "cheat_info.h"
|
||||
#include "Config.h"
|
||||
#include "StrUtil.h"
|
||||
|
||||
LOG_CHANNEL(log_cheat, "Cheat");
|
||||
|
||||
template <>
|
||||
void fmt_class_string<cheat_type>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_enum(out, arg, [](cheat_type value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case cheat_type::unsigned_8_cheat: return "Unsigned 8 bits";
|
||||
case cheat_type::unsigned_16_cheat: return "Unsigned 16 bits";
|
||||
case cheat_type::unsigned_32_cheat: return "Unsigned 32 bits";
|
||||
case cheat_type::unsigned_64_cheat: return "Unsigned 64 bits";
|
||||
case cheat_type::signed_8_cheat: return "Signed 8 bits";
|
||||
case cheat_type::signed_16_cheat: return "Signed 16 bits";
|
||||
case cheat_type::signed_32_cheat: return "Signed 32 bits";
|
||||
case cheat_type::signed_64_cheat: return "Signed 64 bits";
|
||||
case cheat_type::float_32_cheat: return "Float 32 bits";
|
||||
case cheat_type::max: break;
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
bool cheat_info::from_str(const std::string& cheat_line)
|
||||
{
|
||||
auto cheat_vec = fmt::split(cheat_line, {"@@@"}, false);
|
||||
|
||||
@@ -14,6 +14,7 @@ enum class cheat_type : u8
|
||||
signed_16_cheat,
|
||||
signed_32_cheat,
|
||||
signed_64_cheat,
|
||||
float_32_cheat,
|
||||
max
|
||||
};
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
|
||||
if (!next)
|
||||
{
|
||||
// Do not allow access beyond many element more at a time
|
||||
// Do not allow access beyond many element more at a time
|
||||
ensure(!installed && index - i < N * 2);
|
||||
|
||||
installed = true;
|
||||
@@ -384,17 +384,25 @@ public:
|
||||
template <typename T>
|
||||
class lf_queue final
|
||||
{
|
||||
atomic_t<u64> m_head{0};
|
||||
|
||||
lf_queue_item<T>* load(u64 value) const noexcept
|
||||
private:
|
||||
struct fat_ptr
|
||||
{
|
||||
return reinterpret_cast<lf_queue_item<T>*>(value >> 16);
|
||||
u64 ptr{};
|
||||
u32 is_non_null{};
|
||||
u32 reserved{};
|
||||
};
|
||||
|
||||
atomic_t<fat_ptr> m_head{fat_ptr{}};
|
||||
|
||||
lf_queue_item<T>* load(fat_ptr value) const noexcept
|
||||
{
|
||||
return reinterpret_cast<lf_queue_item<T>*>(value.ptr);
|
||||
}
|
||||
|
||||
// Extract all elements and reverse element order (FILO to FIFO)
|
||||
lf_queue_item<T>* reverse() noexcept
|
||||
{
|
||||
if (auto* head = load(m_head) ? load(m_head.exchange(0)) : nullptr)
|
||||
if (auto* head = load(m_head) ? load(m_head.exchange(fat_ptr{})) : nullptr)
|
||||
{
|
||||
if (auto* prev = head->m_link)
|
||||
{
|
||||
@@ -420,7 +428,7 @@ public:
|
||||
|
||||
lf_queue(lf_queue&& other) noexcept
|
||||
{
|
||||
m_head.release(other.m_head.exchange(0));
|
||||
m_head.release(other.m_head.exchange(fat_ptr{}));
|
||||
}
|
||||
|
||||
lf_queue& operator=(lf_queue&& other) noexcept
|
||||
@@ -430,8 +438,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
delete load(m_head);
|
||||
m_head.release(other.m_head.exchange(0));
|
||||
delete load(m_head.exchange(other.m_head.exchange(fat_ptr{})));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -442,12 +449,17 @@ public:
|
||||
|
||||
void wait(std::nullptr_t /*null*/ = nullptr) noexcept
|
||||
{
|
||||
if (m_head == 0)
|
||||
if (!operator bool())
|
||||
{
|
||||
utils::bless<atomic_t<u32>>(&m_head)[1].wait(0);
|
||||
get_wait_atomic().wait(0);
|
||||
}
|
||||
}
|
||||
|
||||
atomic_t<u32> &get_wait_atomic()
|
||||
{
|
||||
return *utils::bless<atomic_t<u32>>(&m_head.raw().is_non_null);
|
||||
}
|
||||
|
||||
const volatile void* observe() const noexcept
|
||||
{
|
||||
return load(m_head);
|
||||
@@ -455,7 +467,7 @@ public:
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return m_head != 0;
|
||||
return observe() != nullptr;
|
||||
}
|
||||
|
||||
template <bool Notify = true, typename... Args>
|
||||
@@ -464,25 +476,25 @@ public:
|
||||
auto oldv = m_head.load();
|
||||
auto item = new lf_queue_item<T>(load(oldv), std::forward<Args>(args)...);
|
||||
|
||||
while (!m_head.compare_exchange(oldv, reinterpret_cast<u64>(item) << 16))
|
||||
while (!m_head.compare_exchange(oldv, fat_ptr{reinterpret_cast<u64>(item), item != nullptr, 0}))
|
||||
{
|
||||
item->m_link = load(oldv);
|
||||
}
|
||||
|
||||
if (!oldv && Notify)
|
||||
if (!oldv.ptr && Notify)
|
||||
{
|
||||
// Notify only if queue was empty
|
||||
notify(true);
|
||||
}
|
||||
|
||||
return !oldv;
|
||||
return !oldv.ptr;
|
||||
}
|
||||
|
||||
void notify(bool force = false)
|
||||
{
|
||||
if (force || operator bool())
|
||||
{
|
||||
utils::bless<atomic_t<u32>>(&m_head)[1].notify_one();
|
||||
get_wait_atomic().notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,7 +510,7 @@ public:
|
||||
lf_queue_slice<T> pop_all_reversed()
|
||||
{
|
||||
lf_queue_slice<T> result;
|
||||
result.m_head = load(m_head.exchange(0));
|
||||
result.m_head = load(m_head.exchange(fat_ptr{}));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "util/types.hpp"
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
|
||||
// Thread-safe object pool with garbage collection
|
||||
class universal_pool
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "Utilities/Thread.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_spu.h"
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ struct audio_port
|
||||
// Handle copy ctor of atomic var
|
||||
audio_port(const audio_port& r)
|
||||
{
|
||||
std::memcpy(this, &r, sizeof(r));
|
||||
std::memcpy(static_cast<void*>(this), &r, sizeof(r));
|
||||
}
|
||||
|
||||
ENABLE_BITWISE_SERIALIZATION;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include "util/endian.hpp"
|
||||
|
||||
// Error codes
|
||||
enum CellAudioInError : u32
|
||||
@@ -76,7 +75,7 @@ struct CellAudioInDeviceInfo
|
||||
u8 reserved[12];
|
||||
be_t<u64> deviceId;
|
||||
be_t<u64> type;
|
||||
char name[64];
|
||||
char name[64]; // Not necessarily null terminated!
|
||||
CellAudioInSoundMode availableModes[16];
|
||||
};
|
||||
|
||||
|
||||
@@ -26,11 +26,6 @@ void fmt_class_string<CellDaisyError>::format(std::string& out, u64 arg)
|
||||
});
|
||||
}
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
using LFQueue2 = struct CellDaisyLFQueue2;
|
||||
using Lock = struct CellDaisyLock;
|
||||
using ScatterGatherInterlock = struct CellDaisyScatterGatherInterlock;
|
||||
@@ -38,134 +33,134 @@ using AtomicInterlock = volatile struct CellDaisyAtomicInterlock;
|
||||
|
||||
error_code cellDaisyLFQueue2GetPopPointer(vm::ptr<LFQueue2> queue, vm::ptr<s32> pPointer, u32 isBlocking)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLFQueue2GetPopPointer()");
|
||||
cellDaisy.todo("cellDaisyLFQueue2GetPopPointer(queue=*0x%x, pPointer=*0x%x, isBlocking=%d)", queue, pPointer, isBlocking);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLFQueue2CompletePopPointer(vm::ptr<LFQueue2> queue, s32 pointer, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal, u32 isQueueFull)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLFQueue2CompletePopPointer()");
|
||||
cellDaisy.todo("cellDaisyLFQueue2CompletePopPointer(queue=*0x%x, pointer=0x%x, fpSendSignal=*0x%x, isQueueFull=%d)", queue, pointer, fpSendSignal, isQueueFull);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellDaisyLFQueue2PushOpen(vm::ptr<LFQueue2> queue)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLFQueue2PushOpen()");
|
||||
cellDaisy.todo("cellDaisyLFQueue2PushOpen(queue=*0x%x)", queue);
|
||||
}
|
||||
|
||||
error_code cellDaisyLFQueue2PushClose(vm::ptr<LFQueue2> queue, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLFQueue2PushClose()");
|
||||
cellDaisy.todo("cellDaisyLFQueue2PushClose(queue=*0x%x, fpSendSignal=*0x%x)", queue, fpSendSignal);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellDaisyLFQueue2PopOpen(vm::ptr<LFQueue2> queue)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLFQueue2PopOpen()");
|
||||
cellDaisy.todo("cellDaisyLFQueue2PopOpen(queue=*0x%x)", queue);
|
||||
}
|
||||
|
||||
error_code cellDaisyLFQueue2PopClose(vm::ptr<LFQueue2> queue, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLFQueue2PopClose()");
|
||||
cellDaisy.todo("cellDaisyLFQueue2PopClose(queue=*0x%x, fpSendSignal=*0x%x)", queue, fpSendSignal);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLFQueue2HasUnfinishedConsumer(vm::ptr<LFQueue2> queue, u32 isCancelled)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLFQueue2HasUnfinishedConsumer()");
|
||||
cellDaisy.todo("cellDaisyLFQueue2HasUnfinishedConsumer(queue=*0x%x, isCancelled=%d)", queue, isCancelled);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisy_snprintf(vm::ptr<char> buffer, u32 count, vm::cptr<char> fmt, ppu_va_args_t fmt_args)
|
||||
{
|
||||
cellDaisy.todo("cellDaisy_snprintf()");
|
||||
cellDaisy.todo("cellDaisy_snprintf(buffer=*0x%x, count=%d, fmt=*0x%x, fmt_args=%d)", buffer, count, fmt, fmt_args.count);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLock_initialize(vm::ptr<Lock> _this, u32 depth)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLock_initialize()");
|
||||
cellDaisy.todo("cellDaisyLock_initialize(_this=*0x%x, depth=%d)", _this, depth);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLock_getNextHeadPointer(vm::ptr<Lock> _this)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLock_getNextHeadPointer()");
|
||||
cellDaisy.todo("cellDaisyLock_getNextHeadPointer(_this=*0x%x)", _this);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLock_getNextTailPointer(vm::ptr<Lock> _this)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLock_getNextTailPointer()");
|
||||
cellDaisy.todo("cellDaisyLock_getNextTailPointer(_this=*0x%x)", _this);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLock_completeConsume(vm::ptr<Lock> _this, u32 pointer)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLock_completeConsume()");
|
||||
cellDaisy.todo("cellDaisyLock_completeConsume(_this=*0x%x, pointer=0x%x)", _this, pointer);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLock_completeProduce(vm::ptr<Lock> _this, u32 pointer)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLock_completeProduce()");
|
||||
cellDaisy.todo("cellDaisyLock_completeProduce(_this=*0x%x, pointer=0x%x)", _this, pointer);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLock_pushOpen(vm::ptr<Lock> _this)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLock_pushOpen()");
|
||||
cellDaisy.todo("cellDaisyLock_pushOpen(_this=*0x%x)", _this);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLock_pushClose(vm::ptr<Lock> _this)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLock_pushClose()");
|
||||
cellDaisy.todo("cellDaisyLock_pushClose(_this=*0x%x)", _this);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLock_popOpen(vm::ptr<Lock> _this)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLock_popOpen()");
|
||||
cellDaisy.todo("cellDaisyLock_popOpen(_this=*0x%x)", _this);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyLock_popClose(vm::ptr<Lock> _this)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyLock_popClose()");
|
||||
cellDaisy.todo("cellDaisyLock_popClose(_this=*0x%x)", _this);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellDaisyScatterGatherInterlock_1(vm::ptr<ScatterGatherInterlock> _this, vm::ptr<AtomicInterlock> ea, u32 size, vm::ptr<void> eaSignal, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_1()");
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_1(_this=*0x%x, ea=*0x%x, size=%d, eaSignal=*0x%x, fpSendSignal=*0x%x)", _this, ea, size, eaSignal, fpSendSignal);
|
||||
}
|
||||
|
||||
void cellDaisyScatterGatherInterlock_2(vm::ptr<ScatterGatherInterlock> _this, u32 size, vm::ptr<u32> ids, u32 numSpus, u8 spup)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_2()");
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_2(_this=*0x%x, size=%d, ids=*0x%x, numSpus=%d, spup=%d)", _this, size, ids, numSpus, spup);
|
||||
}
|
||||
|
||||
void cellDaisyScatterGatherInterlock_9tor(vm::ptr<ScatterGatherInterlock> _this)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_9tor()");
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_9tor(_this=*0x%x)", _this);
|
||||
}
|
||||
|
||||
error_code cellDaisyScatterGatherInterlock_probe(vm::ptr<ScatterGatherInterlock> _this, u32 isBlocking)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_probe()");
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_probe(_this=*0x%x, isBlocking=%d)", _this, isBlocking);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellDaisyScatterGatherInterlock_release(vm::ptr<ScatterGatherInterlock> _this)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_release()");
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_release(_this=*0x%x)", _this);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellDaisyScatterGatherInterlock_proceedSequenceNumber(vm::ptr<ScatterGatherInterlock> _this)
|
||||
{
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_proceedSequenceNumber()");
|
||||
cellDaisy.todo("cellDaisyScatterGatherInterlock_proceedSequenceNumber(_this=*0x%x)", _this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
||||
LOG_CHANNEL(cellDmux);
|
||||
|
||||
template <>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#include "cellPamf.h"
|
||||
|
||||
// Error Codes
|
||||
enum CellDmuxError :u32
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "cellPamf.h"
|
||||
#include "cellDmux.h"
|
||||
#include "cellDmuxPamf.h"
|
||||
|
||||
|
||||
@@ -161,7 +161,8 @@ enum CellGemVideoConvertFormatEnum : s32
|
||||
// External device IDs (types)
|
||||
enum
|
||||
{
|
||||
SHARP_SHOOTER_DEVICE_ID = 0x8081
|
||||
SHARP_SHOOTER_DEVICE_ID = 0x8081,
|
||||
RACING_WHEEL_DEVICE_ID = 0x8101
|
||||
};
|
||||
|
||||
struct CellGemAttribute
|
||||
|
||||
@@ -9,15 +9,8 @@
|
||||
#include "Emu/Cell/lv2/sys_fs.h"
|
||||
#include "cellGifDec.h"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
||||
LOG_CHANNEL(cellGifDec);
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
template <>
|
||||
void fmt_class_string<CellGifDecError>::format(std::string& out, u64 arg)
|
||||
{
|
||||
@@ -273,7 +266,7 @@ error_code cellGifDecReadHeader(vm::ptr<GifDecoder> mainHandle, vm::ptr<GifStrea
|
||||
return CELL_GIFDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
const u32& fd = subHandle->fd;
|
||||
const u32 fd = subHandle->fd;
|
||||
CellGifDecInfo& current_info = subHandle->info;
|
||||
|
||||
// Write the header to buffer
|
||||
@@ -302,7 +295,7 @@ error_code cellGifDecReadHeader(vm::ptr<GifDecoder> mainHandle, vm::ptr<GifStrea
|
||||
return CELL_GIFDEC_ERROR_STREAM_FORMAT; // Surprisingly there is no error code related with headerss
|
||||
}
|
||||
|
||||
u8 packedField = buffer[10];
|
||||
const u8 packedField = buffer[10];
|
||||
current_info.SWidth = buffer[6] + buffer[7] * 0x100;
|
||||
current_info.SHeight = buffer[8] + buffer[9] * 0x100;
|
||||
current_info.SGlobalColorTableFlag = packedField >> 7;
|
||||
@@ -520,8 +513,8 @@ error_code cellGifDecDecodeData(vm::ptr<GifDecoder> mainHandle, vm::cptr<GifStre
|
||||
return CELL_GIFDEC_ERROR_STREAM_FORMAT;
|
||||
|
||||
const int bytesPerLine = static_cast<int>(dataCtrlParam->outputBytesPerLine);
|
||||
const char nComponents = 4;
|
||||
uint image_size = width * height * nComponents;
|
||||
constexpr char nComponents = 4;
|
||||
const u32 image_size = width * height * nComponents;
|
||||
|
||||
switch(current_outParam.outputColorSpace)
|
||||
{
|
||||
@@ -541,9 +534,8 @@ error_code cellGifDecDecodeData(vm::ptr<GifDecoder> mainHandle, vm::cptr<GifStre
|
||||
{
|
||||
memcpy(data.get_ptr(), image.get(), image_size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GIFDEC_ARGB:
|
||||
{
|
||||
if (bytesPerLine > width * nComponents) // Check if we need padding
|
||||
@@ -579,9 +571,8 @@ error_code cellGifDecDecodeData(vm::ptr<GifDecoder> mainHandle, vm::cptr<GifStre
|
||||
}
|
||||
std::memcpy(data.get_ptr(), img.get(), image_size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return CELL_GIFDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@ error_code cellHttpUtilEscapeUri(vm::ptr<char> out, u32 outSize, vm::cptr<u8> in
|
||||
|
||||
for (u32 pos = 0; rindex >= 0; rindex--, pos++)
|
||||
{
|
||||
char c1 = in[pos];
|
||||
const char c1 = in[pos];
|
||||
|
||||
if (false) // DAT[c1] == '\x03') // TODO
|
||||
{
|
||||
@@ -529,7 +529,7 @@ error_code cellHttpUtilEscapeUri(vm::ptr<char> out, u32 outSize, vm::cptr<u8> in
|
||||
return CELL_HTTP_UTIL_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
const char* chars = "0123456789ABCDEF";
|
||||
constexpr const char* chars = "0123456789ABCDEF";
|
||||
out[out_pos++] = '%'; // 0x25
|
||||
out[out_pos++] = chars[c1 >> 4];
|
||||
out[out_pos++] = chars[c1 & 0xf];
|
||||
@@ -618,7 +618,7 @@ error_code cellHttpUtilFormUrlEncode(vm::ptr<char> out, u32 outSize, vm::cptr<u8
|
||||
|
||||
for (u32 pos = 0; rindex >= 0; rindex--, pos++)
|
||||
{
|
||||
char c1 = in[pos];
|
||||
const char c1 = in[pos];
|
||||
|
||||
if (c1 == ' ')
|
||||
{
|
||||
@@ -645,7 +645,7 @@ error_code cellHttpUtilFormUrlEncode(vm::ptr<char> out, u32 outSize, vm::cptr<u8
|
||||
return CELL_HTTP_UTIL_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
const char* chars = "0123456789ABCDEF";
|
||||
constexpr const char* chars = "0123456789ABCDEF";
|
||||
out[out_pos++] = '%'; // 0x25
|
||||
out[out_pos++] = chars[c1 >> 4];
|
||||
out[out_pos++] = chars[c1 & 0xf];
|
||||
@@ -707,7 +707,7 @@ error_code cellHttpUtilFormUrlDecode(vm::ptr<u8> out, u32 size, vm::cptr<char> i
|
||||
for (s32 index = 0, pos = 0;; index++)
|
||||
{
|
||||
size_needed = index + 1;
|
||||
char c1 = in[pos++];
|
||||
const char c1 = in[pos++];
|
||||
|
||||
if (!c1)
|
||||
{
|
||||
@@ -731,7 +731,7 @@ error_code cellHttpUtilFormUrlDecode(vm::ptr<u8> out, u32 size, vm::cptr<char> i
|
||||
|
||||
const auto check_char = [](b8 c)
|
||||
{
|
||||
u32 utmp = static_cast<u32>(c);
|
||||
const u32 utmp = static_cast<u32>(c);
|
||||
s32 stmp = utmp - 48;
|
||||
if (static_cast<u8>(c - 48) > 9)
|
||||
{
|
||||
|
||||
@@ -9,15 +9,8 @@
|
||||
#include "Emu/Cell/lv2/sys_fs.h"
|
||||
#include "cellJpgDec.h"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
||||
LOG_CHANNEL(cellJpgDec);
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
template <>
|
||||
void fmt_class_string<CellJpgDecError>::format(std::string& out, u64 arg)
|
||||
{
|
||||
@@ -42,19 +35,19 @@ void fmt_class_string<CellJpgDecError>::format(std::string& out, u64 arg)
|
||||
|
||||
error_code cellJpgDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellJpgDec);
|
||||
cellJpgDec.todo("cellJpgDecCreate(mainHandle=0x%x, threadInParam=0x%x, threadOutParam=0x%x)", mainHandle, threadInParam, threadOutParam);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellJpgDecExtCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam, u32 extThreadInParam, u32 extThreadOutParam)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellJpgDec);
|
||||
cellJpgDec.todo("cellJpgDecExtCreate(mainHandle=0x%x, threadInParam=0x%x, threadOutParam=0x%x, extThreadInParam=0x%x, extThreadOutParam=0x%x)", mainHandle, threadInParam, threadOutParam, extThreadInParam, extThreadOutParam);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellJpgDecDestroy(u32 mainHandle)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellJpgDec);
|
||||
cellJpgDec.todo("cellJpgDecDestroy(mainHandle=0x%x)", mainHandle);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -76,7 +69,7 @@ error_code cellJpgDecOpen(u32 mainHandle, vm::ptr<u32> subHandle, vm::ptr<CellJp
|
||||
case CELL_JPGDEC_FILE:
|
||||
{
|
||||
// Get file descriptor and size
|
||||
const auto real_path = vfs::get(src->fileName.get_ptr());
|
||||
const std::string real_path = vfs::get(src->fileName.get_ptr());
|
||||
fs::file file_s(real_path);
|
||||
if (!file_s) return CELL_JPGDEC_ERROR_OPEN_FILE;
|
||||
|
||||
@@ -127,8 +120,8 @@ error_code cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellJpgDe
|
||||
return CELL_JPGDEC_ERROR_FATAL;
|
||||
}
|
||||
|
||||
const u32& fd = subHandle_data->fd;
|
||||
const u64& fileSize = subHandle_data->fileSize;
|
||||
const u32 fd = subHandle_data->fd;
|
||||
const u64 fileSize = subHandle_data->fileSize;
|
||||
CellJpgDecInfo& current_info = subHandle_data->info;
|
||||
|
||||
// Write the header to buffer
|
||||
@@ -158,12 +151,12 @@ error_code cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellJpgDe
|
||||
|
||||
u32 i = 4;
|
||||
|
||||
if(i >= fileSize)
|
||||
if (i >= fileSize)
|
||||
return CELL_JPGDEC_ERROR_HEADER;
|
||||
|
||||
u16 block_length = buffer[i] * 0xFF + buffer[i+1];
|
||||
u16 block_length = buffer[i] * 0xFF + buffer[i + 1];
|
||||
|
||||
while(true)
|
||||
while (true)
|
||||
{
|
||||
i += block_length; // Increase the file index to get to the next block
|
||||
if (i >= fileSize || // Check to protect against segmentation faults
|
||||
@@ -172,15 +165,15 @@ error_code cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellJpgDe
|
||||
return CELL_JPGDEC_ERROR_HEADER;
|
||||
}
|
||||
|
||||
if(buffer[i+1] == 0xC0)
|
||||
if (buffer[i + 1] == 0xC0)
|
||||
break; // 0xFFC0 is the "Start of frame" marker which contains the file size
|
||||
|
||||
i += 2; // Skip the block marker
|
||||
block_length = buffer[i] * 0xFF + buffer[i+1]; // Go to the next block
|
||||
block_length = buffer[i] * 0xFF + buffer[i + 1]; // Go to the next block
|
||||
}
|
||||
|
||||
current_info.imageWidth = buffer[i+7]*0x100 + buffer[i+8];
|
||||
current_info.imageHeight = buffer[i+5]*0x100 + buffer[i+6];
|
||||
current_info.imageWidth = buffer[i + 7] * 0x100 + buffer[i + 8];
|
||||
current_info.imageHeight = buffer[i + 5] * 0x100 + buffer[i + 6];
|
||||
current_info.numComponents = 3; // Unimplemented
|
||||
current_info.colorSpace = CELL_JPG_RGB;
|
||||
|
||||
@@ -232,7 +225,7 @@ error_code cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data,
|
||||
}
|
||||
|
||||
//Decode JPG file. (TODO: Is there any faster alternative? Can we do it without external libraries?)
|
||||
int width, height, actual_components;
|
||||
int width = 0, height = 0, actual_components = 0;
|
||||
auto image = std::unique_ptr<unsigned char,decltype(&::free)>
|
||||
(
|
||||
stbi_load_from_memory(jpg.get(), ::narrow<int>(fileSize), &width, &height, &actual_components, 4),
|
||||
@@ -267,18 +260,17 @@ error_code cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data,
|
||||
{
|
||||
memcpy(data.get_ptr(), image.get(), image_size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_JPG_ARGB:
|
||||
{
|
||||
const int nComponents = 4;
|
||||
constexpr int nComponents = 4;
|
||||
image_size *= nComponents;
|
||||
if (bytesPerLine > width * nComponents || flip) //check if we need padding
|
||||
{
|
||||
//TODO: Find out if we can't do padding without an extra copy
|
||||
const int linesize = std::min(bytesPerLine, width * nComponents);
|
||||
const auto output = std::make_unique<char[]>(linesize);
|
||||
std::vector<char> output(image_size);
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
const int dstOffset = i * bytesPerLine;
|
||||
@@ -290,33 +282,32 @@ error_code cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data,
|
||||
output[j + 2] = image.get()[srcOffset + j + 1];
|
||||
output[j + 3] = image.get()[srcOffset + j + 2];
|
||||
}
|
||||
std::memcpy(&data[dstOffset], output.get(), linesize);
|
||||
std::memcpy(&data[dstOffset], output.data(), linesize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto img = std::make_unique<uint[]>(image_size);
|
||||
uint* source_current = reinterpret_cast<uint*>(image.get());
|
||||
uint* dest_current = img.get();
|
||||
for (uint i = 0; i < image_size / nComponents; i++)
|
||||
std::vector<u32> img(image_size);
|
||||
const u32* source_current = reinterpret_cast<const u32*>(image.get());
|
||||
u32* dest_current = img.data();
|
||||
for (u32 i = 0; i < image_size / nComponents; i++)
|
||||
{
|
||||
uint val = *source_current;
|
||||
const u32 val = *source_current;
|
||||
*dest_current = (val >> 24) | (val << 8); // set alpha (A8) as leftmost byte
|
||||
source_current++;
|
||||
dest_current++;
|
||||
}
|
||||
std::memcpy(data.get_ptr(), img.get(), image_size);
|
||||
std::memcpy(data.get_ptr(), img.data(), image_size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_JPG_GRAYSCALE:
|
||||
case CELL_JPG_YCbCr:
|
||||
case CELL_JPG_UPSAMPLE_ONLY:
|
||||
case CELL_JPG_GRAYSCALE_TO_ALPHA_RGBA:
|
||||
case CELL_JPG_GRAYSCALE_TO_ALPHA_ARGB:
|
||||
cellJpgDec.error("cellJpgDecDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace);
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
return CELL_JPGDEC_ERROR_ARG;
|
||||
@@ -324,7 +315,7 @@ error_code cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data,
|
||||
|
||||
dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_FINISH;
|
||||
|
||||
if(dataCtrlParam->outputBytesPerLine)
|
||||
if (dataCtrlParam->outputBytesPerLine)
|
||||
dataOutInfo->outputLines = static_cast<u32>(image_size / dataCtrlParam->outputBytesPerLine);
|
||||
|
||||
return CELL_OK;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "cellKb.h"
|
||||
#include "Emu/Io/Keyboard.h"
|
||||
|
||||
LOG_CHANNEL(cellKey2char);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,25 +52,25 @@ enum
|
||||
L10N_CODEPAGE_863,
|
||||
L10N_CODEPAGE_866,
|
||||
L10N_CODEPAGE_932,
|
||||
L10N_SHIFT_JIS,
|
||||
L10N_SHIFT_JIS = L10N_CODEPAGE_932,
|
||||
L10N_CODEPAGE_936,
|
||||
L10N_GBK,
|
||||
L10N_GBK = L10N_CODEPAGE_936,
|
||||
L10N_CODEPAGE_949,
|
||||
L10N_UHC,
|
||||
L10N_UHC = L10N_CODEPAGE_949,
|
||||
L10N_CODEPAGE_950,
|
||||
L10N_BIG5,
|
||||
L10N_BIG5 = L10N_CODEPAGE_950,
|
||||
L10N_CODEPAGE_1251,
|
||||
L10N_CODEPAGE_1252,
|
||||
L10N_EUC_CN,
|
||||
L10N_EUC_JP,
|
||||
L10N_EUC_KR,
|
||||
L10N_ISO_2022_JP,
|
||||
L10N_JIS,
|
||||
L10N_JIS = L10N_ISO_2022_JP,
|
||||
L10N_ARIB,
|
||||
L10N_HZ,
|
||||
L10N_GB18030,
|
||||
L10N_RIS_506,
|
||||
L10N_MUSIC_SHIFT_JIS,
|
||||
L10N_MUSIC_SHIFT_JIS = L10N_RIS_506,
|
||||
//FW 3.10 and below
|
||||
L10N_CODEPAGE_852,
|
||||
L10N_CODEPAGE_1250,
|
||||
@@ -88,3 +88,12 @@ enum
|
||||
L10N_CODEPAGE_869,
|
||||
_L10N_CODE_
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
UTF16_SURROGATES_MASK1 = 0xf800,
|
||||
UTF16_SURROGATES_MASK2 = 0xfc00,
|
||||
UTF16_SURROGATES = 0xd800,
|
||||
UTF16_HIGH_SURROGATES = 0xd800,
|
||||
UTF16_LOW_SURROGATES = 0xdc00,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "Emu/Io/MouseHandler.h"
|
||||
|
||||
@@ -177,6 +177,11 @@ struct music_state
|
||||
return CELL_MUSIC_ERROR_NO_MORE_CONTENT;
|
||||
}
|
||||
|
||||
if (!fs::is_file(path))
|
||||
{
|
||||
cellMusic.error("set_playback_command: File does not exist: '%s'", path);
|
||||
}
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case CELL_MUSIC_PB_CMD_FASTFORWARD:
|
||||
@@ -213,19 +218,29 @@ error_code cell_music_select_contents()
|
||||
error_code error = rsx::overlays::show_media_list_dialog(rsx::overlays::media_list_dialog::media_type::audio, vfs_dir_path, title,
|
||||
[&music](s32 status, utils::media_info info)
|
||||
{
|
||||
sysutil_register_cb([&music, info, status](ppu_thread& ppu) -> s32
|
||||
sysutil_register_cb([&music, info = std::move(info), status](ppu_thread& ppu) -> s32
|
||||
{
|
||||
std::lock_guard lock(music.mtx);
|
||||
const u32 result = status >= 0 ? u32{CELL_OK} : u32{CELL_MUSIC_CANCELED};
|
||||
if (result == CELL_OK)
|
||||
{
|
||||
// Let's always choose the whole directory for now
|
||||
std::string track;
|
||||
std::string dir = info.path;
|
||||
if (fs::is_file(info.path))
|
||||
{
|
||||
track = std::move(dir);
|
||||
dir = fs::get_parent_dir(track);
|
||||
}
|
||||
|
||||
music_selection_context context{};
|
||||
context.set_playlist(info.path);
|
||||
context.set_playlist(dir);
|
||||
context.set_track(track);
|
||||
// TODO: context.repeat_mode = CELL_SEARCH_REPEATMODE_NONE;
|
||||
// TODO: context.context_option = CELL_SEARCH_CONTEXTOPTION_NONE;
|
||||
music.current_selection_context = context;
|
||||
music.current_selection_context = std::move(context);
|
||||
music.current_selection_context.create_playlist(music_selection_context::get_next_hash());
|
||||
cellMusic.success("Media list dialog: selected entry '%s'", context.playlist.front());
|
||||
cellMusic.success("Media list dialog: selected entry '%s'", music.current_selection_context.playlist.front());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -556,7 +571,7 @@ error_code cellMusicSetPlaybackCommand2(s32 command, vm::ptr<void> param)
|
||||
auto& music = g_fxo->get<music_state>();
|
||||
|
||||
if (!music.func)
|
||||
return CELL_MUSIC2_ERROR_GENERIC;
|
||||
return { CELL_MUSIC2_ERROR_GENERIC, "Not initialized" };
|
||||
|
||||
error_code result = CELL_OK;
|
||||
|
||||
@@ -585,7 +600,7 @@ error_code cellMusicSetPlaybackCommand(s32 command, vm::ptr<void> param)
|
||||
auto& music = g_fxo->get<music_state>();
|
||||
|
||||
if (!music.func)
|
||||
return CELL_MUSIC_ERROR_GENERIC;
|
||||
return { CELL_MUSIC_ERROR_GENERIC, "Not initialized" };
|
||||
|
||||
error_code result = CELL_OK;
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ struct music_selection_context
|
||||
void set_playlist(const std::string& path);
|
||||
void create_playlist(const std::string& new_hash);
|
||||
bool load_playlist();
|
||||
void set_track(std::string_view track);
|
||||
u32 step_track(bool next);
|
||||
|
||||
operator bool() const
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
#include "cellSysutil.h"
|
||||
#include "util/media_utils.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
|
||||
LOG_CHANNEL(cellMusicDecode);
|
||||
|
||||
template<>
|
||||
@@ -140,19 +137,29 @@ error_code cell_music_decode_select_contents()
|
||||
error_code error = rsx::overlays::show_media_list_dialog(rsx::overlays::media_list_dialog::media_type::audio, vfs_dir_path, title,
|
||||
[&dec](s32 status, utils::media_info info)
|
||||
{
|
||||
sysutil_register_cb([&dec, info, status](ppu_thread& ppu) -> s32
|
||||
sysutil_register_cb([&dec, info = std::move(info), status](ppu_thread& ppu) -> s32
|
||||
{
|
||||
std::lock_guard lock(dec.mutex);
|
||||
const u32 result = status >= 0 ? u32{CELL_OK} : u32{CELL_MUSIC_DECODE_CANCELED};
|
||||
if (result == CELL_OK)
|
||||
{
|
||||
// Let's always choose the whole directory for now
|
||||
std::string track;
|
||||
std::string dir = info.path;
|
||||
if (fs::is_file(info.path))
|
||||
{
|
||||
track = std::move(dir);
|
||||
dir = fs::get_parent_dir(track);
|
||||
}
|
||||
|
||||
music_selection_context context{};
|
||||
context.set_playlist(info.path);
|
||||
context.set_playlist(dir);
|
||||
context.set_track(track);
|
||||
// TODO: context.repeat_mode = CELL_SEARCH_REPEATMODE_NONE;
|
||||
// TODO: context.context_option = CELL_SEARCH_CONTEXTOPTION_NONE;
|
||||
dec.current_selection_context = context;
|
||||
dec.current_selection_context = std::move(context);
|
||||
dec.current_selection_context.create_playlist(music_selection_context::get_next_hash());
|
||||
cellMusicDecode.success("Media list dialog: selected entry '%s'", context.playlist.front());
|
||||
cellMusicDecode.success("Media list dialog: selected entry '%s'", dec.current_selection_context.playlist.front());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/VFS.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
LOG_CHANNEL(cellMusicExport);
|
||||
|
||||
@@ -16,7 +16,7 @@ bool music_selection_context::set(const CellMusicSelectionContext& in)
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 pos = sizeof(magic);
|
||||
constexpr u32 pos = sizeof(magic);
|
||||
hash = &in.data[pos];
|
||||
|
||||
return load_playlist();
|
||||
@@ -77,7 +77,7 @@ std::string music_selection_context::get_yaml_path() const
|
||||
|
||||
if (!fs::create_path(path))
|
||||
{
|
||||
cellMusicSelectionContext.fatal("Failed to create path: %s (%s)", path, fs::g_tls_error);
|
||||
cellMusicSelectionContext.fatal("get_yaml_path: Failed to create path: %s (%s)", path, fs::g_tls_error);
|
||||
}
|
||||
|
||||
return path + hash + ".yml";
|
||||
@@ -101,14 +101,21 @@ void music_selection_context::set_playlist(const std::string& path)
|
||||
continue;
|
||||
}
|
||||
|
||||
playlist.push_back(dir_path + std::string(path + "/" + dir_entry.name).substr(vfs_dir_path.length()));
|
||||
std::string track = dir_path + std::string(path + "/" + dir_entry.name).substr(vfs_dir_path.length());
|
||||
cellMusicSelectionContext.notice("set_playlist: Adding track to playlist: '%s'. (path: '%s', name: '%s')", track, path, dir_entry.name);
|
||||
playlist.push_back(std::move(track));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
content_type = CELL_SEARCH_CONTENTTYPE_MUSIC;
|
||||
playlist.push_back(dir_path + path.substr(vfs_dir_path.length()));
|
||||
|
||||
std::string track = dir_path + path.substr(vfs_dir_path.length());
|
||||
cellMusicSelectionContext.notice("set_playlist: Adding track to playlist: '%s'. (path: '%s')", track, path);
|
||||
playlist.push_back(std::move(track));
|
||||
}
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
||||
void music_selection_context::create_playlist(const std::string& new_hash)
|
||||
@@ -116,7 +123,7 @@ void music_selection_context::create_playlist(const std::string& new_hash)
|
||||
hash = new_hash;
|
||||
|
||||
const std::string yaml_path = get_yaml_path();
|
||||
cellMusicSelectionContext.notice("Saving music playlist file %s", yaml_path);
|
||||
cellMusicSelectionContext.notice("create_playlist: Saving music playlist file %s", yaml_path);
|
||||
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginMap;
|
||||
@@ -138,9 +145,9 @@ void music_selection_context::create_playlist(const std::string& new_hash)
|
||||
|
||||
fs::pending_file file(yaml_path);
|
||||
|
||||
if (!file.file || (file.file.write(out.c_str(), out.size()), !file.commit()))
|
||||
if (!file.file || file.file.write(out.c_str(), out.size()) < out.size() || !file.commit())
|
||||
{
|
||||
cellMusicSelectionContext.error("Failed to create music playlist file %s (error=%s)", yaml_path, fs::g_tls_error);
|
||||
cellMusicSelectionContext.error("create_playlist: Failed to create music playlist file '%s' (error=%s)", yaml_path, fs::g_tls_error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +156,7 @@ bool music_selection_context::load_playlist()
|
||||
playlist.clear();
|
||||
|
||||
const std::string path = get_yaml_path();
|
||||
cellMusicSelectionContext.notice("Loading music playlist file %s", path);
|
||||
cellMusicSelectionContext.notice("load_playlist: Loading music playlist file '%s'", path);
|
||||
|
||||
std::string content;
|
||||
{
|
||||
@@ -158,7 +165,7 @@ bool music_selection_context::load_playlist()
|
||||
|
||||
if (!file)
|
||||
{
|
||||
cellMusicSelectionContext.error("Failed to load music playlist file %s: %s", path, fs::g_tls_error);
|
||||
cellMusicSelectionContext.error("load_playlist: Failed to load music playlist file '%s': %s", path, fs::g_tls_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -169,7 +176,7 @@ bool music_selection_context::load_playlist()
|
||||
|
||||
if (!error.empty() || !root)
|
||||
{
|
||||
cellMusicSelectionContext.error("Failed to load music playlist file %s:\n%s", path, error);
|
||||
cellMusicSelectionContext.error("load_playlist: Failed to load music playlist file '%s':\n%s", path, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -178,54 +185,54 @@ bool music_selection_context::load_playlist()
|
||||
const std::string version = get_yaml_node_value<std::string>(root["Version"], err);
|
||||
if (!err.empty())
|
||||
{
|
||||
cellMusicSelectionContext.error("No Version entry found. Error: '%s' (file: %s)", err, path);
|
||||
cellMusicSelectionContext.error("load_playlist: No Version entry found. Error: '%s' (file: '%s')", err, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version != target_version)
|
||||
{
|
||||
cellMusicSelectionContext.error("Version '%s' does not match music playlist target '%s' (file: %s)", version, target_version, path);
|
||||
cellMusicSelectionContext.error("load_playlist: Version '%s' does not match music playlist target '%s' (file: '%s')", version, target_version, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string file_type = get_yaml_node_value<std::string>(root["FileType"], err);
|
||||
if (!err.empty())
|
||||
{
|
||||
cellMusicSelectionContext.error("No FileType entry found. Error: '%s' (file: %s)", err, path);
|
||||
cellMusicSelectionContext.error("load_playlist: No FileType entry found. Error: '%s' (file: '%s')", err, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file_type != target_file_type)
|
||||
{
|
||||
cellMusicSelectionContext.error("FileType '%s' does not match music playlist target '%s' (file: %s)", file_type, target_file_type, path);
|
||||
cellMusicSelectionContext.error("load_playlist: FileType '%s' does not match music playlist target '%s' (file: '%s')", file_type, target_file_type, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
content_type = static_cast<CellSearchContentType>(get_yaml_node_value<u32>(root["ContentType"], err));
|
||||
if (!err.empty())
|
||||
{
|
||||
cellMusicSelectionContext.error("No ContentType entry found. Error: '%s' (file: %s)", err, path);
|
||||
cellMusicSelectionContext.error("load_playlist: No ContentType entry found. Error: '%s' (file: '%s')", err, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
context_option = static_cast<CellSearchContextOption>(get_yaml_node_value<u32>(root["ContextOption"], err));
|
||||
if (!err.empty())
|
||||
{
|
||||
cellMusicSelectionContext.error("No ContextOption entry found. Error: '%s' (file: %s)", err, path);
|
||||
cellMusicSelectionContext.error("load_playlist: No ContextOption entry found. Error: '%s' (file: '%s')", err, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
repeat_mode = static_cast<CellSearchRepeatMode>(get_yaml_node_value<u32>(root["RepeatMode"], err));
|
||||
if (!err.empty())
|
||||
{
|
||||
cellMusicSelectionContext.error("No RepeatMode entry found. Error: '%s' (file: %s)", err, path);
|
||||
cellMusicSelectionContext.error("load_playlist: No RepeatMode entry found. Error: '%s' (file: '%s')", err, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
first_track = get_yaml_node_value<u32>(root["FirstTrack"], err);
|
||||
if (!err.empty())
|
||||
{
|
||||
cellMusicSelectionContext.error("No FirstTrack entry found. Error: '%s' (file: %s)", err, path);
|
||||
cellMusicSelectionContext.error("load_playlist: No FirstTrack entry found. Error: '%s' (file: '%s')", err, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -233,24 +240,49 @@ bool music_selection_context::load_playlist()
|
||||
|
||||
if (!track_node || track_node.Type() != YAML::NodeType::Sequence)
|
||||
{
|
||||
cellMusicSelectionContext.error("No Tracks entry found or Tracks is not a Sequence. (file: %s)", path);
|
||||
cellMusicSelectionContext.error("load_playlist: No Tracks entry found or Tracks is not a Sequence. (file: '%s')", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (usz i = 0; i < track_node.size(); i++)
|
||||
{
|
||||
cellMusicSelectionContext.notice("load_playlist: Adding track to playlist: '%s'. (file: '%s')", track_node[i].Scalar(), path);
|
||||
playlist.push_back(track_node[i].Scalar());
|
||||
}
|
||||
|
||||
cellMusicSelectionContext.notice("load_playlist: Loaded music playlist file '%s' (context: %s)", path, to_string());
|
||||
valid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void music_selection_context::set_track(std::string_view track)
|
||||
{
|
||||
if (track.empty()) return;
|
||||
|
||||
if (playlist.empty())
|
||||
{
|
||||
cellMusicSelectionContext.error("set_track: No tracks to play... (requested path='%s')", track);
|
||||
return;
|
||||
}
|
||||
|
||||
for (usz i = 0; i < playlist.size(); i++)
|
||||
{
|
||||
cellMusicSelectionContext.error("set_track: Comparing track '%s' vs '%s'", track, playlist[i]);
|
||||
if (track.ends_with(playlist[i]))
|
||||
{
|
||||
first_track = current_track = static_cast<u32>(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cellMusicSelectionContext.error("set_track: Track '%s' not found...", track);
|
||||
}
|
||||
|
||||
u32 music_selection_context::step_track(bool next)
|
||||
{
|
||||
if (playlist.empty())
|
||||
{
|
||||
cellMusicSelectionContext.error("No tracks to play...");
|
||||
cellMusicSelectionContext.error("step_track: No tracks to play...");
|
||||
current_track = umax;
|
||||
return umax;
|
||||
}
|
||||
@@ -265,7 +297,7 @@ u32 music_selection_context::step_track(bool next)
|
||||
if (++current_track >= playlist.size())
|
||||
{
|
||||
// We are at the end of the playlist.
|
||||
cellMusicSelectionContext.notice("No more tracks to play in playlist...");
|
||||
cellMusicSelectionContext.notice("step_track: No more tracks to play in playlist...");
|
||||
current_track = umax;
|
||||
return umax;
|
||||
}
|
||||
@@ -276,7 +308,7 @@ u32 music_selection_context::step_track(bool next)
|
||||
if (current_track == 0)
|
||||
{
|
||||
// We are at the start of the playlist.
|
||||
cellMusicSelectionContext.notice("No more tracks to play in playlist...");
|
||||
cellMusicSelectionContext.notice("step_track: No more tracks to play in playlist...");
|
||||
current_track = umax;
|
||||
return umax;
|
||||
}
|
||||
@@ -314,13 +346,13 @@ u32 music_selection_context::step_track(bool next)
|
||||
case CELL_SEARCH_REPEATMODE_NOREPEAT1:
|
||||
{
|
||||
// We are done. We only wanted to decode a single track.
|
||||
cellMusicSelectionContext.notice("No more tracks to play...");
|
||||
cellMusicSelectionContext.notice("step_track: No more tracks to play...");
|
||||
current_track = umax;
|
||||
return umax;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fmt::throw_exception("Unknown repeat mode %d", static_cast<u32>(repeat_mode));
|
||||
fmt::throw_exception("step_track: Unknown repeat mode %d", static_cast<u32>(repeat_mode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +361,7 @@ u32 music_selection_context::step_track(bool next)
|
||||
if (next ? current_track == 0 : current_track == (playlist.size() - 1))
|
||||
{
|
||||
// We reached the first or last track again. Let's shuffle!
|
||||
cellMusicSelectionContext.notice("Shuffling playlist...");
|
||||
cellMusicSelectionContext.notice("step_track: Shuffling playlist...");
|
||||
auto engine = std::default_random_engine{};
|
||||
std::shuffle(std::begin(playlist), std::end(playlist), engine);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "Emu/system_config.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
|
||||
#include "cellGame.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/system_config.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/Io/interception.h"
|
||||
#include "Emu/Io/Keyboard.h"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/VFS.h"
|
||||
#include "Emu/System.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/VFS.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
LOG_CHANNEL(cellPhotoExport);
|
||||
|
||||
@@ -19,11 +19,6 @@ typedef png_bytep iCCP_profile_type;
|
||||
typedef png_charp iCCP_profile_type;
|
||||
#endif
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
LOG_CHANNEL(cellPngDec);
|
||||
|
||||
template <>
|
||||
@@ -149,7 +144,7 @@ void pngDecRowCallback(png_structp png_ptr, png_bytep new_row, png_uint_32 row_n
|
||||
png_progressive_combine_row(png_ptr, data, new_row);
|
||||
}
|
||||
|
||||
void pngDecInfoCallback(png_structp png_ptr, png_infop info)
|
||||
void pngDecInfoCallback(png_structp png_ptr, png_infop /*info*/)
|
||||
{
|
||||
PngStream* stream = static_cast<PngStream*>(png_get_progressive_ptr(png_ptr));
|
||||
if (!stream)
|
||||
@@ -162,7 +157,7 @@ void pngDecInfoCallback(png_structp png_ptr, png_infop info)
|
||||
stream->buffer->cursor += (stream->buffer->length - remaining);
|
||||
}
|
||||
|
||||
void pngDecEndCallback(png_structp png_ptr, png_infop info)
|
||||
void pngDecEndCallback(png_structp png_ptr, png_infop /*info*/)
|
||||
{
|
||||
PngStream* stream = static_cast<PngStream*>(png_get_progressive_ptr(png_ptr));
|
||||
if (!stream)
|
||||
@@ -175,17 +170,17 @@ void pngDecEndCallback(png_structp png_ptr, png_infop info)
|
||||
}
|
||||
|
||||
// Custom error handler for libpng
|
||||
[[noreturn]] void pngDecError(png_structp png_ptr, png_const_charp error_message)
|
||||
[[noreturn]] void pngDecError(png_structp /*png_ptr*/, png_const_charp error_message)
|
||||
{
|
||||
cellPngDec.error("%s", error_message);
|
||||
cellPngDec.error("pngDecError: %s", error_message);
|
||||
// we can't return here or libpng blows up
|
||||
fmt::throw_exception("Fatal Error in libpng: %s", error_message);
|
||||
}
|
||||
|
||||
// Custom warning handler for libpng
|
||||
void pngDecWarning(png_structp png_ptr, png_const_charp error_message)
|
||||
void pngDecWarning(png_structp /*png_ptr*/, png_const_charp error_message)
|
||||
{
|
||||
cellPngDec.warning("%s", error_message);
|
||||
cellPngDec.warning("pngDecWarning: %s", error_message);
|
||||
}
|
||||
|
||||
// Get the chunk information of the PNG file. IDAT is marked as existing, only after decoding or reading the header.
|
||||
@@ -337,7 +332,7 @@ be_t<u32> pngDecGetChunkInformation(PngStream* stream, bool IDAT = false)
|
||||
return chunk_information;
|
||||
}
|
||||
|
||||
error_code pngDecCreate(ppu_thread& ppu, PPHandle png_handle, PThreadInParam thread_in_param, PThreadOutParam thread_out_param, PExtThreadInParam extra_thread_in_param = vm::null, PExtThreadOutParam extra_thread_out_param = vm::null)
|
||||
error_code pngDecCreate(ppu_thread& ppu, PPHandle png_handle, PThreadInParam thread_in_param, PThreadOutParam thread_out_param, PExtThreadInParam /*extra_thread_in_param*/ = vm::null, PExtThreadOutParam extra_thread_out_param = vm::null)
|
||||
{
|
||||
// Check if partial image decoding is used
|
||||
if (extra_thread_out_param)
|
||||
@@ -908,103 +903,103 @@ error_code cellPngDecExtDecodeData(ppu_thread& ppu, PHandle handle, PStream stre
|
||||
|
||||
error_code cellPngDecGetUnknownChunks(PHandle handle, PStream stream, vm::pptr<CellPngUnknownChunk> unknownChunk, vm::ptr<u32> unknownChunkNumber)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetUnknownChunks()");
|
||||
cellPngDec.todo("cellPngDecGetUnknownChunks(handle=*0x%x, stream=*0x%x, unknownChunk=*0x%x, unknownChunkNumber=*0x%x)", handle, stream, unknownChunk, unknownChunkNumber);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetpCAL(PHandle handle, PStream stream, vm::ptr<CellPngPCAL> pcal)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetpCAL()");
|
||||
cellPngDec.todo("cellPngDecGetpCAL(handle=*0x%x, stream=*0x%x, pcal=*0x%x)", handle, stream, pcal);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetcHRM(PHandle handle, PStream stream, vm::ptr<CellPngCHRM> chrm)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetcHRM()");
|
||||
cellPngDec.todo("cellPngDecGetcHRM(handle=*0x%x, stream=*0x%x, chrm=*0x%x)", handle, stream, chrm);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetsCAL(PHandle handle, PStream stream, vm::ptr<CellPngSCAL> scal)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetsCAL()");
|
||||
cellPngDec.todo("cellPngDecGetsCAL(handle=*0x%x, stream=*0x%x, scal=*0x%x)", handle, stream, scal);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetpHYs(PHandle handle, PStream stream, vm::ptr<CellPngPHYS> phys)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetpHYs()");
|
||||
cellPngDec.todo("cellPngDecGetpHYs(handle=*0x%x, stream=*0x%x, phys=*0x%x)", handle, stream, phys);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetoFFs(PHandle handle, PStream stream, vm::ptr<CellPngOFFS> offs)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetoFFs()");
|
||||
cellPngDec.todo("cellPngDecGetoFFs(handle=*0x%x, stream=*0x%x, offs=*0x%x)", handle, stream, offs);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetsPLT(PHandle handle, PStream stream, vm::ptr<CellPngSPLT> splt)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetsPLT()");
|
||||
cellPngDec.todo("cellPngDecGetsPLT(handle=*0x%x, stream=*0x%x, splt=*0x%x)", handle, stream, splt);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetbKGD(PHandle handle, PStream stream, vm::ptr<CellPngBKGD> bkgd)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetbKGD()");
|
||||
cellPngDec.todo("cellPngDecGetbKGD(handle=*0x%x, stream=*0x%x, bkgd=*0x%x)", handle, stream, bkgd);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGettIME(PHandle handle, PStream stream, vm::ptr<CellPngTIME> time)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGettIME()");
|
||||
cellPngDec.todo("cellPngDecGettIME(handle=*0x%x, stream=*0x%x, time=*0x%x)", handle, stream, time);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGethIST(PHandle handle, PStream stream, vm::ptr<CellPngHIST> hist)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGethIST()");
|
||||
cellPngDec.todo("cellPngDecGethIST(handle=*0x%x, stream=*0x%x, hist=*0x%x)", handle, stream, hist);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGettRNS(PHandle handle, PStream stream, vm::ptr<CellPngTRNS> trns)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGettRNS()");
|
||||
cellPngDec.todo("cellPngDecGettRNS(handle=*0x%x, stream=*0x%x, trns=*0x%x)", handle, stream, trns);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetsBIT(PHandle handle, PStream stream, vm::ptr<CellPngSBIT> sbit)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetsBIT()");
|
||||
cellPngDec.todo("cellPngDecGetsBIT(handle=*0x%x, stream=*0x%x, sbit=*0x%x)", handle, stream, sbit);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetiCCP(PHandle handle, PStream stream, vm::ptr<CellPngICCP> iccp)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetiCCP()");
|
||||
cellPngDec.todo("cellPngDecGetiCCP(handle=*0x%x, stream=*0x%x, iccp=*0x%x)", handle, stream, iccp);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetsRGB(PHandle handle, PStream stream, vm::ptr<CellPngSRGB> srgb)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetsRGB()");
|
||||
cellPngDec.todo("cellPngDecGetsRGB(handle=*0x%x, stream=*0x%x, srgb=*0x%x)", handle, stream, srgb);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetgAMA(PHandle handle, PStream stream, vm::ptr<CellPngGAMA> gama)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetgAMA()");
|
||||
cellPngDec.todo("cellPngDecGetgAMA(handle=*0x%x, stream=*0x%x, gama=*0x%x)", handle, stream, gama);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetPLTE(PHandle handle, PStream stream, vm::ptr<CellPngPLTE> plte)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetPLTE()");
|
||||
cellPngDec.todo("cellPngDecGetPLTE(handle=*0x%x, stream=*0x%x, plte=*0x%x)", handle, stream, plte);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPngDecGetTextChunk(PHandle handle, PStream stream, vm::ptr<u32> textInfoNum, vm::pptr<CellPngTextInfo> textInfo)
|
||||
{
|
||||
cellPngDec.todo("cellPngDecGetTextChunk()");
|
||||
cellPngDec.todo("cellPngDecGetTextChunk(handle=*0x%x, stream=*0x%x, textInfoNum=*0x%x, textInfo=*0x%x)", handle, stream, textInfoNum, textInfo);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "cellPngEnc.h"
|
||||
#include "png.h"
|
||||
|
||||
LOG_CHANNEL(cellPngEnc);
|
||||
|
||||
|
||||
@@ -894,7 +894,7 @@ void rec_info::stop_video_provider(bool flush)
|
||||
}
|
||||
}
|
||||
|
||||
bool create_path(std::string& out, std::string dir_name, std::string file_name)
|
||||
bool create_path(std::string& out, std::string dir_name, const std::string& file_name)
|
||||
{
|
||||
out.clear();
|
||||
|
||||
@@ -903,7 +903,7 @@ bool create_path(std::string& out, std::string dir_name, std::string file_name)
|
||||
return false;
|
||||
}
|
||||
|
||||
out = dir_name;
|
||||
out = std::move(dir_name);
|
||||
|
||||
if (!out.empty() && out.back() != '/')
|
||||
{
|
||||
|
||||
@@ -78,7 +78,7 @@ error_code cellRtcGetCurrentTick(ppu_thread& ppu, vm::ptr<CellRtcTick> pTick)
|
||||
|
||||
error_code cellRtcGetCurrentClock(ppu_thread& ppu, vm::ptr<CellRtcDateTime> pClock, s32 iTimeZone)
|
||||
{
|
||||
cellRtc.notice("cellRtcGetCurrentClock(pClock=*0x%x, iTimeZone=%d)", pClock, iTimeZone);
|
||||
cellRtc.trace("cellRtcGetCurrentClock(pClock=*0x%x, iTimeZone=%d)", pClock, iTimeZone);
|
||||
|
||||
const vm::var<sys_page_attr_t> page_attr;
|
||||
|
||||
@@ -1505,7 +1505,7 @@ error_code cellRtcGetSystemTime(ppu_thread& ppu, vm::cptr<CellRtcDateTime> pDate
|
||||
|
||||
error_code cellRtcGetTime_t(ppu_thread& ppu, vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<s64> piTime)
|
||||
{
|
||||
cellRtc.notice("cellRtcGetTime_t(pDateTime=*0x%x, piTime=*0x%x)", pDateTime, piTime);
|
||||
cellRtc.trace("cellRtcGetTime_t(pDateTime=*0x%x, piTime=*0x%x)", pDateTime, piTime);
|
||||
|
||||
const vm::var<sys_page_attr_t> page_attr;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "cellSail.h"
|
||||
|
||||
LOG_CHANNEL(cellSailRec);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
#include "Emu/Cell/lv2/sys_process.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include "Emu/Cell/Modules/cellSysutil.h"
|
||||
#include "Emu/Cell/Modules/cellUserInfo.h"
|
||||
#include "Emu/RSX/Overlays/overlay_message.h"
|
||||
@@ -19,6 +20,7 @@
|
||||
#include "Loader/PSF.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
#include "Utilities/date_time.h"
|
||||
#include "Utilities/sema.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
@@ -242,7 +244,7 @@ static std::vector<SaveDataEntry> get_save_entries(const std::string& base_dir,
|
||||
continue;
|
||||
}
|
||||
|
||||
SaveDataEntry save_entry;
|
||||
SaveDataEntry save_entry {};
|
||||
save_entry.dirName = psf::get_string(psf, "SAVEDATA_DIRECTORY");
|
||||
save_entry.listParam = psf::get_string(psf, "SAVEDATA_LIST_PARAM");
|
||||
save_entry.title = psf::get_string(psf, "TITLE");
|
||||
@@ -305,7 +307,7 @@ static error_code select_and_delete(ppu_thread& ppu)
|
||||
// Display a blocking Save Data List asynchronously in the GUI thread.
|
||||
if (auto save_dialog = Emu.GetCallbacks().get_save_dialog())
|
||||
{
|
||||
selected = save_dialog->ShowSaveDataList(save_entries, focused, SAVEDATA_OP_LIST_DELETE, vm::null, g_fxo->get<savedata_manager>().enable_overlay);
|
||||
selected = save_dialog->ShowSaveDataList(base_dir, save_entries, focused, SAVEDATA_OP_LIST_DELETE, vm::null, g_fxo->get<savedata_manager>().enable_overlay);
|
||||
}
|
||||
|
||||
// Reschedule after a blocking dialog returns
|
||||
@@ -324,7 +326,7 @@ static error_code select_and_delete(ppu_thread& ppu)
|
||||
focused = save_entries.empty() ? -1 : selected;
|
||||
|
||||
// Get information from the selected entry
|
||||
SaveDataEntry entry = save_entries[selected];
|
||||
const SaveDataEntry& entry = ::at32(save_entries, selected);
|
||||
const std::string info = entry.title + "\n" + entry.subtitle + "\n" + entry.details;
|
||||
|
||||
// Reusable display message string
|
||||
@@ -758,7 +760,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
|
||||
result->userdata = userdata; // probably should be assigned only once (allows the callback to change it)
|
||||
|
||||
SaveDataEntry save_entry;
|
||||
SaveDataEntry save_entry {};
|
||||
|
||||
if (setList)
|
||||
{
|
||||
@@ -818,7 +820,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
break;
|
||||
}
|
||||
|
||||
SaveDataEntry save_entry2;
|
||||
SaveDataEntry save_entry2 {};
|
||||
save_entry2.dirName = psf::get_string(psf, "SAVEDATA_DIRECTORY");
|
||||
save_entry2.listParam = psf::get_string(psf, "SAVEDATA_LIST_PARAM");
|
||||
save_entry2.title = psf::get_string(psf, "TITLE");
|
||||
@@ -1181,7 +1183,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
// Display a blocking Save Data List asynchronously in the GUI thread.
|
||||
if (auto save_dialog = Emu.GetCallbacks().get_save_dialog())
|
||||
{
|
||||
selected = save_dialog->ShowSaveDataList(save_entries, focused, operation, listSet, g_fxo->get<savedata_manager>().enable_overlay);
|
||||
selected = save_dialog->ShowSaveDataList(base_dir, save_entries, focused, operation, listSet, g_fxo->get<savedata_manager>().enable_overlay);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1212,8 +1214,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
else
|
||||
{
|
||||
// Get information from the selected entry
|
||||
SaveDataEntry entry = save_entries[selected];
|
||||
message = get_confirmation_message(operation, entry);
|
||||
message = get_confirmation_message(operation, ::at32(save_entries, selected));
|
||||
}
|
||||
|
||||
// Yield before a blocking dialog is being spawned
|
||||
@@ -1343,14 +1344,14 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
else
|
||||
{
|
||||
// Get information from the selected entry
|
||||
SaveDataEntry entry = save_entries[selected];
|
||||
message = get_confirmation_message(operation, entry);
|
||||
message = get_confirmation_message(operation, ::at32(save_entries, selected));
|
||||
}
|
||||
|
||||
// Yield before a blocking dialog is being spawned
|
||||
lv2_obj::sleep(ppu);
|
||||
|
||||
// Get user confirmation by opening a blocking dialog
|
||||
// TODO: show fixedSet->newIcon
|
||||
s32 return_code = CELL_MSGDIALOG_BUTTON_NONE;
|
||||
error_code res = open_msg_dialog(true, CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO, vm::make_str(message), msg_dialog_source::_cellSaveData, vm::null, vm::null, vm::null, &return_code);
|
||||
|
||||
@@ -2499,12 +2500,7 @@ error_code cellSaveDataListDelete(ppu_thread& ppu, PSetList setList, PSetBuf set
|
||||
return savedata_op(ppu, SAVEDATA_OP_LIST_DELETE, 0, vm::null, 0, setList, setBuf, funcList, vm::null, vm::null, vm::null, container, 0x40, userdata, 0, funcDone);
|
||||
}
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
error_code cellSaveDataListImport(ppu_thread& ppu, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
error_code cellSaveDataListImport(ppu_thread& /*ppu*/, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.todo("cellSaveDataListImport(setList=*0x%x, maxSizeKB=%d, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", setList, maxSizeKB, funcDone, container, userdata);
|
||||
|
||||
@@ -2519,7 +2515,7 @@ error_code cellSaveDataListImport(ppu_thread& ppu, PSetList setList, u32 maxSize
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSaveDataListExport(ppu_thread& ppu, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
error_code cellSaveDataListExport(ppu_thread& /*ppu*/, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.todo("cellSaveDataListExport(setList=*0x%x, maxSizeKB=%d, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", setList, maxSizeKB, funcDone, container, userdata);
|
||||
|
||||
@@ -2534,7 +2530,7 @@ error_code cellSaveDataListExport(ppu_thread& ppu, PSetList setList, u32 maxSize
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSaveDataFixedImport(ppu_thread& ppu, vm::cptr<char> dirName, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
error_code cellSaveDataFixedImport(ppu_thread& /*ppu*/, vm::cptr<char> dirName, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.todo("cellSaveDataFixedImport(dirName=%s, maxSizeKB=%d, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", dirName, maxSizeKB, funcDone, container, userdata);
|
||||
|
||||
@@ -2549,7 +2545,7 @@ error_code cellSaveDataFixedImport(ppu_thread& ppu, vm::cptr<char> dirName, u32
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSaveDataFixedExport(ppu_thread& ppu, vm::cptr<char> dirName, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
error_code cellSaveDataFixedExport(ppu_thread& /*ppu*/, vm::cptr<char> dirName, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.todo("cellSaveDataFixedExport(dirName=%s, maxSizeKB=%d, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", dirName, maxSizeKB, funcDone, container, userdata);
|
||||
|
||||
@@ -2580,7 +2576,7 @@ error_code cellSaveDataUserListDelete(ppu_thread& ppu, u32 userId, PSetList setL
|
||||
return savedata_op(ppu, SAVEDATA_OP_LIST_DELETE, 0, vm::null, 0, setList, setBuf, funcList, vm::null, vm::null, vm::null, container, 0x40, userdata, userId, funcDone);
|
||||
}
|
||||
|
||||
error_code cellSaveDataUserListImport(ppu_thread& ppu, u32 userId, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
error_code cellSaveDataUserListImport(ppu_thread& /*ppu*/, u32 userId, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.todo("cellSaveDataUserListImport(userId=%d, setList=*0x%x, maxSizeKB=%d, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", userId, setList, maxSizeKB, funcDone, container, userdata);
|
||||
|
||||
@@ -2595,7 +2591,7 @@ error_code cellSaveDataUserListImport(ppu_thread& ppu, u32 userId, PSetList setL
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSaveDataUserListExport(ppu_thread& ppu, u32 userId, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
error_code cellSaveDataUserListExport(ppu_thread& /*ppu*/, u32 userId, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.todo("cellSaveDataUserListExport(userId=%d, setList=*0x%x, maxSizeKB=%d, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", userId, setList, maxSizeKB, funcDone, container, userdata);
|
||||
|
||||
@@ -2610,7 +2606,7 @@ error_code cellSaveDataUserListExport(ppu_thread& ppu, u32 userId, PSetList setL
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSaveDataUserFixedImport(ppu_thread& ppu, u32 userId, vm::cptr<char> dirName, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
error_code cellSaveDataUserFixedImport(ppu_thread& /*ppu*/, u32 userId, vm::cptr<char> dirName, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.todo("cellSaveDataUserFixedImport(userId=%d, dirName=%s, maxSizeKB=%d, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", userId, dirName, maxSizeKB, funcDone, container, userdata);
|
||||
|
||||
@@ -2625,7 +2621,7 @@ error_code cellSaveDataUserFixedImport(ppu_thread& ppu, u32 userId, vm::cptr<cha
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSaveDataUserFixedExport(ppu_thread& ppu, u32 userId, vm::cptr<char> dirName, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
error_code cellSaveDataUserFixedExport(ppu_thread& /*ppu*/, u32 userId, vm::cptr<char> dirName, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.todo("cellSaveDataUserFixedExport(userId=%d, dirName=%s, maxSizeKB=%d, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", userId, dirName, maxSizeKB, funcDone, container, userdata);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include "util/endian.hpp"
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -362,5 +361,5 @@ class SaveDialogBase
|
||||
public:
|
||||
virtual ~SaveDialogBase();
|
||||
|
||||
virtual s32 ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) = 0;
|
||||
virtual s32 ShowSaveDataList(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) = 0;
|
||||
};
|
||||
|
||||
@@ -160,11 +160,6 @@ void fmt_class_string<SpursWorkloadState>::format(std::string& out, u64 arg)
|
||||
|
||||
error_code sys_spu_image_close(ppu_thread&, vm::ptr<sys_spu_image> img);
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Function prototypes
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -738,7 +733,7 @@ void _spurs::handler_entry(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
|
||||
}
|
||||
}
|
||||
|
||||
s32 _spurs::create_handler(vm::ptr<CellSpurs> spurs, u32 ppuPriority)
|
||||
s32 _spurs::create_handler(vm::ptr<CellSpurs> /*spurs*/, u32 /*ppuPriority*/)
|
||||
{
|
||||
struct handler_thread : ppu_thread
|
||||
{
|
||||
@@ -909,7 +904,7 @@ void _spurs::event_helper_entry(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
|
||||
}
|
||||
}
|
||||
|
||||
s32 _spurs::create_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 ppuPriority)
|
||||
s32 _spurs::create_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 /*ppuPriority*/)
|
||||
{
|
||||
if (s32 rc = _spurs::create_lv2_eq(ppu, spurs, spurs.ptr(&CellSpurs::eventQueue), spurs.ptr(&CellSpurs::spuPort), 0x2A, sys_event_queue_attribute_t{SYS_SYNC_PRIORITY, SYS_PPU_QUEUE, {"_spuPrv\0"_u64}}))
|
||||
{
|
||||
@@ -981,7 +976,7 @@ void _spurs::init_event_port_mux(vm::ptr<CellSpurs::EventPortMux> eventPortMux,
|
||||
eventPortMux->x08 = unknown;
|
||||
}
|
||||
|
||||
s32 _spurs::add_default_syswkl(vm::ptr<CellSpurs> spurs, vm::cptr<u8> swlPriority, u32 swlMaxSpu, u32 swlIsPreem)
|
||||
s32 _spurs::add_default_syswkl(vm::ptr<CellSpurs> /*spurs*/, vm::cptr<u8> /*swlPriority*/, u32 /*swlMaxSpu*/, u32 /*swlIsPreem*/)
|
||||
{
|
||||
// TODO: Implement this
|
||||
return CELL_OK;
|
||||
@@ -1859,7 +1854,7 @@ s32 cellSpursSetPriority(vm::ptr<CellSpurs> spurs, u32 wid, u32 spuId, u32 prior
|
||||
/// Set preemption victim SPU
|
||||
s32 cellSpursSetPreemptionVictimHints(vm::ptr<CellSpurs> spurs, vm::cptr<b8> isPreemptible)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSpurs);
|
||||
cellSpurs.todo("cellSpursSetPreemptionVictimHints(spurs=*0x%x, isPreemptible=*0x%x)", spurs, isPreemptible);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -2230,7 +2225,7 @@ s32 cellSpursTraceStop(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/// Initialize attributes of a workload
|
||||
s32 _cellSpursWorkloadAttributeInitialize(ppu_thread& ppu, vm::ptr<CellSpursWorkloadAttribute> attr, u32 revision, u32 sdkVersion, vm::cptr<void> pm, u32 size, u64 data, vm::cptr<u8[8]> priority, u32 minCnt, u32 maxCnt)
|
||||
s32 _cellSpursWorkloadAttributeInitialize(ppu_thread& /*ppu*/, vm::ptr<CellSpursWorkloadAttribute> attr, u32 revision, u32 sdkVersion, vm::cptr<void> pm, u32 size, u64 data, vm::cptr<u8[8]> priority, u32 minCnt, u32 maxCnt)
|
||||
{
|
||||
cellSpurs.warning("_cellSpursWorkloadAttributeInitialize(attr=*0x%x, revision=%d, sdkVersion=0x%x, pm=*0x%x, size=0x%x, data=0x%llx, priority=*0x%x, minCnt=0x%x, maxCnt=0x%x)",
|
||||
attr, revision, sdkVersion, pm, size, data, priority, minCnt, maxCnt);
|
||||
@@ -2277,7 +2272,7 @@ s32 _cellSpursWorkloadAttributeInitialize(ppu_thread& ppu, vm::ptr<CellSpursWork
|
||||
}
|
||||
|
||||
/// Set the name of a workload
|
||||
s32 cellSpursWorkloadAttributeSetName(ppu_thread& ppu, vm::ptr<CellSpursWorkloadAttribute> attr, vm::cptr<char> nameClass, vm::cptr<char> nameInstance)
|
||||
s32 cellSpursWorkloadAttributeSetName(ppu_thread& /*ppu*/, vm::ptr<CellSpursWorkloadAttribute> attr, vm::cptr<char> nameClass, vm::cptr<char> nameInstance)
|
||||
{
|
||||
cellSpurs.warning("cellSpursWorkloadAttributeSetName(attr=*0x%x, nameClass=%s, nameInstance=%s)", attr, nameClass, nameInstance);
|
||||
|
||||
@@ -2771,7 +2766,7 @@ s32 cellSpursWakeUp(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
|
||||
}
|
||||
|
||||
/// Send a workload signal
|
||||
s32 cellSpursSendWorkloadSignal(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid)
|
||||
s32 cellSpursSendWorkloadSignal(ppu_thread& /*ppu*/, vm::ptr<CellSpurs> spurs, u32 wid)
|
||||
{
|
||||
cellSpurs.warning("cellSpursSendWorkloadSignal(spurs=*0x%x, wid=%d)", spurs, wid);
|
||||
|
||||
@@ -2833,7 +2828,7 @@ s32 cellSpursGetWorkloadFlag(vm::ptr<CellSpurs> spurs, vm::pptr<CellSpursWorkloa
|
||||
}
|
||||
|
||||
/// Set ready count
|
||||
s32 cellSpursReadyCountStore(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid, u32 value)
|
||||
s32 cellSpursReadyCountStore(ppu_thread& /*ppu*/, vm::ptr<CellSpurs> spurs, u32 wid, u32 value)
|
||||
{
|
||||
cellSpurs.trace("cellSpursReadyCountStore(spurs=*0x%x, wid=%d, value=0x%x)", spurs, wid, value);
|
||||
|
||||
@@ -2871,7 +2866,7 @@ s32 cellSpursReadyCountStore(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid,
|
||||
}
|
||||
|
||||
/// Swap ready count
|
||||
s32 cellSpursReadyCountSwap(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid, vm::ptr<u32> old, u32 swap)
|
||||
s32 cellSpursReadyCountSwap(ppu_thread& /*ppu*/, vm::ptr<CellSpurs> spurs, u32 wid, vm::ptr<u32> old, u32 swap)
|
||||
{
|
||||
cellSpurs.trace("cellSpursReadyCountSwap(spurs=*0x%x, wid=%d, old=*0x%x, swap=0x%x)", spurs, wid, old, swap);
|
||||
|
||||
@@ -2909,7 +2904,7 @@ s32 cellSpursReadyCountSwap(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid,
|
||||
}
|
||||
|
||||
/// Compare and swap ready count
|
||||
s32 cellSpursReadyCountCompareAndSwap(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid, vm::ptr<u32> old, u32 compare, u32 swap)
|
||||
s32 cellSpursReadyCountCompareAndSwap(ppu_thread& /*ppu*/, vm::ptr<CellSpurs> spurs, u32 wid, vm::ptr<u32> old, u32 compare, u32 swap)
|
||||
{
|
||||
cellSpurs.trace("cellSpursReadyCountCompareAndSwap(spurs=*0x%x, wid=%d, old=*0x%x, compare=0x%x, swap=0x%x)", spurs, wid, old, compare, swap);
|
||||
|
||||
@@ -2950,7 +2945,7 @@ s32 cellSpursReadyCountCompareAndSwap(ppu_thread& ppu, vm::ptr<CellSpurs> spurs,
|
||||
}
|
||||
|
||||
/// Increase or decrease ready count
|
||||
s32 cellSpursReadyCountAdd(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid, vm::ptr<u32> old, s32 value)
|
||||
s32 cellSpursReadyCountAdd(ppu_thread& /*ppu*/, vm::ptr<CellSpurs> spurs, u32 wid, vm::ptr<u32> old, s32 value)
|
||||
{
|
||||
cellSpurs.trace("cellSpursReadyCountAdd(spurs=*0x%x, wid=%d, old=*0x%x, value=0x%x)", spurs, wid, old, value);
|
||||
|
||||
@@ -3030,7 +3025,7 @@ s32 cellSpursGetWorkloadData(vm::ptr<CellSpurs> spurs, vm::ptr<u64> data, u32 wi
|
||||
}
|
||||
|
||||
/// Get workload information
|
||||
s32 cellSpursGetWorkloadInfo(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid, vm::ptr<CellSpursWorkloadInfo> info)
|
||||
s32 cellSpursGetWorkloadInfo(ppu_thread& /*ppu*/, vm::ptr<CellSpurs> spurs, u32 wid, vm::ptr<CellSpursWorkloadInfo> info)
|
||||
{
|
||||
cellSpurs.todo("cellSpursGetWorkloadInfo(spurs=*0x%x, wid=0x%x, info=*0x%x)", spurs, wid, info);
|
||||
return CELL_OK;
|
||||
@@ -3135,7 +3130,7 @@ s32 _cellSpursWorkloadFlagReceiver(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u3
|
||||
}
|
||||
|
||||
/// Set/unset the recipient of the workload flag
|
||||
s32 _cellSpursWorkloadFlagReceiver2(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid, u32 is_set, u32 print_debug_output)
|
||||
s32 _cellSpursWorkloadFlagReceiver2(ppu_thread& /*ppu*/, vm::ptr<CellSpurs> spurs, u32 wid, u32 is_set, u32 print_debug_output)
|
||||
{
|
||||
cellSpurs.warning("_cellSpursWorkloadFlagReceiver2(spurs=*0x%x, wid=%d, is_set=%d, print_debug_output=%d)", spurs, wid, is_set, print_debug_output);
|
||||
|
||||
@@ -3833,19 +3828,19 @@ s32 _cellSpursLFQueueInitialize(vm::ptr<void> pTasksetOrSpurs, vm::ptr<CellSpurs
|
||||
|
||||
s32 _cellSpursLFQueuePushBody()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSpurs);
|
||||
cellSpurs.todo("_cellSpursLFQueuePushBody()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSpursLFQueueAttachLv2EventQueue(vm::ptr<CellSyncLFQueue> queue)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSpurs);
|
||||
cellSpurs.todo("cellSpursLFQueueAttachLv2EventQueue(queue=*0x%x)", queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSpursLFQueueDetachLv2EventQueue(vm::ptr<CellSyncLFQueue> queue)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSpurs);
|
||||
cellSpurs.todo("cellSpursLFQueueDetachLv2EventQueue(queue=*0x%x)", queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -4571,7 +4566,7 @@ s32 cellSpursTasksetUnsetExceptionEventHandler(vm::ptr<CellSpursTaskset> taskset
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSpursLookUpTasksetAddress(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::pptr<CellSpursTaskset> taskset, u32 id)
|
||||
s32 cellSpursLookUpTasksetAddress(ppu_thread& /*ppu*/, vm::ptr<CellSpurs> spurs, vm::pptr<CellSpursTaskset> taskset, u32 id)
|
||||
{
|
||||
cellSpurs.warning("cellSpursLookUpTasksetAddress(spurs=*0x%x, taskset=**0x%x, id=0x%x)", spurs, taskset, id);
|
||||
|
||||
@@ -4653,9 +4648,9 @@ s32 _cellSpursTasksetAttributeInitialize(vm::ptr<CellSpursTasksetAttribute> attr
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 _spurs::check_job_chain_attribute(u32 sdkVer, vm::cptr<u64> jcEntry, u16 sizeJobDescr, u16 maxGrabbedJob
|
||||
, u64 priorities, u32 maxContention, u8 autoSpuCount, u32 tag1, u32 tag2
|
||||
, u8 isFixedMemAlloc, u32 maxSizeJob, u32 initSpuCount)
|
||||
s32 _spurs::check_job_chain_attribute(u32 sdkVer, vm::cptr<u64> jcEntry, u16 sizeJobDescr, u16 maxGrabbedJob,
|
||||
u64 priorities, u32 /*maxContention*/, u8 autoSpuCount, u32 tag1, u32 tag2,
|
||||
u8 /*isFixedMemAlloc*/, u32 maxSizeJob, u32 initSpuCount)
|
||||
{
|
||||
if (!jcEntry)
|
||||
return CELL_SPURS_JOB_ERROR_NULL_POINTER;
|
||||
@@ -4686,9 +4681,9 @@ s32 _spurs::check_job_chain_attribute(u32 sdkVer, vm::cptr<u64> jcEntry, u16 siz
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 _spurs::create_job_chain(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursJobChain> jobChain, vm::cptr<u64> jobChainEntry, u16 sizeJob
|
||||
, u16 maxGrabbedJob, vm::cptr<u8[8]> prio, u32 maxContention, b8 autoReadyCount
|
||||
, u32 tag1, u32 tag2, u32 HaltOnError, vm::cptr<char> name, u32 param_13, u32 param_14)
|
||||
s32 _spurs::create_job_chain(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursJobChain> jobChain, vm::cptr<u64> jobChainEntry, u16 /*sizeJob*/,
|
||||
u16 maxGrabbedJob, vm::cptr<u8[8]> prio, u32 maxContention, b8 /*autoReadyCount*/,
|
||||
u32 tag1, u32 tag2, u32 /*HaltOnError*/, vm::cptr<char> name, u32 /*param_13*/, u32 /*param_14*/)
|
||||
{
|
||||
const s32 sdkVer = _spurs::get_sdk_version();
|
||||
jobChain->spurs = spurs;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_spu.h"
|
||||
#include "cellSpursJq.h"
|
||||
|
||||
LOG_CHANNEL(cellSpursJq);
|
||||
|
||||
error_code cellSpursJobQueueAttributeInitialize()
|
||||
|
||||
@@ -15,7 +15,6 @@ LOG_CHANNEL(cellSpurs);
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -89,7 +88,7 @@ void spursJobchainPopUrgentCommand(spu_thread& spu);
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Output trace information
|
||||
void cellSpursModulePutTrace(CellSpursTracePacket* packet, u32 dmaTagId)
|
||||
void cellSpursModulePutTrace(CellSpursTracePacket* /*packet*/, u32 /*dmaTagId*/)
|
||||
{
|
||||
// TODO: Implement this
|
||||
}
|
||||
@@ -871,7 +870,7 @@ void spursSysServiceIdleHandler(spu_thread& spu, SpursKernelContext* ctxt)
|
||||
}
|
||||
|
||||
// Main function for the system service
|
||||
void spursSysServiceMain(spu_thread& spu, u32 pollStatus)
|
||||
void spursSysServiceMain(spu_thread& spu, u32 /*pollStatus*/)
|
||||
{
|
||||
const auto ctxt = spu._ptr<SpursKernelContext>(0x100);
|
||||
|
||||
@@ -1166,7 +1165,7 @@ void spursSysServiceUpdateShutdownCompletionEvents(spu_thread& spu, SpursKernelC
|
||||
}
|
||||
|
||||
// Update the trace count for this SPU
|
||||
void spursSysServiceTraceSaveCount(spu_thread& spu, SpursKernelContext* ctxt)
|
||||
void spursSysServiceTraceSaveCount(spu_thread& /*spu*/, SpursKernelContext* ctxt)
|
||||
{
|
||||
if (ctxt->traceBuffer)
|
||||
{
|
||||
@@ -2056,7 +2055,7 @@ s32 spursTasksetLoadElf(spu_thread& spu, u32* entryPoint, u32* lowestLoadAddr, u
|
||||
//----------------------------------------------------------------------------
|
||||
// SPURS taskset policy module functions
|
||||
//----------------------------------------------------------------------------
|
||||
bool spursJobChainEntry(spu_thread& spu)
|
||||
bool spursJobChainEntry(spu_thread& /*spu*/)
|
||||
{
|
||||
//const auto ctxt = spu._ptr<SpursJobChainContext>(0x4a00);
|
||||
//auto kernelCtxt = spu._ptr<SpursKernelContext>(spu.gpr[3]._u32[3]);
|
||||
|
||||
@@ -580,8 +580,6 @@ error_code cellSysutilCheckCallback(ppu_thread& ppu)
|
||||
|
||||
auto& cbm = g_fxo->get<sysutil_cb_manager>();
|
||||
|
||||
bool read = false;
|
||||
|
||||
for (auto&& func : cbm.registered.pop_all())
|
||||
{
|
||||
if (func.call_active && !*func.call_active)
|
||||
@@ -589,7 +587,11 @@ error_code cellSysutilCheckCallback(ppu_thread& ppu)
|
||||
continue;
|
||||
}
|
||||
|
||||
read = true;
|
||||
// Increase read counter before we call the callback.
|
||||
// We use this counter to check if the game reacts to a command during game termination and calls sys_process_exit.
|
||||
// We would not realize that the game reacted in time and terminate it prematurely if we increased
|
||||
// the counter after we called the callback and the callback did some time-consuming work.
|
||||
cbm.read_counter++;
|
||||
|
||||
if (s32 res = func.func(ppu))
|
||||
{
|
||||
@@ -603,11 +605,6 @@ error_code cellSysutilCheckCallback(ppu_thread& ppu)
|
||||
}
|
||||
}
|
||||
|
||||
if (read)
|
||||
{
|
||||
cbm.read_counter++;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1619,10 +1619,25 @@ error_code cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frameRateCode)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellVdecOpenExt()
|
||||
error_code cellVdecOpenExt(ppu_thread& ppu, vm::cptr<CellVdecType> type, vm::cptr<CellVdecResourceExt> res, vm::cptr<CellVdecCb> cb, vm::ptr<u32> handle)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellVdec);
|
||||
return CELL_OK;
|
||||
cellVdec.warning("cellVdecOpenExt(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
vm::var<CellVdecResource> tmp = vm::make_var<CellVdecResource>({});
|
||||
tmp->memAddr = res->memAddr;
|
||||
tmp->memSize = res->memSize;
|
||||
tmp->ppuThreadPriority = res->ppuThreadPriority;
|
||||
tmp->ppuThreadStackSize = res->ppuThreadStackSize;
|
||||
tmp->spuThreadPriority = 0;
|
||||
tmp->numOfSpus = res->numOfSpus;
|
||||
|
||||
const vm::ptr<CellVdecResource> ptr = vm::cast(tmp.addr());
|
||||
return vdecOpen(ppu, type, ptr, cb, handle);
|
||||
}
|
||||
|
||||
error_code cellVdecStartSeqExt()
|
||||
|
||||
@@ -133,6 +133,16 @@ struct CellVdecResourceEx
|
||||
be_t<u32> spursResource_addr;
|
||||
};
|
||||
|
||||
struct CellVdecResourceExt // speculative
|
||||
{
|
||||
be_t<u32> memAddr;
|
||||
be_t<u32> memSize;
|
||||
be_t<s32> ppuThreadPriority;
|
||||
be_t<u32> ppuThreadStackSize;
|
||||
u8 unk[12];
|
||||
be_t<u32> numOfSpus;
|
||||
};
|
||||
|
||||
// Access Unit Information
|
||||
struct CellVdecAuInfo
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/VFS.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
LOG_CHANNEL(cellVideoExport);
|
||||
|
||||
@@ -423,7 +423,7 @@ error_code cellVideoOutGetDeviceInfo(u32 videoOut, u32 deviceIndex, vm::ptr<Cell
|
||||
|
||||
error_code cellVideoOutGetNumberOfDevice(u32 videoOut)
|
||||
{
|
||||
cellSysutil.warning("cellVideoOutGetNumberOfDevice(videoOut=%d)", videoOut);
|
||||
cellSysutil.trace("cellVideoOutGetNumberOfDevice(videoOut=%d)", videoOut);
|
||||
|
||||
switch (videoOut)
|
||||
{
|
||||
@@ -478,11 +478,6 @@ error_code cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId,
|
||||
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
|
||||
}
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
error_code cellVideoOutGetConvertCursorColorInfo(vm::ptr<u8> rgbOutputRange)
|
||||
{
|
||||
cellSysutil.todo("cellVideoOutGetConvertCursorColorInfo(rgbOutputRange=*0x%x)", rgbOutputRange);
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <deque>
|
||||
|
||||
// libvoice = 0x80310801 - 0x803108ff
|
||||
// libvoice version 100
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "cellWebBrowser.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "cellSysutil.h"
|
||||
|
||||
LOG_CHANNEL(cellSysutil);
|
||||
|
||||
struct browser_info
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "cellSysutil.h"
|
||||
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
|
||||
//events
|
||||
|
||||
@@ -34,308 +34,303 @@ void fmt_class_string<CellSnd3Error>::format(std::string& out, u64 arg)
|
||||
});
|
||||
}
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
error_code cellSnd3Init(u32 maxVoice, u32 samples, vm::ptr<CellSnd3RequestQueueCtx> queue)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3Init(maxVoice=%d, samples=%d, queue=*0x%x)", maxVoice, samples, queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3Exit()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3Exit()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
u16 cellSnd3Note2Pitch(u16 center_note, u16 center_fine, u16 note, s16 fine)
|
||||
{
|
||||
libsnd3.todo("cellSnd3Note2Pitch()");
|
||||
libsnd3.todo("cellSnd3Note2Pitch(center_note=%d, center_fine=%d, note=%d, fine=%d)", center_note, center_fine, note, fine);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 cellSnd3Pitch2Note(u16 center_note, u16 center_fine, u16 pitch)
|
||||
{
|
||||
libsnd3.todo("cellSnd3Pitch2Note()");
|
||||
libsnd3.todo("cellSnd3Pitch2Note(center_note=%d, center_fine=%d, pitch=%d)", center_note, center_fine, pitch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
error_code cellSnd3SetOutputMode(u32 mode)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SetOutputMode(mode=%d)", mode);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3Synthesis(vm::ptr<f32> pOutL, vm::ptr<f32> pOutR)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3Synthesis(pOutL=*0x%x, pOutR=*0x%x)", pOutL, pOutR);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SynthesisEx(vm::ptr<f32> pOutL, vm::ptr<f32> pOutR, vm::ptr<f32> pOutRL, vm::ptr<f32> pOutRR)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SynthesisEx(pOutL=*0x%x, pOutR=*0x%x, pOutRL=*0x%x, pOutRR=*0x%x)", pOutL, pOutR, pOutRL, pOutRR);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3BindSoundData(vm::ptr<CellSnd3DataCtx> snd3Ctx, vm::ptr<void> hd3, u32 synthMemOffset)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3BindSoundData(snd3Ctx=*0x%x, hd3=*0x%x, synthMemOffset=0x%x)", snd3Ctx, hd3, synthMemOffset);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3UnbindSoundData(u32 hd3ID)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3UnbindSoundData(hd3ID=0x%x)", hd3ID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3NoteOnByTone(u32 hd3ID, u32 toneIndex, u32 note, u32 keyOnID, vm::ptr<CellSnd3KeyOnParam> keyOnParam)
|
||||
{
|
||||
libsnd3.todo("cellSnd3NoteOnByTone()");
|
||||
libsnd3.todo("cellSnd3NoteOnByTone(hd3ID=0x%x, toneIndex=%d, note=%d, keyOnID=0x%x, keyOnParam=*0x%x)", hd3ID, toneIndex, note, keyOnID, keyOnParam);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3KeyOnByTone(u32 hd3ID, u32 toneIndex, u32 pitch, u32 keyOnID, vm::ptr<CellSnd3KeyOnParam> keyOnParam)
|
||||
{
|
||||
libsnd3.todo("cellSnd3KeyOnByTone()");
|
||||
libsnd3.todo("cellSnd3KeyOnByTone(hd3ID=0x%x, toneIndex=%d, pitch=%d, keyOnID=0x%x, keyOnParam=*0x%x)", hd3ID, toneIndex, pitch, keyOnID, keyOnParam);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceNoteOnByTone(u32 hd3ID, u32 voiceNum, u32 toneIndex, u32 note, u32 keyOnID, vm::ptr<CellSnd3KeyOnParam> keyOnParam)
|
||||
{
|
||||
libsnd3.todo("cellSnd3VoiceNoteOnByTone()");
|
||||
libsnd3.todo("cellSnd3VoiceNoteOnByTone(hd3ID=0x%x, voiceNum=%d, toneIndex=%d, note=%d, keyOnID=0x%x, keyOnParam=*0x%x)", hd3ID, voiceNum, toneIndex, note, keyOnID, keyOnParam);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceKeyOnByTone(u32 hd3ID, u32 voiceNum, u32 toneIndex, u32 pitch, u32 keyOnID, vm::ptr<CellSnd3KeyOnParam> keyOnParam)
|
||||
{
|
||||
libsnd3.todo("cellSnd3VoiceKeyOnByTone()");
|
||||
libsnd3.todo("cellSnd3VoiceKeyOnByTone(hd3ID=0x%x, voiceNum=%d, toneIndex=%d, pitch=%d, keyOnID=0x%x, keyOnParam=*0x%x)", hd3ID, voiceNum, toneIndex, pitch, keyOnID, keyOnParam);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceSetReserveMode(u32 voiceNum, u32 reserveMode)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceSetReserveMode(voiceNum=%d, reserveMode=%d)", voiceNum, reserveMode);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceSetSustainHold(u32 voiceNum, u32 sustainHold)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceSetSustainHold(voiceNum=%d, sustainHold=%d)", voiceNum, sustainHold);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceKeyOff(u32 voiceNum)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceKeyOff(voiceNum=%d)", voiceNum);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceSetPitch(u32 voiceNum, s32 addPitch)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceSetPitch(voiceNum=%d, addPitch=%d)", voiceNum, addPitch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceSetVelocity(u32 voiceNum, u32 velocity)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceSetVelocity(voiceNum=%d, velocity=%d)", voiceNum, velocity);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceSetPanpot(u32 voiceNum, u32 panpot)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceSetPanpot(voiceNum=%d, panpot=%d)", voiceNum, panpot);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceSetPanpotEx(u32 voiceNum, u32 panpotEx)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceSetPanpotEx(voiceNum=%d, panpotEx=%d)", voiceNum, panpotEx);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceSetPitchBend(u32 voiceNum, u32 bendValue)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceSetPitchBend(voiceNum=%d, bendValue=%d)", voiceNum, bendValue);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceAllKeyOff()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceAllKeyOff()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceGetEnvelope(u32 voiceNum)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3VoiceGetEnvelope(voiceNum=%d)", voiceNum);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3VoiceGetStatus(u32 voiceNum)
|
||||
{
|
||||
libsnd3.todo("cellSnd3VoiceGetStatus()");
|
||||
libsnd3.todo("cellSnd3VoiceGetStatus(voiceNum=%d)", voiceNum);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
u32 cellSnd3KeyOffByID(u32 keyOnID)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3KeyOffByID(keyOnID=%d)", keyOnID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3GetVoice(u32 midiChannel, u32 keyOnID, vm::ptr<CellSnd3VoiceBitCtx> voiceBit)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3GetVoice(midiChannel=%d, keyOnID=%d, voiceBit=*0x%x)", midiChannel, keyOnID, voiceBit);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3GetVoiceByID(u32 ID, vm::ptr<CellSnd3VoiceBitCtx> voiceBit)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3GetVoiceByID(ID=%d, voiceBit=*0x%x)", ID, voiceBit);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3NoteOn(u32 hd3ID, u32 midiChannel, u32 midiProgram, u32 midiNote, u32 sustain, vm::ptr<CellSnd3KeyOnParam> keyOnParam, u32 keyOnID)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3NoteOn(hd3ID=%d, midiChannel=%d, midiProgram=%d, midiNote=%d, sustain=%d, keyOnParam=*0x%x, keyOnID=%d)", hd3ID, midiChannel, midiProgram, midiNote, sustain, keyOnParam, keyOnID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3NoteOff(u32 midiChannel, u32 midiNote, u32 keyOnID)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3NoteOff(midiChannel=%d, midiNote=%d, keyOnID=%d)", midiChannel, midiNote, keyOnID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SetSustainHold(u32 midiChannel, u32 sustainHold, u32 keyOnID)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SetSustainHold(midiChannel=%d, sustainHold=%d, keyOnID=%d)", midiChannel, sustainHold, keyOnID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SetEffectType(u16 effectType, s16 returnVol, u16 delay, u16 feedback)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SetEffectType(effectType=%d, returnVol=%d, delay=%d, feedback=%d)", effectType, returnVol, delay, feedback);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFBind(vm::ptr<CellSnd3SmfCtx> smfCtx, vm::ptr<void> smf, u32 hd3ID)
|
||||
{
|
||||
libsnd3.todo("cellSnd3SMFBind()");
|
||||
libsnd3.todo("cellSnd3SMFBind(smfCtx=*0x%x, delay=*0x%x, hd3ID=%d)", smfCtx, smf, hd3ID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFUnbind(u32 smfID)
|
||||
{
|
||||
libsnd3.todo("cellSnd3SMFUnbind()");
|
||||
libsnd3.todo("cellSnd3SMFUnbind(smfID=%d)", smfID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFPlay(u32 smfID, u32 playVelocity, u32 playPan, u32 playCount)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFPlay(smfID=%d, playVelocity=%d, playPan=%d, playCount=%d)", smfID, playVelocity, playPan, playCount);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFPlayEx(u32 smfID, u32 playVelocity, u32 playPan, u32 playPanEx, u32 playCount)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFPlayEx(smfID=%d, playVelocity=%d, playPan=%d, playPanEx=%d, playCount=%d)", smfID, playVelocity, playPan, playPanEx, playCount);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFPause(u32 smfID)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFPause(smfID=%d)", smfID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFResume(u32 smfID)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFResume(smfID=%d)", smfID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFStop(u32 smfID)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFStop(smfID=%d)", smfID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFAddTempo(u32 smfID, s32 addTempo)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFAddTempo(smfID=%d, addTempo=%d)", smfID, addTempo);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFGetTempo(u32 smfID)
|
||||
{
|
||||
libsnd3.todo("cellSnd3SMFGetTempo()");
|
||||
libsnd3.todo("cellSnd3SMFGetTempo(smfID=%d)", smfID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFSetPlayVelocity(u32 smfID, u32 playVelocity)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFSetPlayVelocity(smfID=%d, playVelocity=%d)", smfID, playVelocity);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFGetPlayVelocity(u32 smfID)
|
||||
{
|
||||
libsnd3.todo("cellSnd3SMFGetPlayVelocity()");
|
||||
libsnd3.todo("cellSnd3SMFGetPlayVelocity(smfID=%d)", smfID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFSetPlayPanpot(u32 smfID, u32 playPanpot)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFSetPlayPanpot(smfID=%d, playPanpot=%d)", smfID, playPanpot);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFSetPlayPanpotEx(u32 smfID, u32 playPanpotEx)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFSetPlayPanpotEx(smfID=%d, playPanpotEx=%d)", smfID, playPanpotEx);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFGetPlayPanpot(u32 smfID)
|
||||
{
|
||||
libsnd3.todo("cellSnd3SMFGetPlayPanpot()");
|
||||
libsnd3.todo("cellSnd3SMFGetPlayPanpot(smfID=%d)", smfID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFGetPlayPanpotEx(u32 smfID)
|
||||
{
|
||||
libsnd3.todo("cellSnd3SMFGetPlayPanpotEx()");
|
||||
libsnd3.todo("cellSnd3SMFGetPlayPanpotEx(smfID=%d)", smfID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFGetPlayStatus(u32 smfID)
|
||||
{
|
||||
libsnd3.todo("cellSnd3SMFGetPlayStatus()");
|
||||
libsnd3.todo("cellSnd3SMFGetPlayStatus(smfID=%d)", smfID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFSetPlayChannel(u32 smfID, u32 playChannelBit)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFSetPlayChannel(smfID=%d, playChannelBit=%d)", smfID, playChannelBit);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFGetPlayChannel(u32 smfID, vm::ptr<u32> playChannelBit)
|
||||
{
|
||||
libsnd3.todo("cellSnd3SMFGetPlayChannel()");
|
||||
libsnd3.todo("cellSnd3SMFGetPlayChannel(smfID=%d, playChannelBit=*0x%x)", smfID, playChannelBit);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSnd3SMFGetKeyOnID(u32 smfID, u32 midiChannel, vm::ptr<u32> keyOnID)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libsnd3);
|
||||
libsnd3.todo("cellSnd3SMFAddTempo(smfID=%d, midiChannel=%d, keyOnID=*0x%x)", smfID, midiChannel, keyOnID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/system_utils.hpp"
|
||||
#include "Emu/VFS.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/Cell/Modules/cellUserInfo.h"
|
||||
#include "Emu/Io/interception.h"
|
||||
#include "Emu/NP/signaling_handler.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include "sysPrxForUser.h"
|
||||
@@ -16,6 +14,7 @@
|
||||
#include "sceNp.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include "Emu/Cell/lv2/sys_time.h"
|
||||
#include "Emu/Cell/lv2/sys_fs.h"
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
@@ -23,6 +22,7 @@
|
||||
#include "Emu/NP/np_contexts.h"
|
||||
#include "Emu/NP/np_helpers.h"
|
||||
#include "Emu/NP/np_structs_extra.h"
|
||||
#include "Emu/NP/signaling_handler.h"
|
||||
#include "Emu/system_config.h"
|
||||
|
||||
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||
|
||||
@@ -592,7 +592,6 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
|
||||
|
||||
// open trophy pack file
|
||||
std::string trp_path = vfs::get(Emu.GetDir() + "TROPDIR/" + ctxt->trp_name + "/TROPHY.TRP");
|
||||
|
||||
fs::file stream;
|
||||
if(Emu.GetIsoFs()&&trp_path[0]==':')
|
||||
stream=fs::file(*Emu.GetIsoFs(), trp_path);
|
||||
@@ -721,9 +720,9 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
|
||||
|
||||
lock2.unlock();
|
||||
|
||||
struct register_context_thread : register_context_thread_name
|
||||
lv2_obj::sleep(ppu);
|
||||
{
|
||||
void operator()(s32 progress_cb_count, u32 context, vm::ptr<SceNpTrophyStatusCallback> statusCb, vm::ptr<void> arg) const
|
||||
const s32 progress_cb_count = ::narrow<s32>(tropusr->GetTrophiesCount()) - 1;
|
||||
{
|
||||
// This emulates vsh sending the events and ensures that not 2 events are processed at once
|
||||
const std::pair<SceNpTrophyStatus, s32> statuses[] =
|
||||
@@ -737,6 +736,13 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
|
||||
// Create a counter which is destroyed after the function ends
|
||||
const auto queued = std::make_shared<atomic_t<u32>>(0);
|
||||
|
||||
u32 total_events = 0;
|
||||
|
||||
for (auto status : statuses)
|
||||
{
|
||||
total_events += status.second + 1;
|
||||
}
|
||||
|
||||
for (auto status : statuses)
|
||||
{
|
||||
for (s32 completed = 0; completed <= status.second; completed++)
|
||||
@@ -759,8 +765,9 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
|
||||
|
||||
u64 current = get_system_time();
|
||||
|
||||
const u64 until_max = current + 300'000;
|
||||
const u64 until_min = current + 100'000;
|
||||
// Minimum register trophy time 2 seconds globally.
|
||||
const u64 until_min = current + (2'000'000 / total_events);
|
||||
const u64 until_max = until_min + 50'000;
|
||||
|
||||
// If too much time passes just send the rest of the events anyway
|
||||
for (u32 old_value = *queued; current < (old_value ? until_max : until_min);
|
||||
@@ -777,19 +784,13 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
|
||||
|
||||
if (thread_ctrl::state() == thread_state::aborting)
|
||||
{
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
lv2_obj::sleep(ppu);
|
||||
|
||||
g_fxo->get<named_thread<register_context_thread>>()(::narrow<s32>(tropusr->GetTrophiesCount()) - 1, context, statusCb, arg);
|
||||
|
||||
thread_ctrl::wait_for(200'000);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "sysPrxForUser.h"
|
||||
|
||||
LOG_CHANNEL(sysPrxForUser);
|
||||
|
||||
struct HeapInfo
|
||||
|
||||
@@ -65,38 +65,33 @@ void fmt_class_string<CellLv2DbgError>::format(std::string& out, u64 arg)
|
||||
});
|
||||
}
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
error_code sys_dbg_read_ppu_thread_context(u64 id, vm::ptr<sys_dbg_ppu_thread_context_t> ppu_context)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_read_ppu_thread_context()");
|
||||
sys_lv2dbg.todo("sys_dbg_read_ppu_thread_context(id=0x%x, ppu_context=*0x%x)", id, ppu_context);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_read_spu_thread_context(u32 id, vm::ptr<sys_dbg_spu_thread_context_t> spu_context)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_read_spu_thread_context()");
|
||||
sys_lv2dbg.todo("sys_dbg_read_spu_thread_context(id=0x%x, spu_context=*0x%x)", id, spu_context);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_read_spu_thread_context2(u32 id, vm::ptr<sys_dbg_spu_thread_context2_t> spu_context)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_read_spu_thread_context2()");
|
||||
sys_lv2dbg.todo("sys_dbg_read_spu_thread_context2(id=0x%x, spu_context=*0x%x)", id, spu_context);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_set_stacksize_ppu_exception_handler(u32 stacksize)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_set_stacksize_ppu_exception_handler()");
|
||||
sys_lv2dbg.todo("sys_dbg_set_stacksize_ppu_exception_handler(stacksize=0x%x)", stacksize);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_initialize_ppu_exception_handler(s32 prio)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_initialize_ppu_exception_handler()");
|
||||
sys_lv2dbg.todo("sys_dbg_initialize_ppu_exception_handler(prio=0x%x)", prio);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -108,7 +103,7 @@ error_code sys_dbg_finalize_ppu_exception_handler()
|
||||
|
||||
error_code sys_dbg_register_ppu_exception_handler(vm::ptr<dbg_exception_handler_t> callback, u64 ctrl_flags)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_register_ppu_exception_handler()");
|
||||
sys_lv2dbg.todo("sys_dbg_register_ppu_exception_handler(callback=*0x%x, ctrl_flags=0x%x)", callback, ctrl_flags);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -120,170 +115,163 @@ error_code sys_dbg_unregister_ppu_exception_handler()
|
||||
|
||||
error_code sys_dbg_signal_to_ppu_exception_handler(u64 flags)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_signal_to_ppu_exception_handler()");
|
||||
sys_lv2dbg.todo("sys_dbg_signal_to_ppu_exception_handler(flags=0x%x)", flags);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_mutex_information(u32 id, vm::ptr<sys_dbg_mutex_information_t> info)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_mutex_information()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_mutex_information(id=0x%x, info=*0x%x)", id, info);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_cond_information(u32 id, vm::ptr<sys_dbg_cond_information_t> info)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_cond_information()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_cond_information(id=0x%x, info=*0x%x)", id, info);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_rwlock_information(u32 id, vm::ptr<sys_dbg_rwlock_information_t> info)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_rwlock_information()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_rwlock_information(id=0x%x, info=*0x%x)", id, info);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_event_queue_information(u32 id, vm::ptr<sys_dbg_event_queue_information_t> info)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_event_queue_information()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_event_queue_information(id=0x%x, info=*0x%x)", id, info);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_semaphore_information(u32 id, vm::ptr<sys_dbg_semaphore_information_t> info)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_semaphore_information()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_semaphore_information(id=0x%x, info=*0x%x)", id, info);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_lwmutex_information(u32 id, vm::ptr<sys_dbg_lwmutex_information_t> info)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_lwmutex_information()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_lwmutex_information(id=0x%x, info=*0x%x)", id, info);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_lwcond_information(u32 id, vm::ptr<sys_dbg_lwcond_information_t> info)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_lwcond_information()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_lwcond_information(id=0x%x, info=*0x%x)", id, info);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_event_flag_information(u32 id, vm::ptr<sys_dbg_event_flag_information_t> info)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_event_flag_information()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_event_flag_information(id=0x%x, info=*0x%x)", id, info);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_ppu_thread_ids(vm::ptr<u64> ids, vm::ptr<u64> ids_num, vm::ptr<u64> all_ids_num)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_ppu_thread_ids()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_ppu_thread_ids(ids=*0x%x, ids_num=*0x%x, all_ids_num=*0x%x)", ids, ids_num, all_ids_num);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_spu_thread_group_ids(vm::ptr<u32> ids, vm::ptr<u64> ids_num, vm::ptr<u64> all_ids_num)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_group_ids()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_group_ids(ids=*0x%x, ids_num=*0x%x, all_ids_num=*0x%x)", ids, ids_num, all_ids_num);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_spu_thread_ids(u32 group_id, vm::ptr<u32> ids, vm::ptr<u64> ids_num, vm::ptr<u64> all_ids_num)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_ids()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_ids(group_id=0x%x, ids=*0x%x, ids_num=*0x%x, all_ids_num=*0x%x)", group_id, ids, ids_num, all_ids_num);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_ppu_thread_name(u64 id, vm::ptr<char> name)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_ppu_thread_name()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_ppu_thread_name(id=0x%x, name=*0x%x)", id, name);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_spu_thread_name(u32 id, vm::ptr<char> name)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_name()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_name(id=0x%x, name=*0x%x)", id, name);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_spu_thread_group_name(u32 id, vm::ptr<char> name)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_group_name()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_group_name(id=0x%x, name=*0x%x)", id, name);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
error_code sys_dbg_get_ppu_thread_status(u64 id, vm::ptr<u32> status)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_ppu_thread_status()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_ppu_thread_status(id=0x%x, status=*0x%x)", id, status);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_spu_thread_group_status(u32 id, vm::ptr<u32> status)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_group_status()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_spu_thread_group_status(id=0x%x, status=*0x%x)", id, status);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
error_code sys_dbg_enable_floating_point_enabled_exception(u64 id, u64 flags, u64 opt1, u64 opt2)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_enable_floating_point_enabled_exception()");
|
||||
sys_lv2dbg.todo("sys_dbg_enable_floating_point_enabled_exception(id=0x%x, flags=0x%x, opt1=0x%x, opt2=0x%x)", id, flags, opt1, opt2);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_disable_floating_point_enabled_exception(u64 id, u64 flags, u64 opt1, u64 opt2)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_disable_floating_point_enabled_exception()");
|
||||
sys_lv2dbg.todo("sys_dbg_disable_floating_point_enabled_exception(id=0x%x, flags=0x%x, opt1=0x%x, opt2=0x%x)", id, flags, opt1, opt2);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
error_code sys_dbg_vm_get_page_information(u32 addr, u32 num, vm::ptr<sys_vm_page_information_t> pageinfo)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_vm_get_page_information()");
|
||||
sys_lv2dbg.todo("sys_dbg_vm_get_page_information(addr=0x%x, num=0x%x, pageinfo=*0x%x)", addr, num, pageinfo);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
error_code sys_dbg_set_address_to_dabr(u64 addr, u64 ctrl_flag)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_set_address_to_dabr()");
|
||||
sys_lv2dbg.todo("sys_dbg_set_address_to_dabr(addr=0x%x, spu_context=0x%x)", addr, ctrl_flag);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_get_address_from_dabr(vm::ptr<u64> addr, vm::ptr<u64> ctrl_flag)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_address_from_dabr()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_address_from_dabr(addr=*0x%x, spu_context=*0x%x)", addr, ctrl_flag);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
error_code sys_dbg_signal_to_coredump_handler(u64 data1, u64 data2, u64 data3)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_signal_to_coredump_handler()");
|
||||
sys_lv2dbg.todo("sys_dbg_signal_to_coredump_handler(data1=0x%x, data2=0x%x, data3=0x%x)", data1, data2, data3);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
error_code sys_dbg_mat_set_condition(u32 addr, u64 cond)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_mat_set_condition()");
|
||||
sys_lv2dbg.todo("sys_dbg_mat_set_condition(addr=0x%x, cond=0x%x)", addr, cond);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_mat_get_condition(u32 addr, vm::ptr<u64> condp)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_mat_get_condition()");
|
||||
sys_lv2dbg.todo("sys_dbg_mat_get_condition(addr=0x%x, condp=*0x%x)", addr, condp);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
error_code sys_dbg_get_coredump_params(vm::ptr<s32> param)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_get_coredump_params()");
|
||||
sys_lv2dbg.todo("sys_dbg_get_coredump_params(param=*0x%x)", param);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_dbg_set_mask_to_ppu_exception_handler(u64 mask, u64 flags)
|
||||
{
|
||||
sys_lv2dbg.todo("sys_dbg_set_mask_to_ppu_exception_handler()");
|
||||
sys_lv2dbg.todo("sys_dbg_set_mask_to_ppu_exception_handler(mask=0x%x, flags=0x%x)", mask, flags);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/system_config.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include "Emu/Cell/lv2/sys_lwmutex.h"
|
||||
#include "Emu/Cell/lv2/sys_mutex.h"
|
||||
#include "sysPrxForUser.h"
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
#include "Emu/Cell/lv2/sys_mutex.h"
|
||||
#include "Emu/Cell/lv2/sys_cond.h"
|
||||
|
||||
#include "sysPrxForUser.h"
|
||||
|
||||
LOG_CHANNEL(sysPrxForUser);
|
||||
|
||||
using sys_mempool_t = u32;
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "sys_net_.h"
|
||||
|
||||
LOG_CHANNEL(libnet);
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
s32 sys_net_accept(s32 s, vm::ptr<sys_net_sockaddr> addr, vm::ptr<u32> paddrlen)
|
||||
{
|
||||
libnet.todo("accept(s=%d, addr=*0x%x, paddrlen=*0x%x)", s, addr, paddrlen);
|
||||
@@ -46,19 +39,22 @@ s32 sys_net_gethostbyname()
|
||||
|
||||
s32 sys_net_getpeername(s32 s, vm::ptr<sys_net_sockaddr> addr, vm::ptr<u32> paddrlen)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libnet);
|
||||
libnet.todo("getpeername(s=%d, addr=*0x%x, paddrlen=*0x%x)", s, addr, paddrlen);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_net_getsockname(s32 s, vm::ptr<sys_net_sockaddr> addr, vm::ptr<u32> paddrlen)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libnet);
|
||||
libnet.todo("getsockname(s=%d, addr=*0x%x, paddrlen=*0x%x)", s, addr, paddrlen);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_net_getsockopt(s32 s, s32 level, s32 optname, vm::ptr<void> optval, vm::ptr<u32> optlen)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libnet);
|
||||
libnet.todo("getsockopt(s=%d, level=%d, optname=%d, optval=*0x%x, optlen=*0x%x)", s, level, optname, optval, optlen);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -143,7 +139,8 @@ s32 sys_net_recvfrom(s32 s, vm::ptr<void> buf, u32 len, s32 flags, vm::ptr<sys_n
|
||||
|
||||
s32 sys_net_recvmsg(s32 s, vm::ptr<sys_net_msghdr> msg, s32 flags)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libnet);
|
||||
libnet.todo("recvmsg(s=%d, msg=*0x%x, flags=0x%x)", s, msg, flags);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -156,7 +153,8 @@ s32 sys_net_send(s32 s, vm::cptr<void> buf, u32 len, s32 flags)
|
||||
|
||||
s32 sys_net_sendmsg(s32 s, vm::cptr<sys_net_msghdr> msg, s32 flags)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libnet);
|
||||
libnet.todo("sendmsg(s=%d, msg=*0x%x, flags=0x%x)", s, msg, flags);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -197,7 +195,8 @@ s32 sys_net_socketclose(s32 s)
|
||||
|
||||
s32 sys_net_socketpoll(vm::ptr<sys_net_pollfd> fds, s32 nfds, s32 ms)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libnet);
|
||||
libnet.todo("socketpoll(fds=*0x%x, nfds=%d, ms=%d)", fds, nfds, ms);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -272,7 +271,8 @@ s32 sys_net_get_sockinfo(s32 s, vm::ptr<sys_net_sockinfo_t> p, s32 n)
|
||||
|
||||
s32 sys_net_close_dump(s32 id, vm::ptr<s32> pflags)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libnet);
|
||||
libnet.todo("sys_net_close_dump(id=%d, pflags=*0x%x)", id, pflags);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -310,7 +310,8 @@ s32 sys_net_show_route()
|
||||
|
||||
s32 sys_net_read_dump(s32 id, vm::ptr<void> buf, s32 len, vm::ptr<s32> pflags)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libnet);
|
||||
libnet.todo("sys_net_read_dump(id=%d, buf=*0x%x, len=%d, pflags=*0x%x)", id, buf, len, pflags);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -346,7 +347,8 @@ s32 sys_net_get_sockinfo_ex()
|
||||
|
||||
s32 sys_net_open_dump(s32 len, s32 flags)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(libnet);
|
||||
libnet.todo("sys_net_open_dump(len=%d, flags=0x%x)", len, flags);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Cell/lv2/sys_net.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
|
||||
struct sys_net_sockinfo_t
|
||||
{
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_ppu_thread.h"
|
||||
#include "Emu/Cell/lv2/sys_interrupt.h"
|
||||
#include "Emu/Cell/lv2/sys_lwmutex.h"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "sysPrxForUser.h"
|
||||
|
||||
LOG_CHANNEL(sysPrxForUser);
|
||||
|
||||
error_code sys_rsxaudio_close_connection()
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "sysPrxForUser.h"
|
||||
|
||||
LOG_CHANNEL(sysPrxForUser);
|
||||
|
||||
void sys_spinlock_initialize(vm::ptr<atomic_be_t<u32>> lock)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_spu.h"
|
||||
#include "Crypto/unself.h"
|
||||
#include "Loader/ELF.h"
|
||||
#include "sysPrxForUser.h"
|
||||
|
||||
|
||||
@@ -532,7 +532,7 @@ namespace ppu_patterns
|
||||
}
|
||||
|
||||
static constexpr struct const_tag{} is_const;
|
||||
static constexpr struct range_tag{} is_range;
|
||||
/*static constexpr*/ struct range_tag{} /*is_range*/;
|
||||
static constexpr struct min_value_tag{} minv;
|
||||
static constexpr struct max_value_tag{} maxv;
|
||||
static constexpr struct sign_bit_tag{} sign_bitv;
|
||||
@@ -2361,7 +2361,9 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
|
||||
}
|
||||
case ppu_itype::MTSPR:
|
||||
{
|
||||
switch (const u32 n = (op.spr >> 5) | ((op.spr & 0x1f) << 5))
|
||||
const u32 spr_idx = (op.spr >> 5) | ((op.spr & 0x1f) << 5);
|
||||
|
||||
switch (spr_idx)
|
||||
{
|
||||
case 0x001: // MTXER
|
||||
{
|
||||
@@ -2459,7 +2461,6 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
|
||||
const reg_state_t rb = get_reg(op.rb);
|
||||
|
||||
const bool is_ra = ra(is_const) && (ra(minv) >= start && ra(minv) < segs_end);
|
||||
const bool is_rb = rb(is_const) && (rb(minv) >= start && rb(minv) < segs_end);
|
||||
|
||||
if (ra(is_const) == rb(is_const))
|
||||
{
|
||||
|
||||
@@ -1902,8 +1902,9 @@ auto gen_ghc_cpp_trampoline(ppu_intrp_func_t fn_target)
|
||||
// Take second ghc arg
|
||||
c.mov(args[0], x86::rbp);
|
||||
c.mov(args[2].r32(), x86::dword_ptr(args[0], ::offset32(&ppu_thread::cia)));
|
||||
c.add(args[2], x86::qword_ptr(reinterpret_cast<u64>(&vm::g_base_addr)));
|
||||
c.jmp(fn_target);
|
||||
c.movabs(args[1], reinterpret_cast<u64>(&vm::g_base_addr));
|
||||
c.add(args[2], x86::qword_ptr(args[1]));
|
||||
c.jmp(Imm(fn_target));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -192,13 +192,13 @@ namespace ppu_func_detail
|
||||
const u32 v_count = (info.last_value >> 24);
|
||||
|
||||
// TODO: check calculations
|
||||
const bool is_float = std::is_floating_point_v<T>;
|
||||
const bool is_vector = std::is_same_v<std::decay_t<T>, v128>;
|
||||
const bool is_context = std::is_base_of_v<std::decay_t<T>, ppu_thread>;
|
||||
const bool is_variadic = std::is_same_v<std::decay_t<T>, ppu_va_args_t>;
|
||||
const bool is_general = !is_float && !is_vector && !is_context && !is_variadic;
|
||||
constexpr bool is_float = std::is_floating_point_v<T>;
|
||||
constexpr bool is_vector = std::is_same_v<std::decay_t<T>, v128>;
|
||||
constexpr bool is_context = std::is_base_of_v<std::decay_t<T>, ppu_thread>;
|
||||
constexpr bool is_variadic = std::is_same_v<std::decay_t<T>, ppu_va_args_t>;
|
||||
constexpr bool is_general = !is_float && !is_vector && !is_context && !is_variadic;
|
||||
|
||||
const arg_class t =
|
||||
constexpr arg_class t =
|
||||
is_general ? (g_count >= 8 ? ARG_STACK : ARG_GENERAL) :
|
||||
is_float ? (f_count >= 13 ? ARG_STACK : ARG_FLOAT) :
|
||||
is_vector ? (v_count >= 12 ? ARG_STACK : ARG_VECTOR) :
|
||||
@@ -206,9 +206,9 @@ namespace ppu_func_detail
|
||||
is_variadic ? ARG_VARIADIC :
|
||||
ARG_UNKNOWN;
|
||||
|
||||
const u32 g = g_count + (is_general || is_float ? 1 : is_vector ? (g_count & 1) + 2 : 0);
|
||||
const u32 f = f_count + is_float;
|
||||
const u32 v = v_count + is_vector;
|
||||
constexpr u32 g = g_count + (is_general || is_float ? 1 : is_vector ? (g_count & 1) + 2 : 0);
|
||||
constexpr u32 f = f_count + is_float;
|
||||
constexpr u32 v = v_count + is_vector;
|
||||
|
||||
return call<Types...>(ppu, func, arg_info_pack_t<Info..., t | (g << 8) | (f << 16) | (v << 24)>{});
|
||||
}
|
||||
@@ -218,9 +218,9 @@ namespace ppu_func_detail
|
||||
{
|
||||
static_assert(!std::is_pointer_v<RT>, "Invalid function result type (pointer)");
|
||||
static_assert(!std::is_reference_v<RT>, "Invalid function result type (reference)");
|
||||
static const bool is_float = std::is_floating_point_v<RT>;
|
||||
static const bool is_vector = std::is_same_v<std::decay_t<RT>, v128>;
|
||||
static const arg_class value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
static constexpr bool is_float = std::is_floating_point_v<RT>;
|
||||
static constexpr bool is_vector = std::is_same_v<std::decay_t<RT>, v128>;
|
||||
static constexpr arg_class value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
};
|
||||
|
||||
template<typename RT, typename... T> struct func_binder;
|
||||
|
||||
@@ -1171,7 +1171,9 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
|
||||
auto find_first_of_multiple = [](std::string_view data, std::initializer_list<std::string_view> values, usz index)
|
||||
{
|
||||
u32 pos = static_cast<u32>(data.size());
|
||||
u32 pos = umax;
|
||||
|
||||
ensure(data.size() <= pos && index <= data.size());
|
||||
|
||||
for (std::string_view value : values)
|
||||
{
|
||||
@@ -1191,65 +1193,74 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
|
||||
u32 prev_bound = 0;
|
||||
|
||||
for (u32 i = find_first_of_multiple(seg_view, prefixes, 0); i < seg.size; i = find_first_of_multiple(seg_view, prefixes, utils::align<u32>(i + 1, 4)))
|
||||
for (u32 prefix_addr = find_first_of_multiple(seg_view, prefixes, 0); prefix_addr < seg.size; prefix_addr = find_first_of_multiple(seg_view, prefixes, prefix_addr + 4))
|
||||
{
|
||||
const auto elf_header = ensure(mod.get_ptr<u8>(seg.addr + i));
|
||||
const auto elf_header = ensure(mod.get_ptr<u8>(seg.addr + prefix_addr));
|
||||
|
||||
if (i % 4 == 0 && std::memcmp(elf_header, "\x24\0\x40\x80", 4) == 0)
|
||||
if (std::memcmp(elf_header, "\x24\0\x40\x80", 4) == 0)
|
||||
{
|
||||
bool next = true;
|
||||
const u32 old_i = i;
|
||||
u32 guid_start = umax, guid_end = umax;
|
||||
const u32 old_prefix_addr = prefix_addr;
|
||||
|
||||
for (u32 search = i & -128, tries = 10; tries && search >= prev_bound; tries--, search = utils::sub_saturate<u32>(search, 128))
|
||||
auto search_guid_pattern = [&](u32 index, std::string_view data_span, s32 advance_index, u32 lower_bound, u32 uppper_bound) -> u32
|
||||
{
|
||||
if (seg_view[search] != 0x42 && seg_view[search] != 0x43)
|
||||
for (u32 search = index & -16, tries = 16 * 64; tries && search >= lower_bound && search < uppper_bound; tries = tries - 1, search = advance_index < 0 ? utils::sub_saturate<u32>(search, 0 - advance_index) : search + advance_index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const u32 inst1 = read_from_ptr<be_t<u32>>(seg_view, search);
|
||||
const u32 inst2 = read_from_ptr<be_t<u32>>(seg_view, search + 4);
|
||||
const u32 inst3 = read_from_ptr<be_t<u32>>(seg_view, search + 8);
|
||||
const u32 inst4 = read_from_ptr<be_t<u32>>(seg_view, search + 12);
|
||||
|
||||
if ((inst1 & 0xfe'00'00'7f) != 0x42000002 || (inst2 & 0xfe'00'00'7f) != 0x42000002 || (inst3 & 0xfe'00'00'7f) != 0x42000002 || (inst4 & 0xfe'00'00'7f) != 0x42000002)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
guid_start = search + seg.addr;
|
||||
i = search;
|
||||
next = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (next)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string_view ls_segment = seg_view.substr(i);
|
||||
|
||||
// Bound to a bit less than LS size
|
||||
ls_segment = ls_segment.substr(0, 0x38000);
|
||||
|
||||
for (u32 addr_last = 0, valid_count = 0, invalid_count = 0;;)
|
||||
{
|
||||
const u32 instruction = static_cast<u32>(ls_segment.find("\x24\0\x40\x80"sv, addr_last));
|
||||
|
||||
if (instruction != umax)
|
||||
{
|
||||
if (instruction % 4 != i % 4)
|
||||
if (seg_view[search] != 0x42 && seg_view[search] != 0x43)
|
||||
{
|
||||
// Unaligned, continue
|
||||
addr_last = instruction + (i % 4 - instruction % 4) % 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
// FIXME: This seems to terminate SPU code prematurely in some cases
|
||||
// Likely due to absolute branches
|
||||
if (spu_thread::is_exec_code(instruction, {reinterpret_cast<const u8*>(ls_segment.data()), ls_segment.size()}, 0))
|
||||
const u32 inst1 = read_from_ptr<be_t<u32>>(data_span, search);
|
||||
const u32 inst2 = read_from_ptr<be_t<u32>>(data_span, search + 4);
|
||||
const u32 inst3 = read_from_ptr<be_t<u32>>(data_span, search + 8);
|
||||
const u32 inst4 = read_from_ptr<be_t<u32>>(data_span, search + 12);
|
||||
|
||||
if ((inst1 & 0xfe'00'00'7f) != 0x42000002 || (inst2 & 0xfe'00'00'7f) != 0x42000002 || (inst3 & 0xfe'00'00'7f) != 0x42000002 || (inst4 & 0xfe'00'00'7f) != 0x42000002)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!spu_thread::is_exec_code(search, {reinterpret_cast<const u8*>(data_span.data()), data_span.size()}, 0, true, true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
return umax;
|
||||
};
|
||||
|
||||
prefix_addr = search_guid_pattern(prefix_addr, seg_view, -16, prev_bound, seg.size);
|
||||
|
||||
if (prefix_addr == umax)
|
||||
{
|
||||
prefix_addr = old_prefix_addr;
|
||||
continue;
|
||||
}
|
||||
|
||||
u32 guid_start = seg.addr + prefix_addr, guid_end = umax;
|
||||
|
||||
std::string_view ls_segment = seg_view.substr(prefix_addr);
|
||||
|
||||
// Bound to a bit less than LS size
|
||||
ls_segment = ls_segment.substr(0, SPU_LS_SIZE - 0x8000);
|
||||
|
||||
for (u32 addr_last = 0, valid_count = 0, invalid_count = 0;;)
|
||||
{
|
||||
const u32 instruction = std::min<u32>(search_guid_pattern(addr_last, ls_segment, +16, 0, ::size32(ls_segment)), find_first_of_multiple(ls_segment, prefixes, addr_last));
|
||||
|
||||
if (instruction != umax && std::memcmp(ls_segment.data() + instruction, "\x24\0\x40\x80", 4) == 0)
|
||||
{
|
||||
if (instruction % 4 != prefix_addr % 4)
|
||||
{
|
||||
// Unaligned, continue
|
||||
addr_last = instruction + (prefix_addr % 4 - instruction % 4) % 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check execution compatibility
|
||||
if (spu_thread::is_exec_code(instruction, {reinterpret_cast<const u8*>(ls_segment.data()), ls_segment.size()}, 0, true, true))
|
||||
{
|
||||
addr_last = instruction + 4;
|
||||
valid_count++;
|
||||
@@ -1270,8 +1281,7 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
|
||||
if (addr_last >= 0x80 && valid_count >= 2)
|
||||
{
|
||||
const u32 begin = i & -128;
|
||||
u32 end = std::min<u32>(seg.size, utils::align<u32>(i + addr_last + 256, 128));
|
||||
u32 end = std::min<u32>({instruction, seg.size - prefix_addr, utils::align<u32>(addr_last + 256, 128)});
|
||||
|
||||
u32 guessed_ls_addr = 0;
|
||||
|
||||
@@ -1279,12 +1289,12 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
// ILA R2, PC + 8
|
||||
// BIE/BID R2
|
||||
|
||||
for (u32 found = 0, last_vaddr = 0, it = begin + 16; it < end - 16; it += 4)
|
||||
for (u32 found = 0, last_vaddr = 0, it = 16; it < end - 16; it += 4)
|
||||
{
|
||||
const u32 inst1 = read_from_ptr<be_t<u32>>(seg_view, it);
|
||||
const u32 inst2 = read_from_ptr<be_t<u32>>(seg_view, it + 4);
|
||||
const u32 inst3 = read_from_ptr<be_t<u32>>(seg_view, it + 8);
|
||||
const u32 inst4 = read_from_ptr<be_t<u32>>(seg_view, it + 12);
|
||||
const u32 inst1 = read_from_ptr<be_t<u32>>(ls_segment, it);
|
||||
const u32 inst2 = read_from_ptr<be_t<u32>>(ls_segment, it + 4);
|
||||
const u32 inst3 = read_from_ptr<be_t<u32>>(ls_segment, it + 8);
|
||||
const u32 inst4 = read_from_ptr<be_t<u32>>(ls_segment, it + 12);
|
||||
|
||||
if ((inst1 & 0xfe'00'00'7f) == 0x42000002 && (inst2 & 0xfe'00'00'7f) == 0x42000002 && (inst3 & 0xfe'00'00'7f) == 0x42000002 && (inst4 & 0xfe'00'00'7f) == 0x42000002)
|
||||
{
|
||||
@@ -1298,7 +1308,7 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
{
|
||||
const u32 addr_inst = (inst1 >> 7) % 0x40000;
|
||||
|
||||
if (u32 addr_seg = addr_inst - std::min<u32>(it + 8 - begin, addr_inst))
|
||||
if (u32 addr_seg = addr_inst - std::min<u32>(it + 8, addr_inst))
|
||||
{
|
||||
if (last_vaddr != addr_seg)
|
||||
{
|
||||
@@ -1321,23 +1331,27 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
|
||||
if (guessed_ls_addr)
|
||||
{
|
||||
end = begin + std::min<u32>(end - begin, SPU_LS_SIZE - guessed_ls_addr);
|
||||
end = prefix_addr + std::min<u32>(end, SPU_LS_SIZE - guessed_ls_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
end = prefix_addr + std::min<u32>(end, SPU_LS_SIZE);
|
||||
}
|
||||
|
||||
ppu_log.success("Found valid roaming SPU code at 0x%x..0x%x (guessed_ls_addr=0x%x, GUID=0x%05x..0x%05x)", seg.addr + begin, seg.addr + end, guessed_ls_addr, guid_start, guid_end);
|
||||
ppu_log.success("Found valid roaming SPU code at 0x%x..0x%x (guessed_ls_addr=0x%x, GUID=0x%05x..0x%05x)", seg.addr + prefix_addr, seg.addr + end, guessed_ls_addr, guid_start, guid_end);
|
||||
|
||||
if (!is_firmware && _main == &mod)
|
||||
{
|
||||
// Siginify that the base address is unknown by passing 0
|
||||
utilize_spu_data_segment(guessed_ls_addr ? guessed_ls_addr : 0x4000, seg_view.data() + begin, end - begin);
|
||||
utilize_spu_data_segment(guessed_ls_addr ? guessed_ls_addr : 0x4000, seg_view.data() + prefix_addr, end - prefix_addr);
|
||||
}
|
||||
|
||||
i = std::max<u32>(end, i + 4) - 4;
|
||||
prev_bound = i + 4;
|
||||
prefix_addr = std::max<u32>(end, prefix_addr + 4) - 4;
|
||||
prev_bound = prefix_addr + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = old_i;
|
||||
prefix_addr = old_prefix_addr;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1347,7 +1361,7 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
}
|
||||
|
||||
// Try to load SPU image
|
||||
const spu_exec_object obj(fs::file(elf_header, seg.size - i));
|
||||
const spu_exec_object obj(fs::file(elf_header, seg.size - prefix_addr));
|
||||
|
||||
if (obj != elf_error::ok)
|
||||
{
|
||||
@@ -1392,7 +1406,7 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
sha1_update(&sha2, (elf_header + prog.p_offset), prog.p_filesz);
|
||||
|
||||
// We assume that the string SPUNAME exists 0x14 bytes into the NOTE segment
|
||||
name = ensure(mod.get_ptr<const char>(seg.addr + i + prog.p_offset + 0x14));
|
||||
name = ensure(mod.get_ptr<const char>(seg.addr + prefix_addr + prog.p_offset + 0x14));
|
||||
|
||||
if (!name.empty())
|
||||
{
|
||||
@@ -1401,7 +1415,7 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
}
|
||||
}
|
||||
|
||||
fmt::append(dump, " (image addr: 0x%x, size: 0x%x)", seg.addr + i, obj.highest_offset);
|
||||
fmt::append(dump, " (image addr: 0x%x, size: 0x%x)", seg.addr + prefix_addr, obj.highest_offset);
|
||||
|
||||
sha1_finish(&sha2, sha1_hash);
|
||||
|
||||
@@ -1451,8 +1465,8 @@ static void ppu_check_patch_spu_images(const ppu_module<lv2_obj>& mod, const ppu
|
||||
ppu_loader.success("SPU executable hash: %s (<- %u)%s", hash, applied.size(), dump);
|
||||
}
|
||||
|
||||
i += ::narrow<u32>(obj.highest_offset) - 4;
|
||||
prev_bound = i + 4;
|
||||
prefix_addr += ::narrow<u32>(obj.highest_offset - 4);
|
||||
prev_bound = prefix_addr + 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2141,6 +2155,8 @@ bool ppu_load_exec(const ppu_exec_object& elf, bool virtual_load, const std::str
|
||||
|
||||
const auto old_process_info = g_ps3_process_info;
|
||||
|
||||
u32 segs_size = 0;
|
||||
|
||||
// Allocate memory at fixed positions
|
||||
for (const auto& prog : elf.progs)
|
||||
{
|
||||
@@ -2235,6 +2251,8 @@ bool ppu_load_exec(const ppu_exec_object& elf, bool virtual_load, const std::str
|
||||
{
|
||||
ppu_register_range(addr, size);
|
||||
}
|
||||
|
||||
segs_size += utils::align<u32>(size + (addr % 0x10000), 0x10000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2759,7 +2777,7 @@ bool ppu_load_exec(const ppu_exec_object& elf, bool virtual_load, const std::str
|
||||
|
||||
ppu->gpr[1] -= stack_alloc_size;
|
||||
|
||||
ensure(g_fxo->get<lv2_memory_container>().take(primary_stacksize));
|
||||
ensure(g_fxo->get<lv2_memory_container>().take(primary_stacksize + segs_size));
|
||||
|
||||
ppu->cmd_push({ppu_cmd::initialize, 0});
|
||||
|
||||
|
||||
@@ -220,19 +220,21 @@ const auto ppu_gateway = build_function_asm<void(*)(ppu_thread*)>("ppu_gateway",
|
||||
c.mov(x86::qword_ptr(args[0], ::offset32(&ppu_thread::hv_ctx, &rpcs3::hypervisor_context_t::regs)), x86::rsp);
|
||||
|
||||
// Initialize args
|
||||
c.mov(x86::r13, x86::qword_ptr(reinterpret_cast<u64>(&vm::g_exec_addr)));
|
||||
c.movabs(x86::r13, reinterpret_cast<u64>(&vm::g_exec_addr));
|
||||
c.mov(x86::r13, x86::qword_ptr(x86::r13));
|
||||
c.mov(x86::rbp, args[0]);
|
||||
c.mov(x86::edx, x86::dword_ptr(x86::rbp, ::offset32(&ppu_thread::cia))); // Load PC
|
||||
|
||||
c.mov(x86::rax, x86::qword_ptr(x86::r13, x86::edx, 1, 0)); // Load call target
|
||||
c.mov(x86::rdx, x86::rax);
|
||||
c.shl(x86::rax, 16);
|
||||
c.shr(x86::rax, 16);
|
||||
c.shr(x86::rdx, 48);
|
||||
c.mov(x86::rax, x86::qword_ptr(x86::r13, x86::rdx, 1, 0)); // Load call target
|
||||
c.movabs(x86::r12, vm::g_exec_addr_seg_offset);
|
||||
c.add(x86::r12, x86::r13);
|
||||
c.shr(x86::edx, 1);
|
||||
c.mov(x86::edx, x86::word_ptr(x86::r12, x86::edx)); // Load relocation base
|
||||
c.shl(x86::edx, 13);
|
||||
c.mov(x86::r12d, x86::edx); // Load relocation base
|
||||
c.mov(x86::r12d, x86::edx); // Set relocation base
|
||||
|
||||
c.mov(x86::rbx, x86::qword_ptr(reinterpret_cast<u64>(&vm::g_base_addr)));
|
||||
c.movabs(x86::rbx, reinterpret_cast<u64>(&vm::g_base_addr));
|
||||
c.mov(x86::rbx, x86::qword_ptr(x86::rbx));
|
||||
c.mov(x86::r14, x86::qword_ptr(x86::rbp, ::offset32(&ppu_thread::gpr, 0))); // Load some registers
|
||||
c.mov(x86::rsi, x86::qword_ptr(x86::rbp, ::offset32(&ppu_thread::gpr, 1)));
|
||||
c.mov(x86::rdi, x86::qword_ptr(x86::rbp, ::offset32(&ppu_thread::gpr, 2)));
|
||||
@@ -346,14 +348,11 @@ const auto ppu_gateway = build_function_asm<void(*)(ppu_thread*)>("ppu_gateway",
|
||||
c.ldr(call_target, arm::Mem(a64::x19, pc));
|
||||
// Compute REG_Hp
|
||||
const arm::GpX reg_hp = a64::x21;
|
||||
c.mov(reg_hp, call_target);
|
||||
c.lsr(reg_hp, reg_hp, 48);
|
||||
c.mov(reg_hp, Imm(vm::g_exec_addr_seg_offset));
|
||||
c.add(reg_hp, reg_hp, pc, arm::Shift(arm::ShiftOp::kLSR, 2));
|
||||
c.ldrh(reg_hp.w(), arm::Mem(a64::x19, reg_hp));
|
||||
c.lsl(reg_hp.w(), reg_hp.w(), 13);
|
||||
|
||||
// Zero top 16 bits of call target
|
||||
c.lsl(call_target, call_target, Imm(16));
|
||||
c.lsr(call_target, call_target, Imm(16));
|
||||
|
||||
// Load registers
|
||||
c.mov(a64::x22, Imm(reinterpret_cast<u64>(&vm::g_base_addr)));
|
||||
c.ldr(a64::x22, arm::Mem(a64::x22));
|
||||
@@ -473,6 +472,11 @@ static inline u8* ppu_ptr(u32 addr)
|
||||
return vm::g_exec_addr + u64{addr} * 2;
|
||||
}
|
||||
|
||||
static inline u8* ppu_seg_ptr(u32 addr)
|
||||
{
|
||||
return vm::g_exec_addr + vm::g_exec_addr_seg_offset + (addr >> 1);
|
||||
}
|
||||
|
||||
static inline ppu_intrp_func_t ppu_read(u32 addr)
|
||||
{
|
||||
return read_from_ptr<ppu_intrp_func_t>(ppu_ptr(addr));
|
||||
@@ -518,7 +522,7 @@ void ppu_recompiler_fallback(ppu_thread& ppu)
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (uptr func = uptr(ppu_read(ppu.cia)); (func << 16 >> 16) != reinterpret_cast<uptr>(ppu_recompiler_fallback_ghc))
|
||||
if (uptr func = uptr(ppu_read(ppu.cia)); func != reinterpret_cast<uptr>(ppu_recompiler_fallback_ghc))
|
||||
{
|
||||
// We found a recompiler function at cia, return
|
||||
break;
|
||||
@@ -773,6 +777,9 @@ extern void ppu_register_range(u32 addr, u32 size)
|
||||
utils::memory_commit(ppu_ptr(addr), u64{size} * 2, utils::protection::rw);
|
||||
ensure(vm::page_protect(addr, size, 0, vm::page_executable));
|
||||
|
||||
// Segment data
|
||||
utils::memory_commit(ppu_seg_ptr(addr), size >> 1, utils::protection::rw);
|
||||
|
||||
if (g_cfg.core.ppu_debug)
|
||||
{
|
||||
utils::memory_commit(vm::g_stat_addr + addr, size);
|
||||
@@ -785,12 +792,13 @@ extern void ppu_register_range(u32 addr, u32 size)
|
||||
if (g_cfg.core.ppu_decoder == ppu_decoder_type::llvm)
|
||||
{
|
||||
// Assume addr is the start of first segment of PRX
|
||||
const uptr entry_value = reinterpret_cast<uptr>(ppu_recompiler_fallback_ghc) | (seg_base << (32 + 3));
|
||||
write_to_ptr<uptr>(ppu_ptr(addr), entry_value);
|
||||
write_to_ptr<uptr>(ppu_ptr(addr), std::bit_cast<uptr>(ppu_recompiler_fallback_ghc));
|
||||
write_to_ptr<u16>(ppu_seg_ptr(addr), static_cast<u16>(seg_base >> 13));
|
||||
}
|
||||
else
|
||||
{
|
||||
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(addr), ppu_fallback);
|
||||
write_to_ptr<u16>(ppu_seg_ptr(addr), 0);
|
||||
}
|
||||
|
||||
addr += 4;
|
||||
@@ -805,7 +813,7 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_intrp_func_t ptr =
|
||||
// Initialize specific function
|
||||
if (ptr)
|
||||
{
|
||||
write_to_ptr<uptr>(ppu_ptr(addr), (reinterpret_cast<uptr>(ptr) & 0xffff'ffff'ffffu) | (uptr(ppu_read(addr)) & ~0xffff'ffff'ffffu));
|
||||
write_to_ptr<uptr>(ppu_ptr(addr), std::bit_cast<uptr>(ptr));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3164,8 +3172,9 @@ const auto ppu_stcx_accurate_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime
|
||||
|
||||
// Create stack frame if necessary (Windows ABI has only 6 volatile vector registers)
|
||||
c.push(x86::rbp);
|
||||
c.push(x86::r13);
|
||||
c.push(x86::r14);
|
||||
c.sub(x86::rsp, 40);
|
||||
c.sub(x86::rsp, 48);
|
||||
#ifdef _WIN32
|
||||
if (!s_tsx_avx)
|
||||
{
|
||||
@@ -3176,14 +3185,16 @@ const auto ppu_stcx_accurate_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime
|
||||
|
||||
// Prepare registers
|
||||
build_swap_rdx_with(c, args, x86::r10);
|
||||
c.mov(x86::rbp, x86::qword_ptr(reinterpret_cast<u64>(&vm::g_sudo_addr)));
|
||||
c.movabs(x86::rbp, reinterpret_cast<u64>(&vm::g_sudo_addr));
|
||||
c.mov(x86::rbp, x86::qword_ptr(x86::rbp));
|
||||
c.lea(x86::rbp, x86::qword_ptr(x86::rbp, args[0]));
|
||||
c.and_(x86::rbp, -128);
|
||||
c.prefetchw(x86::byte_ptr(x86::rbp, 0));
|
||||
c.prefetchw(x86::byte_ptr(x86::rbp, 64));
|
||||
c.movzx(args[0].r32(), args[0].r16());
|
||||
c.shr(args[0].r32(), 1);
|
||||
c.lea(x86::r11, x86::qword_ptr(reinterpret_cast<u64>(+vm::g_reservations), args[0]));
|
||||
c.movabs(x86::r11, reinterpret_cast<u64>(+vm::g_reservations));
|
||||
c.lea(x86::r11, x86::qword_ptr(x86::r11, args[0]));
|
||||
c.and_(x86::r11, -128 / 2);
|
||||
c.and_(args[0].r32(), 63);
|
||||
|
||||
@@ -3217,7 +3228,8 @@ const auto ppu_stcx_accurate_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime
|
||||
{
|
||||
build_get_tsc(c);
|
||||
c.sub(x86::rax, stamp0);
|
||||
c.cmp(x86::rax, x86::qword_ptr(reinterpret_cast<u64>(&g_rtm_tx_limit2)));
|
||||
c.movabs(x86::r13, reinterpret_cast<u64>(&g_rtm_tx_limit2));
|
||||
c.cmp(x86::rax, x86::qword_ptr(x86::r13));
|
||||
c.jae(fall);
|
||||
});
|
||||
|
||||
@@ -3342,8 +3354,9 @@ const auto ppu_stcx_accurate_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime
|
||||
c.vzeroupper();
|
||||
}
|
||||
|
||||
c.add(x86::rsp, 40);
|
||||
c.add(x86::rsp, 48);
|
||||
c.pop(x86::r14);
|
||||
c.pop(x86::r13);
|
||||
c.pop(x86::rbp);
|
||||
|
||||
maybe_flush_lbr(c);
|
||||
@@ -5079,17 +5092,18 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
||||
code_size_until_jump = buf_end - buf_start;
|
||||
|
||||
c.add(x86::edx, seg0);
|
||||
c.mov(x86::rax, x86::qword_ptr(reinterpret_cast<u64>(&vm::g_exec_addr)));
|
||||
c.movabs(x86::rax, reinterpret_cast<u64>(&vm::g_exec_addr));
|
||||
c.mov(x86::rax, x86::qword_ptr(x86::rax));
|
||||
c.mov(x86::dword_ptr(x86::rbp, ::offset32(&ppu_thread::cia)), x86::edx);
|
||||
|
||||
c.mov(x86::rax, x86::qword_ptr(x86::rax, x86::rdx, 1, 0)); // Load call target
|
||||
c.mov(x86::rdx, x86::rax);
|
||||
c.shl(x86::rax, 16);
|
||||
c.shr(x86::rax, 16);
|
||||
c.shr(x86::rdx, 48);
|
||||
c.mov(x86::rcx, x86::qword_ptr(x86::rax, x86::rdx, 1, 0)); // Load call target
|
||||
c.movabs(x86::r12, vm::g_exec_addr_seg_offset);
|
||||
c.add(x86::rax, x86::r12);
|
||||
c.shr(x86::edx, 1);
|
||||
c.mov(x86::edx, x86::word_ptr(x86::rax, x86::edx)); // Load relocation base
|
||||
c.shl(x86::edx, 13);
|
||||
c.mov(x86::r12d, x86::edx); // Load relocation base
|
||||
c.jmp(x86::rax);
|
||||
c.mov(x86::r12d, x86::edx); // Set relocation base
|
||||
c.jmp(x86::rcx);
|
||||
#else
|
||||
// Load REG_Base - use absolute jump target to bypass rel jmp range limits
|
||||
// X19 contains vm::g_exec_addr
|
||||
@@ -5125,14 +5139,11 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
||||
|
||||
// Compute REG_Hp
|
||||
const arm::GpX reg_hp = a64::x21;
|
||||
c.mov(reg_hp, call_target);
|
||||
c.lsr(reg_hp, reg_hp, 48);
|
||||
c.mov(reg_hp, Imm(vm::g_exec_addr_seg_offset));
|
||||
c.add(reg_hp, reg_hp, pc, arm::Shift(arm::ShiftOp::kLSR, 2));
|
||||
c.ldrh(reg_hp.w(), arm::Mem(exec_addr, reg_hp));
|
||||
c.lsl(reg_hp.w(), reg_hp.w(), 13);
|
||||
|
||||
// Zero top 16 bits of call target
|
||||
c.lsl(call_target, call_target, 16);
|
||||
c.lsr(call_target, call_target, 16);
|
||||
|
||||
// Execute LLE call
|
||||
c.br(call_target);
|
||||
#endif
|
||||
@@ -5400,7 +5411,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
||||
settings += ppu_settings::contains_symbol_resolver; // Avoid invalidating all modules for this purpose
|
||||
|
||||
// Write version, hash, CPU, settings
|
||||
fmt::append(obj_name, "v6-kusa-%s-%s-%s.obj", fmt::base57(output, 16), fmt::base57(settings), jit_compiler::cpu(g_cfg.core.llvm_cpu));
|
||||
fmt::append(obj_name, "v7-kusa-%s-%s-%s.obj", fmt::base57(output, 16), fmt::base57(settings), jit_compiler::cpu(g_cfg.core.llvm_cpu));
|
||||
}
|
||||
|
||||
if (cpu ? cpu->state.all_of(cpu_flag::exit) : Emu.IsStopped())
|
||||
@@ -5712,7 +5723,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
||||
|
||||
for (u32 addr = info.segs[0].addr; addr < info.segs[0].addr + info.segs[0].size; addr += 4, inst_ptr++)
|
||||
{
|
||||
if (*inst_ptr == ppu_instructions::BLR() && (reinterpret_cast<uptr>(ppu_read(addr)) << 16 >> 16) == reinterpret_cast<uptr>(ppu_recompiler_fallback_ghc))
|
||||
if (*inst_ptr == ppu_instructions::BLR() && reinterpret_cast<uptr>(ppu_read(addr)) == reinterpret_cast<uptr>(ppu_recompiler_fallback_ghc))
|
||||
{
|
||||
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(addr), BLR_func);
|
||||
}
|
||||
|
||||
@@ -411,12 +411,19 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module<lv2_obj>& info)
|
||||
|
||||
const auto faddr = m_ir->CreateLoad(ptr_inst->getResultElementType(), ptr_inst);
|
||||
const auto faddr_int = m_ir->CreatePtrToInt(faddr, get_type<uptr>());
|
||||
const auto fval = m_ir->CreateOr(m_ir->CreateShl(m_seg0, 32 + 3), faddr_int);
|
||||
const auto pos = m_ir->CreateShl(m_reloc ? m_ir->CreateAdd(func_pc, m_seg0) : func_pc, 1);
|
||||
const auto pos_32 = m_reloc ? m_ir->CreateAdd(func_pc, m_seg0) : func_pc;
|
||||
const auto pos = m_ir->CreateShl(pos_32, 1);
|
||||
const auto ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(get_type<u8>(), m_exec, pos));
|
||||
|
||||
const auto seg_base_ptr = m_ir->CreateIntToPtr(m_ir->CreateAdd(
|
||||
m_ir->CreatePtrToInt(m_exec, get_type<u64>()), m_ir->getInt64(vm::g_exec_addr_seg_offset)), m_exec->getType());
|
||||
const auto seg_pos = m_ir->CreateLShr(pos_32, 1);
|
||||
const auto seg_ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(get_type<u8>(), seg_base_ptr, seg_pos));
|
||||
const auto seg_val = m_ir->CreateTrunc(m_ir->CreateLShr(m_seg0, 13), get_type<u16>());
|
||||
|
||||
// Store to jumptable
|
||||
m_ir->CreateStore(fval, ptr);
|
||||
m_ir->CreateStore(faddr_int, ptr);
|
||||
m_ir->CreateStore(seg_val, seg_ptr);
|
||||
|
||||
// Increment index and branch back to loop
|
||||
const auto post_add = m_ir->CreateAdd(index_value, m_ir->getInt64(1));
|
||||
@@ -605,10 +612,15 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
|
||||
const auto pos = m_ir->CreateShl(indirect, 1);
|
||||
const auto ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(get_type<u8>(), m_exec, pos));
|
||||
const auto val = m_ir->CreateLoad(get_type<u64>(), ptr);
|
||||
callee = FunctionCallee(type, m_ir->CreateIntToPtr(m_ir->CreateAnd(val, 0xffff'ffff'ffff), type->getPointerTo()));
|
||||
callee = FunctionCallee(type, m_ir->CreateIntToPtr(val, type->getPointerTo()));
|
||||
|
||||
// Load new segment address
|
||||
seg0 = m_ir->CreateShl(m_ir->CreateLShr(val, 48), 13);
|
||||
const auto seg_base_ptr = m_ir->CreateIntToPtr(m_ir->CreateAdd(
|
||||
m_ir->CreatePtrToInt(m_exec, get_type<u64>()), m_ir->getInt64(vm::g_exec_addr_seg_offset)), m_exec->getType());
|
||||
const auto seg_pos = m_ir->CreateLShr(indirect, 1);
|
||||
const auto seg_ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(get_type<u8>(), seg_base_ptr, seg_pos));
|
||||
const auto seg_val = m_ir->CreateZExt(m_ir->CreateLoad(get_type<u16>(), seg_ptr), get_type<u64>());
|
||||
seg0 = m_ir->CreateShl(seg_val, 13);
|
||||
}
|
||||
|
||||
m_ir->SetInsertPoint(block);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "Loader/ELF.h"
|
||||
#include "util/asm.hpp"
|
||||
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "SPUThread.h"
|
||||
|
||||
inline void try_start(spu_thread& spu)
|
||||
{
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
#pragma once
|
||||
|
||||
#include "SPUThread.h"
|
||||
|
||||
@@ -5,15 +5,12 @@
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
|
||||
#include "SPUDisAsm.h"
|
||||
#include "SPUThread.h"
|
||||
#include "SPUInterpreter.h"
|
||||
#include "PPUAnalyser.h"
|
||||
#include "Crypto/sha1.h"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
#include "util/v128.hpp"
|
||||
#include "util/simd.hpp"
|
||||
#include "util/sysinfo.hpp"
|
||||
|
||||
#include <cmath>
|
||||
@@ -2773,14 +2770,17 @@ void spu_recompiler::FREST(spu_opcode_t op)
|
||||
const u64 fraction_lut_addr = reinterpret_cast<u64>(spu_frest_fraction_lut);
|
||||
const u64 exponent_lut_addr = reinterpret_cast<u64>(spu_frest_exponent_lut);
|
||||
|
||||
c->movabs(*arg0, fraction_lut_addr);
|
||||
c->movabs(*arg1, exponent_lut_addr);
|
||||
|
||||
for (u32 index = 0; index < 4; index++)
|
||||
{
|
||||
c->pextrd(*qw0, v_fraction, index);
|
||||
c->mov(*qw1, asmjit::x86::dword_ptr(fraction_lut_addr, *qw0, 2));
|
||||
c->mov(*qw1, asmjit::x86::dword_ptr(*arg0, *qw0, 2));
|
||||
c->pinsrd(v_fraction, *qw1, index);
|
||||
|
||||
c->pextrd(*qw0, v_exponent, index);
|
||||
c->mov(*qw1, asmjit::x86::dword_ptr(exponent_lut_addr, *qw0, 2));
|
||||
c->mov(*qw1, asmjit::x86::dword_ptr(*arg1, *qw0, 2));
|
||||
c->pinsrd(v_exponent, *qw1, index);
|
||||
}
|
||||
|
||||
@@ -2813,14 +2813,17 @@ void spu_recompiler::FRSQEST(spu_opcode_t op)
|
||||
const u64 fraction_lut_addr = reinterpret_cast<u64>(spu_frsqest_fraction_lut);
|
||||
const u64 exponent_lut_addr = reinterpret_cast<u64>(spu_frsqest_exponent_lut);
|
||||
|
||||
c->movabs(*arg0, fraction_lut_addr);
|
||||
c->movabs(*arg1, exponent_lut_addr);
|
||||
|
||||
for (u32 index = 0; index < 4; index++)
|
||||
{
|
||||
c->pextrd(*qw0, v_fraction, index);
|
||||
c->mov(*qw1, asmjit::x86::dword_ptr(fraction_lut_addr, *qw0, 2));
|
||||
c->mov(*qw1, asmjit::x86::dword_ptr(*arg0, *qw0, 2));
|
||||
c->pinsrd(v_fraction, *qw1, index);
|
||||
|
||||
c->pextrd(*qw0, v_exponent, index);
|
||||
c->mov(*qw1, asmjit::x86::dword_ptr(exponent_lut_addr, *qw0, 2));
|
||||
c->mov(*qw1, asmjit::x86::dword_ptr(*arg1, *qw0, 2));
|
||||
c->pinsrd(v_exponent, *qw1, index);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/types.hpp"
|
||||
|
||||
// SPU Instruction Type
|
||||
struct spu_itype
|
||||
{
|
||||
|
||||
@@ -842,6 +842,7 @@ void spu_cache::initialize(bool build_existing_cache)
|
||||
// Initialize compiler instances for parallel compilation
|
||||
std::unique_ptr<spu_recompiler_base> compiler;
|
||||
|
||||
#if defined(ARCH_X64)
|
||||
if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit)
|
||||
{
|
||||
compiler = spu_recompiler_base::make_asmjit_recompiler();
|
||||
@@ -850,6 +851,22 @@ void spu_cache::initialize(bool build_existing_cache)
|
||||
{
|
||||
compiler = spu_recompiler_base::make_llvm_recompiler();
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::throw_exception("Unsupported spu decoder '%s'", g_cfg.core.spu_decoder);
|
||||
}
|
||||
#elif defined(ARCH_ARM64)
|
||||
if (g_cfg.core.spu_decoder == spu_decoder_type::llvm)
|
||||
{
|
||||
compiler = spu_recompiler_base::make_llvm_recompiler();
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::throw_exception("Unsupported spu decoder '%s'", g_cfg.core.spu_decoder);
|
||||
}
|
||||
#else
|
||||
#error "Unimplemented"
|
||||
#endif
|
||||
|
||||
compiler->init();
|
||||
|
||||
@@ -2545,7 +2562,7 @@ bool reg_state_t::is_const() const
|
||||
|
||||
bool reg_state_t::compare_tags(const reg_state_t& rhs) const
|
||||
{
|
||||
// Compare by tag, address of instruction origin
|
||||
// Compare by tag, address of instruction origin
|
||||
return tag == rhs.tag && origin == rhs.origin && is_instruction == rhs.is_instruction;
|
||||
}
|
||||
|
||||
@@ -6066,7 +6083,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||
else if (atomic16->ls_offs.compare_with_mask_indifference(atomic16->lsa, SPU_LS_MASK_128) && atomic16->ls.is_less_than(128 - (atomic16->ls_offs.value & 127)))
|
||||
{
|
||||
// Relative memory access with offset less than 128 bytes
|
||||
// Common around SPU utilities which have less strict restrictions about memory alignment
|
||||
// Common around SPU utilities which have less strict restrictions about memory alignment
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
@@ -6340,7 +6357,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||
{
|
||||
atomic16->mem_count++;
|
||||
|
||||
// Do not clear lower 16 bytes addressing because the program can move on 4-byte basis
|
||||
// Do not clear lower 16 bytes addressing because the program can move on 4-byte basis
|
||||
const u32 offs = spu_branch_target(pos - result.lower_bound, op.si16);
|
||||
|
||||
if (atomic16->lsa.is_const() && [&]()
|
||||
@@ -7359,7 +7376,7 @@ struct spu_llvm_worker
|
||||
set_relax_flag = false;
|
||||
}
|
||||
|
||||
thread_ctrl::wait_on(utils::bless<atomic_t<u32>>(®istered)[1], 0);
|
||||
thread_ctrl::wait_on(registered.get_wait_atomic(), 0);
|
||||
slice = registered.pop_all();
|
||||
}())
|
||||
{
|
||||
@@ -7474,7 +7491,7 @@ struct spu_llvm
|
||||
while (!registered && thread_ctrl::state() != thread_state::aborting)
|
||||
{
|
||||
// Wait for the first SPU block before launching any thread
|
||||
thread_ctrl::wait_on(utils::bless<atomic_t<u32>>(®istered)[1], 0);
|
||||
thread_ctrl::wait_on(registered.get_wait_atomic(), 0);
|
||||
}
|
||||
|
||||
if (thread_ctrl::state() == thread_state::aborting)
|
||||
@@ -7577,7 +7594,7 @@ struct spu_llvm
|
||||
|
||||
// Interrupt profiler thread and put it to sleep
|
||||
static_cast<void>(prof_mutex.reset());
|
||||
thread_ctrl::wait_on(utils::bless<atomic_t<u32>>(®istered)[1], 0);
|
||||
thread_ctrl::wait_on(registered.get_wait_atomic(), 0);
|
||||
std::fill(notify_compile.begin(), notify_compile.end(), 0); // Reset notification flags
|
||||
notify_compile_count = 0;
|
||||
compile_pending = 0;
|
||||
@@ -8142,7 +8159,7 @@ std::array<reg_state_t, s_reg_max>& block_reg_info::evaluate_start_state(const s
|
||||
// Check if the node is resolved
|
||||
if (!node->has_true_state)
|
||||
{
|
||||
// Assume this block cannot be resolved at the moment
|
||||
// Assume this block cannot be resolved at the moment
|
||||
is_all_resolved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "Utilities/JIT.h"
|
||||
#include "SPUThread.h"
|
||||
#include "Emu/Cell/Common.h"
|
||||
#include "Emu/Cell/SPUAnalyser.h"
|
||||
#include "Emu/system_config.h"
|
||||
|
||||
@@ -13,7 +12,6 @@
|
||||
#include "util/sysinfo.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <cfenv>
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#pragma GCC diagnostic push
|
||||
|
||||
@@ -628,6 +628,8 @@ const auto spu_putllc_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime, void*
|
||||
//}
|
||||
|
||||
// Create stack frame if necessary (Windows ABI has only 6 volatile vector registers)
|
||||
c.push(x86::rbp);
|
||||
c.push(x86::rbx);
|
||||
#ifdef _WIN32
|
||||
c.sub(x86::rsp, 168);
|
||||
if (s_tsx_avx)
|
||||
@@ -648,17 +650,21 @@ const auto spu_putllc_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime, void*
|
||||
c.movups(x86::oword_ptr(x86::rsp, 128), x86::xmm14);
|
||||
c.movups(x86::oword_ptr(x86::rsp, 144), x86::xmm15);
|
||||
}
|
||||
#else
|
||||
c.sub(x86::rsp, 40);
|
||||
#endif
|
||||
|
||||
// Prepare registers
|
||||
build_swap_rdx_with(c, args, x86::r10);
|
||||
c.mov(args[1], x86::qword_ptr(reinterpret_cast<u64>(&vm::g_sudo_addr)));
|
||||
c.movabs(args[1], reinterpret_cast<u64>(&vm::g_sudo_addr));
|
||||
c.mov(args[1], x86::qword_ptr(args[1]));
|
||||
c.lea(args[1], x86::qword_ptr(args[1], args[0]));
|
||||
c.prefetchw(x86::byte_ptr(args[1], 0));
|
||||
c.prefetchw(x86::byte_ptr(args[1], 64));
|
||||
c.and_(args[0].r32(), 0xff80);
|
||||
c.shr(args[0].r32(), 1);
|
||||
c.lea(x86::r11, x86::qword_ptr(reinterpret_cast<u64>(+vm::g_reservations), args[0]));
|
||||
c.movabs(x86::r11, reinterpret_cast<u64>(+vm::g_reservations));
|
||||
c.lea(x86::r11, x86::qword_ptr(x86::r11, args[0]));
|
||||
|
||||
// Prepare data
|
||||
if (s_tsx_avx)
|
||||
@@ -703,7 +709,8 @@ const auto spu_putllc_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime, void*
|
||||
c.add(x86::qword_ptr(args[2], ::offset32(&spu_thread::ftx) - ::offset32(&spu_thread::rdata)), 1);
|
||||
build_get_tsc(c);
|
||||
c.sub(x86::rax, stamp0);
|
||||
c.cmp(x86::rax, x86::qword_ptr(reinterpret_cast<u64>(&g_rtm_tx_limit2)));
|
||||
c.movabs(x86::rbx, reinterpret_cast<u64>(&g_rtm_tx_limit2));
|
||||
c.cmp(x86::rax, x86::qword_ptr(x86::rbx));
|
||||
c.jae(fall);
|
||||
});
|
||||
|
||||
@@ -853,8 +860,13 @@ const auto spu_putllc_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime, void*
|
||||
c.movups(x86::xmm15, x86::oword_ptr(x86::rsp, 144));
|
||||
}
|
||||
c.add(x86::rsp, 168);
|
||||
#else
|
||||
c.add(x86::rsp, 40);
|
||||
#endif
|
||||
|
||||
c.pop(x86::rbx);
|
||||
c.pop(x86::rbp);
|
||||
|
||||
if (s_tsx_avx)
|
||||
{
|
||||
c.vzeroupper();
|
||||
@@ -884,8 +896,10 @@ const auto spu_putlluc_tx = build_function_asm<u64(*)(u32 raddr, const void* rda
|
||||
//}
|
||||
|
||||
// Create stack frame if necessary (Windows ABI has only 6 volatile vector registers)
|
||||
#ifdef _WIN32
|
||||
c.push(x86::rbp);
|
||||
c.push(x86::rbx);
|
||||
c.sub(x86::rsp, 40);
|
||||
#ifdef _WIN32
|
||||
if (!s_tsx_avx)
|
||||
{
|
||||
c.movups(x86::oword_ptr(x86::rsp, 0), x86::xmm6);
|
||||
@@ -894,7 +908,8 @@ const auto spu_putlluc_tx = build_function_asm<u64(*)(u32 raddr, const void* rda
|
||||
#endif
|
||||
// Prepare registers
|
||||
build_swap_rdx_with(c, args, x86::r10);
|
||||
c.mov(x86::r11, x86::qword_ptr(reinterpret_cast<u64>(&vm::g_sudo_addr)));
|
||||
c.movabs(x86::r11, reinterpret_cast<u64>(&vm::g_sudo_addr));
|
||||
c.mov(x86::r11, x86::qword_ptr(x86::r11));
|
||||
c.lea(x86::r11, x86::qword_ptr(x86::r11, args[0]));
|
||||
c.prefetchw(x86::byte_ptr(x86::r11, 0));
|
||||
c.prefetchw(x86::byte_ptr(x86::r11, 64));
|
||||
@@ -921,7 +936,8 @@ const auto spu_putlluc_tx = build_function_asm<u64(*)(u32 raddr, const void* rda
|
||||
|
||||
c.and_(args[0].r32(), 0xff80);
|
||||
c.shr(args[0].r32(), 1);
|
||||
c.lea(args[1], x86::qword_ptr(reinterpret_cast<u64>(+vm::g_reservations), args[0]));
|
||||
c.movabs(args[1], reinterpret_cast<u64>(+vm::g_reservations));
|
||||
c.lea(args[1], x86::qword_ptr(args[1], args[0]));
|
||||
|
||||
// Alloc args[0] to stamp0
|
||||
const auto stamp0 = args[0];
|
||||
@@ -933,7 +949,8 @@ const auto spu_putlluc_tx = build_function_asm<u64(*)(u32 raddr, const void* rda
|
||||
c.add(x86::qword_ptr(args[3]), 1);
|
||||
build_get_tsc(c);
|
||||
c.sub(x86::rax, stamp0);
|
||||
c.cmp(x86::rax, x86::qword_ptr(reinterpret_cast<u64>(&g_rtm_tx_limit2)));
|
||||
c.movabs(x86::rbx, reinterpret_cast<u64>(&g_rtm_tx_limit2));
|
||||
c.cmp(x86::rax, x86::qword_ptr(x86::rbx));
|
||||
c.jae(fall);
|
||||
});
|
||||
|
||||
@@ -986,6 +1003,10 @@ const auto spu_putlluc_tx = build_function_asm<u64(*)(u32 raddr, const void* rda
|
||||
c.vzeroupper();
|
||||
}
|
||||
|
||||
c.add(x86::rsp, 40);
|
||||
c.pop(x86::rbx);
|
||||
c.pop(x86::rbp);
|
||||
|
||||
maybe_flush_lbr(c);
|
||||
c.ret();
|
||||
#else
|
||||
@@ -1023,11 +1044,13 @@ const auto spu_getllar_tx = build_function_asm<u64(*)(u32 raddr, void* rdata, cp
|
||||
|
||||
// Prepare registers
|
||||
build_swap_rdx_with(c, args, x86::r10);
|
||||
c.mov(x86::rbp, x86::qword_ptr(reinterpret_cast<u64>(&vm::g_sudo_addr)));
|
||||
c.movabs(x86::rbp, reinterpret_cast<u64>(&vm::g_sudo_addr));
|
||||
c.mov(x86::rbp, x86::qword_ptr(x86::rbp));
|
||||
c.lea(x86::rbp, x86::qword_ptr(x86::rbp, args[0]));
|
||||
c.and_(args[0].r32(), 0xff80);
|
||||
c.shr(args[0].r32(), 1);
|
||||
c.lea(x86::r11, x86::qword_ptr(reinterpret_cast<u64>(+vm::g_reservations), args[0]));
|
||||
c.movabs(x86::r11, reinterpret_cast<u64>(+vm::g_reservations));
|
||||
c.lea(x86::r11, x86::qword_ptr(x86::r11, args[0]));
|
||||
|
||||
// Alloc args[0] to stamp0
|
||||
const auto stamp0 = args[0];
|
||||
@@ -1039,7 +1062,8 @@ const auto spu_getllar_tx = build_function_asm<u64(*)(u32 raddr, void* rdata, cp
|
||||
c.add(x86::qword_ptr(args[2], ::offset32(&spu_thread::ftx)), 1);
|
||||
build_get_tsc(c);
|
||||
c.sub(x86::rax, stamp0);
|
||||
c.cmp(x86::rax, x86::qword_ptr(reinterpret_cast<u64>(&g_rtm_tx_limit1)));
|
||||
c.movabs(x86::rbx, reinterpret_cast<u64>(&g_rtm_tx_limit1));
|
||||
c.cmp(x86::rax, x86::qword_ptr(x86::rbx));
|
||||
c.jae(fall);
|
||||
});
|
||||
|
||||
@@ -1209,8 +1233,6 @@ void spu_thread::dump_regs(std::string& ret, std::any& /*custom_data*/) const
|
||||
u32 saved_pc = umax;
|
||||
const u8* lsa_state_ptr = nullptr;
|
||||
|
||||
const u8* lsa_ptr = _ptr<u8>(ch_mfc_cmd.lsa);
|
||||
|
||||
// Load PC, GPRs and reservation data atomically
|
||||
// We may not load the entire context atomically, but there is importance their state being intact for debugging
|
||||
do
|
||||
@@ -2107,6 +2129,41 @@ u8* spu_thread::map_ls(utils::shm& shm, void* ptr)
|
||||
return ls;
|
||||
}
|
||||
|
||||
void spu_thread::init_spu_decoder()
|
||||
{
|
||||
ensure(!jit);
|
||||
|
||||
#if !defined(ARCH_X64) && !defined(ARCH_ARM64)
|
||||
#error "Unimplemented"
|
||||
#else
|
||||
const spu_decoder_type spu_decoder = g_cfg.core.spu_decoder;
|
||||
|
||||
#if defined(ARCH_X64)
|
||||
if (spu_decoder == spu_decoder_type::asmjit)
|
||||
{
|
||||
jit = spu_recompiler_base::make_asmjit_recompiler();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (spu_decoder == spu_decoder_type::llvm)
|
||||
{
|
||||
#if defined(ARCH_X64)
|
||||
jit = spu_recompiler_base::make_fast_llvm_recompiler();
|
||||
#elif defined(ARCH_ARM64)
|
||||
jit = spu_recompiler_base::make_llvm_recompiler();
|
||||
#endif
|
||||
}
|
||||
else if (spu_decoder == spu_decoder_type::_static || spu_decoder == spu_decoder_type::dynamic)
|
||||
{
|
||||
//
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::throw_exception("Unsupported spu decoder '%s'", g_cfg.core.spu_decoder);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated, u32 option)
|
||||
: cpu_thread(idm::last_id())
|
||||
, group(group)
|
||||
@@ -2118,20 +2175,7 @@ spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u
|
||||
, lv2_id(lv2_id)
|
||||
, spu_tname(make_single<std::string>(name))
|
||||
{
|
||||
if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit)
|
||||
{
|
||||
jit = spu_recompiler_base::make_asmjit_recompiler();
|
||||
}
|
||||
else if (g_cfg.core.spu_decoder == spu_decoder_type::llvm)
|
||||
{
|
||||
#if defined(ARCH_X64)
|
||||
jit = spu_recompiler_base::make_fast_llvm_recompiler();
|
||||
#elif defined(ARCH_ARM64)
|
||||
jit = spu_recompiler_base::make_llvm_recompiler();
|
||||
#else
|
||||
#error "Unimplemented"
|
||||
#endif
|
||||
}
|
||||
init_spu_decoder();
|
||||
|
||||
if (g_cfg.core.mfc_debug)
|
||||
{
|
||||
@@ -2193,20 +2237,7 @@ spu_thread::spu_thread(utils::serial& ar, lv2_spu_group* group)
|
||||
, lv2_id(ar)
|
||||
, spu_tname(make_single<std::string>(ar.operator std::string()))
|
||||
{
|
||||
if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit)
|
||||
{
|
||||
jit = spu_recompiler_base::make_asmjit_recompiler();
|
||||
}
|
||||
else if (g_cfg.core.spu_decoder == spu_decoder_type::llvm)
|
||||
{
|
||||
#if defined(ARCH_X64)
|
||||
jit = spu_recompiler_base::make_fast_llvm_recompiler();
|
||||
#elif defined(ARCH_ARM64)
|
||||
jit = spu_recompiler_base::make_llvm_recompiler();
|
||||
#else
|
||||
#error "Unimplemented"
|
||||
#endif
|
||||
}
|
||||
init_spu_decoder();
|
||||
|
||||
if (g_cfg.core.mfc_debug)
|
||||
{
|
||||
@@ -4329,7 +4360,7 @@ bool spu_thread::check_mfc_interrupts(u32 next_pc)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_addr, bool avoid_dead_code)
|
||||
bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_addr, bool avoid_dead_code, bool is_range_limited)
|
||||
{
|
||||
bool had_conditional = false;
|
||||
|
||||
@@ -4337,12 +4368,12 @@ bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_add
|
||||
{
|
||||
if (addr & ~0x3FFFC)
|
||||
{
|
||||
return false;
|
||||
return is_range_limited;
|
||||
}
|
||||
|
||||
if (addr < base_addr || addr >= base_addr + ls_ptr.size())
|
||||
{
|
||||
return false;
|
||||
return is_range_limited;
|
||||
}
|
||||
|
||||
const u32 addr0 = spu_branch_target(addr);
|
||||
@@ -4445,19 +4476,19 @@ bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_add
|
||||
// Detect "invalid" relative branches
|
||||
// Branch offsets that, although are the only way to get X code address using relative address
|
||||
// Rely on overflow/underflow of SPU memory bounds
|
||||
// Thus they would behave differently if SPU LS memory size was to increase (evolving the CELL architecture was the original plan)
|
||||
// Thus they would behave differently if SPU LS memory size was to increase (evolving the CELL architecture was the original plan)
|
||||
// Making them highly unlikely to be valid code
|
||||
|
||||
if (rel < 0)
|
||||
{
|
||||
if (addr < 0u - rel)
|
||||
{
|
||||
return false;
|
||||
return is_range_limited;
|
||||
}
|
||||
}
|
||||
else if (SPU_LS_SIZE - addr <= rel + 0u)
|
||||
{
|
||||
return false;
|
||||
return is_range_limited;
|
||||
}
|
||||
|
||||
if (type == spu_itype::BRSL)
|
||||
@@ -4487,7 +4518,7 @@ bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_add
|
||||
|
||||
if (route_pc < base_addr || route_pc >= base_addr + ls_ptr.size())
|
||||
{
|
||||
return false;
|
||||
return is_range_limited;
|
||||
}
|
||||
|
||||
// Test the validity of a single instruction of the optional target
|
||||
@@ -4518,6 +4549,126 @@ u32 spu_thread::get_mfc_completed() const
|
||||
return ch_tag_mask & ~mfc_fence;
|
||||
}
|
||||
|
||||
u32 evaluate_spin_optimization(std::span<u8> stats, u64 evaluate_time, const cfg::uint<0, 100>& wait_percent, bool inclined_for_responsiveness = false)
|
||||
{
|
||||
ensure(stats.size() >= 2 && stats.size() <= 16);
|
||||
|
||||
const u32 percent = wait_percent;
|
||||
|
||||
// Predict whether or not to use operating system sleep based on history
|
||||
|
||||
std::array<u8, 16> old_stats{};
|
||||
std::copy_n(stats.data(), stats.size(), old_stats.data());
|
||||
|
||||
// Rotate history (prepare newest entry)
|
||||
stats[0] = 0;
|
||||
std::copy_n(old_stats.data(), stats.size() - 1, stats.data() + 1);
|
||||
|
||||
u32 total_wait = 0;
|
||||
u32 zero_count = 0; // Try to ignore major inconsistencies
|
||||
u32 consecutive_zero = 0;
|
||||
u32 consecutive_zero_or_one = 0;
|
||||
u32 consecutive_zero_or_one_tally = 0;
|
||||
|
||||
usz index = umax;
|
||||
|
||||
for (u8 val : old_stats)
|
||||
{
|
||||
index++;
|
||||
|
||||
if (index == stats.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
total_wait += val;
|
||||
|
||||
if (val == 0)
|
||||
{
|
||||
if (consecutive_zero == index)
|
||||
{
|
||||
consecutive_zero++;
|
||||
consecutive_zero_or_one++;
|
||||
//consecutive_zero_or_one_tally += 0;
|
||||
}
|
||||
|
||||
++zero_count;
|
||||
}
|
||||
|
||||
if (val == 1)
|
||||
{
|
||||
if (consecutive_zero_or_one == index)
|
||||
{
|
||||
consecutive_zero_or_one++;
|
||||
consecutive_zero_or_one_tally++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inclined_for_responsiveness)
|
||||
{
|
||||
total_wait /= 2;
|
||||
}
|
||||
|
||||
// Add to chance if previous wait was long enough
|
||||
u32 add_count = 0;
|
||||
|
||||
if (stats.size() == 4)
|
||||
{
|
||||
add_count = zero_count == 3 && total_wait >= 9 ? (total_wait - 8) * 40
|
||||
: zero_count == 2 && total_wait >= 8 ? (total_wait - 7) * 40
|
||||
: zero_count == 1 && total_wait >= 7 ? (total_wait - 6) * 40
|
||||
: zero_count == 0 && total_wait >= 4 ? (total_wait - 3) * 40
|
||||
: 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
add_count = zero_count >= 12 && total_wait >= 80 ? (total_wait - 80) * 30
|
||||
: zero_count >= 7 && total_wait >= 30 ? (total_wait - 30) * 10
|
||||
: zero_count >= 4 && total_wait >= 20 ? (total_wait - 20) * 10
|
||||
: zero_count >= 0 && total_wait >= 10 ? (total_wait - 10) * 10
|
||||
: 0;
|
||||
}
|
||||
|
||||
if (stats.size() == 16 && (consecutive_zero >= 2 || (consecutive_zero_or_one >= 3 && consecutive_zero_or_one_tally < consecutive_zero_or_one * 2 / 3)))
|
||||
{
|
||||
// Thread is back to action after some sleep
|
||||
add_count = 0;
|
||||
}
|
||||
|
||||
if (inclined_for_responsiveness && std::count(old_stats.data(), old_stats.data() + 3, 0) >= 2)
|
||||
{
|
||||
add_count = 0;
|
||||
}
|
||||
|
||||
// Evalute its value (shift-right to ensure its randomness with different CPUs)
|
||||
const u32 busy_waiting_switch = ((evaluate_time >> 8) % 100 + add_count < percent) ? 1 : 0;
|
||||
|
||||
thread_local usz g_system_wait = 0, g_busy_wait = 0;
|
||||
|
||||
if (busy_waiting_switch)
|
||||
{
|
||||
g_busy_wait++;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_system_wait++;
|
||||
}
|
||||
|
||||
if ((g_system_wait + g_busy_wait) && (g_system_wait + g_busy_wait) % 200 == 0)
|
||||
{
|
||||
spu_log.trace("SPU wait: count=%d. switch=%d, spin=%d, busy=%d, system=%d, {%d, %d, %d, %d}", total_wait, busy_waiting_switch, !"TODO: Spin", +g_busy_wait, +g_system_wait, old_stats[0], old_stats[1], old_stats[2], old_stats[3]);
|
||||
}
|
||||
|
||||
if ((g_system_wait + g_busy_wait) % 5000 == 0)
|
||||
{
|
||||
g_system_wait = 0;
|
||||
g_busy_wait = 0;
|
||||
}
|
||||
|
||||
return busy_waiting_switch;
|
||||
}
|
||||
|
||||
bool spu_thread::process_mfc_cmd()
|
||||
{
|
||||
// Stall infinitely if MFC queue is full
|
||||
@@ -4632,61 +4783,16 @@ bool spu_thread::process_mfc_cmd()
|
||||
|
||||
getllar_spin_count = std::min<u32>(getllar_spin_count + 1, u16{umax});
|
||||
|
||||
static atomic_t<usz> g_ok = 0, g_fail = 0;
|
||||
|
||||
if (getllar_busy_waiting_switch == umax && getllar_spin_count == 4)
|
||||
{
|
||||
// Hidden value to force busy waiting (100 to 1 are dynamically adjusted, 0 is not)
|
||||
if (!g_cfg.core.spu_getllar_spin_optimization_disabled)
|
||||
{
|
||||
const u32 percent = g_cfg.core.spu_getllar_busy_waiting_percentage;
|
||||
|
||||
// Predict whether or not to use operating system sleep based on history
|
||||
auto& stats = getllar_wait_time[(addr % SPU_LS_SIZE) / 128];
|
||||
|
||||
const std::array<u8, 4> old_stats = stats;
|
||||
std::array<u8, 4> new_stats{};
|
||||
|
||||
// Rotate history (prepare newest entry)
|
||||
new_stats[0] = 0;
|
||||
new_stats[1] = old_stats[0];
|
||||
new_stats[2] = old_stats[1];
|
||||
new_stats[3] = old_stats[2];
|
||||
|
||||
stats = new_stats;
|
||||
|
||||
u32 total_wait = 0;
|
||||
u32 zero_count = 0; // Try to ignore major inconsistencies
|
||||
|
||||
for (u8 val : old_stats)
|
||||
{
|
||||
total_wait += val;
|
||||
if (val == 0) ++zero_count;
|
||||
}
|
||||
|
||||
// Add to chance if previous wait was long enough
|
||||
const u32 add_count = zero_count == 3 && total_wait >= 40 ? (total_wait - 39) * 40
|
||||
: zero_count == 2 && total_wait >= 11 ? (total_wait - 10) * 40
|
||||
: zero_count == 1 && total_wait >= 8 ? (total_wait - 7) * 40
|
||||
: zero_count == 0 && total_wait >= 6 ? (total_wait - 5) * 40
|
||||
: 0;
|
||||
|
||||
// Evalute its value (shift-right to ensure its randomness with different CPUs)
|
||||
getllar_busy_waiting_switch = ((perf0.get() >> 8) % 100 + add_count < percent) ? 1 : 0;
|
||||
|
||||
getllar_evaluate_time = perf0.get();
|
||||
auto& history = getllar_wait_time[(addr % SPU_LS_SIZE) / 128];
|
||||
|
||||
if (getllar_busy_waiting_switch)
|
||||
{
|
||||
g_fail++;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ok++;
|
||||
}
|
||||
|
||||
if ((g_ok + g_fail) % 200 == 0 && !getllar_busy_waiting_switch)
|
||||
spu_log.trace("SPU wait: count=%d. switch=%d, spin=%d, fail=%d, ok=%d, {%d, %d, %d, %d}", total_wait, getllar_busy_waiting_switch, getllar_spin_count, +g_fail, +g_ok, old_stats[0], old_stats[1], old_stats[2], old_stats[3] );
|
||||
getllar_busy_waiting_switch =
|
||||
evaluate_spin_optimization({ history.data(), history.size() }, getllar_evaluate_time, g_cfg.core.spu_getllar_busy_waiting_percentage);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5004,7 +5110,7 @@ bool spu_thread::process_mfc_cmd()
|
||||
|
||||
if (group->spurs_running == max_run - 1)
|
||||
{
|
||||
// Try to let another thread slip in and take over execution
|
||||
// Try to let another thread slip in and take over execution
|
||||
thread_ctrl::wait_for(300);
|
||||
|
||||
// Update value
|
||||
@@ -5029,7 +5135,7 @@ bool spu_thread::process_mfc_cmd()
|
||||
if (spurs_last_task_timestamp)
|
||||
{
|
||||
const u64 avg_entry = spurs_average_task_duration / spurs_task_count_to_calculate;
|
||||
spurs_average_task_duration -= avg_entry;
|
||||
spurs_average_task_duration -= avg_entry;
|
||||
spurs_average_task_duration += std::min<u64>(45'000, current - spurs_last_task_timestamp);
|
||||
spu_log.trace("duration: %d, avg=%d", current - spurs_last_task_timestamp, spurs_average_task_duration / spurs_task_count_to_calculate);
|
||||
spurs_last_task_timestamp = 0;
|
||||
@@ -5050,7 +5156,7 @@ bool spu_thread::process_mfc_cmd()
|
||||
}
|
||||
|
||||
max_run = group->max_run;
|
||||
|
||||
|
||||
prev_running = group->spurs_running.fetch_op([max_run](u32& x)
|
||||
{
|
||||
if (x < max_run)
|
||||
@@ -5115,7 +5221,7 @@ bool spu_thread::process_mfc_cmd()
|
||||
if (spurs_last_task_timestamp)
|
||||
{
|
||||
const u64 avg_entry = spurs_average_task_duration / spurs_task_count_to_calculate;
|
||||
spurs_average_task_duration -= avg_entry;
|
||||
spurs_average_task_duration -= avg_entry;
|
||||
spurs_average_task_duration += std::min<u64>(45'000, current - spurs_last_task_timestamp);
|
||||
spu_log.trace("duration: %d, avg=%d", current - spurs_last_task_timestamp, spurs_average_task_duration / spurs_task_count_to_calculate);
|
||||
spurs_last_task_timestamp = 0;
|
||||
@@ -5937,7 +6043,52 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||
return true;
|
||||
};
|
||||
|
||||
for (; !events.count; events = get_events(mask1 & ~SPU_EVENT_LR, true, true))
|
||||
const bool is_LR_wait = raddr && mask1 & SPU_EVENT_LR;
|
||||
|
||||
auto& history = eventstat_wait_time[(raddr % SPU_LS_SIZE) / 128];
|
||||
|
||||
if (is_LR_wait)
|
||||
{
|
||||
const u32 spu_group_restart = group ? +group->stop_count : 0;
|
||||
|
||||
// Check if waiting session changed
|
||||
if (eventstat_raddr != raddr || eventstat_block_counter != block_counter || last_getllar != eventstat_getllar || eventstat_spu_group_restart != spu_group_restart)
|
||||
{
|
||||
eventstat_raddr = raddr;
|
||||
eventstat_block_counter = block_counter;
|
||||
eventstat_getllar = last_getllar;
|
||||
eventstat_spu_group_restart = spu_group_restart;
|
||||
eventstat_spin_count = 0;
|
||||
eventstat_evaluate_time = get_system_time();
|
||||
eventstat_busy_waiting_switch = umax;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8& val = history.front();
|
||||
val = static_cast<u8>(std::min<u32>(val + 1, u8{umax}));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eventstat_busy_waiting_switch = 0;
|
||||
eventstat_raddr = 0;
|
||||
eventstat_block_counter = 0;
|
||||
}
|
||||
|
||||
if (eventstat_busy_waiting_switch == umax)
|
||||
{
|
||||
bool value = false;
|
||||
|
||||
if (is_LR_wait && g_cfg.core.spu_reservation_busy_waiting_enabled)
|
||||
{
|
||||
// Make single-threaded groups inclined for busy-waiting
|
||||
value = evaluate_spin_optimization({ history.data(), history.size() }, eventstat_evaluate_time, g_cfg.core.spu_reservation_busy_waiting_percentage, group && group->max_num == 1) != 0;
|
||||
}
|
||||
|
||||
eventstat_busy_waiting_switch = value ? 1 : 0;
|
||||
}
|
||||
|
||||
for (bool is_first = true; !events.count; events = get_events(mask1 & ~SPU_EVENT_LR, true, true), is_first = false)
|
||||
{
|
||||
const auto old = +state;
|
||||
|
||||
@@ -5952,7 +6103,7 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||
}
|
||||
|
||||
// Optimized check
|
||||
if (raddr && mask1 & SPU_EVENT_LR)
|
||||
if (is_LR_wait)
|
||||
{
|
||||
if (cache_line_waiter_index == umax)
|
||||
{
|
||||
@@ -5983,6 +6134,59 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||
set_events(SPU_EVENT_LR);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_first && eventstat_busy_waiting_switch != 1)
|
||||
{
|
||||
u8& val = history.front();
|
||||
val = static_cast<u8>(std::min<u32>(val + 1, u8{umax}));
|
||||
}
|
||||
}
|
||||
|
||||
if (eventstat_busy_waiting_switch == 1)
|
||||
{
|
||||
// Don't be stubborn, force operating sleep if too much time has passed
|
||||
const u64 time_since = get_system_time() - eventstat_evaluate_time;
|
||||
|
||||
if (time_since >= (utils::get_thread_count() >= 9 ? 50'000 : 3000))
|
||||
{
|
||||
spu_log.trace("SPU RdEventStat wait for 0x%x failed", raddr);
|
||||
history.front() = 2;
|
||||
eventstat_busy_waiting_switch = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined(ARCH_X64)
|
||||
if (utils::has_um_wait())
|
||||
{
|
||||
if (utils::has_waitpkg())
|
||||
{
|
||||
__tpause(std::min<u32>(eventstat_spin_count, 10) * 500, 0x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct check_wait_t
|
||||
{
|
||||
static FORCE_INLINE bool needs_wait(u64 rtime, const atomic_t<u64>& mem_rtime) noexcept
|
||||
{
|
||||
return rtime == mem_rtime;
|
||||
}
|
||||
};
|
||||
|
||||
// Provide the first X64 cache line of the reservation to be tracked
|
||||
__mwaitx<check_wait_t>(std::min<u32>(eventstat_spin_count, 17) * 500, 0xf0, std::addressof(*resrv_mem), +rtime, vm::reservation_acquire(raddr));
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
busy_wait(300);
|
||||
}
|
||||
|
||||
// Check other reservations in other threads
|
||||
lv2_obj::notify_all();
|
||||
|
||||
eventstat_spin_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (raddr && (mask1 & ~SPU_EVENT_TM) == SPU_EVENT_LR)
|
||||
|
||||
@@ -638,6 +638,7 @@ public:
|
||||
virtual ~spu_thread() override;
|
||||
void cleanup();
|
||||
void cpu_init();
|
||||
void init_spu_decoder();
|
||||
|
||||
static const u32 id_base = 0x02000000; // TODO (used to determine thread type)
|
||||
static const u32 id_step = 1;
|
||||
@@ -805,6 +806,14 @@ public:
|
||||
u32 getllar_busy_waiting_switch = umax; // umax means the test needs evaluation, otherwise it's a boolean
|
||||
u64 getllar_evaluate_time = 0;
|
||||
|
||||
u32 eventstat_raddr = 0;
|
||||
u32 eventstat_getllar = 0;
|
||||
u64 eventstat_block_counter = 0;
|
||||
u64 eventstat_spu_group_restart = 0;
|
||||
u64 eventstat_spin_count = 0;
|
||||
u64 eventstat_evaluate_time = 0;
|
||||
u32 eventstat_busy_waiting_switch = 0;
|
||||
|
||||
std::vector<mfc_cmd_dump> mfc_history;
|
||||
u64 mfc_dump_idx = 0;
|
||||
static constexpr u32 max_mfc_dump_idx = 4096;
|
||||
@@ -828,6 +837,7 @@ public:
|
||||
bool stop_flag_removal_protection = false;
|
||||
|
||||
std::array<std::array<u8, 4>, SPU_LS_SIZE / 128> getllar_wait_time{};
|
||||
std::array<std::array<u8, 16>, SPU_LS_SIZE / 128> eventstat_wait_time{};
|
||||
|
||||
void push_snr(u32 number, u32 value);
|
||||
static void do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8* ls);
|
||||
@@ -843,7 +853,7 @@ public:
|
||||
void set_events(u32 bits);
|
||||
void set_interrupt_status(bool enable);
|
||||
bool check_mfc_interrupts(u32 next_pc);
|
||||
static bool is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_addr = 0, bool avoid_dead_code = false); // Only a hint, do not rely on it other than debugging purposes
|
||||
static bool is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_addr = 0, bool avoid_dead_code = false, bool is_range_limited = false); // A hint, do not rely on it for true execution compatibility
|
||||
static std::vector<u32> discover_functions(u32 base_addr, std::span<const u8> ls, bool is_known_addr, u32 /*entry*/);
|
||||
u32 get_ch_count(u32 ch);
|
||||
s64 get_ch_value(u32 ch);
|
||||
|
||||
@@ -2160,7 +2160,7 @@ bool lv2_obj::wait_timeout(u64 usec, ppu_thread* cpu, bool scale, bool is_usleep
|
||||
}
|
||||
|
||||
u64 remaining = usec - passed;
|
||||
#if defined(__linux__)
|
||||
#ifdef __linux__
|
||||
// NOTE: Assumption that timer initialization has succeeded
|
||||
constexpr u64 host_min_quantum = 10;
|
||||
#else
|
||||
@@ -2178,7 +2178,7 @@ bool lv2_obj::wait_timeout(u64 usec, ppu_thread* cpu, bool scale, bool is_usleep
|
||||
{
|
||||
if (remaining > host_min_quantum)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
#ifdef __linux__
|
||||
// With timerslack set low, Linux is precise for all values above
|
||||
wait_for(remaining);
|
||||
#else
|
||||
@@ -2268,7 +2268,7 @@ void lv2_obj::notify_all() noexcept
|
||||
|
||||
u32 notifies[total_waiters]{};
|
||||
|
||||
// There may be 6 waiters, but checking them all may be performance expensive
|
||||
// There may be 6 waiters, but checking them all may be performance expensive
|
||||
// Instead, check 2 at max, but use the CPU ID index to tell which index to start checking so the work would be distributed across all threads
|
||||
|
||||
atomic_t<u64, 64>* range_lock = nullptr;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "util/serialization.hpp"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
@@ -60,7 +59,6 @@ CellError lv2_cond::on_id_create()
|
||||
if (!mutex)
|
||||
{
|
||||
_mutex = static_cast<shared_ptr<lv2_obj>>(ensure(idm::get_unlocked<lv2_obj, lv2_mutex>(mtx_id)));
|
||||
|
||||
}
|
||||
|
||||
// Defer function
|
||||
@@ -72,7 +70,7 @@ CellError lv2_cond::on_id_create()
|
||||
|
||||
std::function<void(void*)> lv2_cond::load(utils::serial& ar)
|
||||
{
|
||||
return load_func(make_shared<lv2_cond>(ar));
|
||||
return load_func(make_shared<lv2_cond>(stx::exact_t<utils::serial&>(ar)));
|
||||
}
|
||||
|
||||
void lv2_cond::save(utils::serial& ar)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_event.h"
|
||||
@@ -122,7 +120,7 @@ void lv2_config::remove_service_event(u32 id)
|
||||
|
||||
lv2_config_service_event& lv2_config_service_event::operator=(thread_state s) noexcept
|
||||
{
|
||||
if (s == thread_state::finished)
|
||||
if (s == thread_state::destroying_context && !m_destroyed.exchange(true))
|
||||
{
|
||||
if (auto global = g_fxo->try_get<lv2_config>())
|
||||
{
|
||||
@@ -133,6 +131,23 @@ lv2_config_service_event& lv2_config_service_event::operator=(thread_state s) no
|
||||
return *this;
|
||||
}
|
||||
|
||||
lv2_config_service_event::~lv2_config_service_event() noexcept
|
||||
{
|
||||
operator=(thread_state::destroying_context);
|
||||
}
|
||||
|
||||
lv2_config::~lv2_config() noexcept
|
||||
{
|
||||
for (auto& [key, event] : events)
|
||||
{
|
||||
if (event)
|
||||
{
|
||||
// Avoid collision with lv2_config_service_event destructor
|
||||
event->m_destroyed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LV2 Config Service Listener
|
||||
bool lv2_config_service_listener::check_service(const lv2_config_service& service) const
|
||||
{
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include "util/atomic.hpp"
|
||||
#include "util/shared_ptr.hpp"
|
||||
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
|
||||
/*
|
||||
* sys_config is a "subscription-based data storage API"
|
||||
@@ -161,6 +158,8 @@ public:
|
||||
|
||||
return null_ptr;
|
||||
}
|
||||
|
||||
~lv2_config() noexcept;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -276,7 +275,7 @@ public:
|
||||
|
||||
// Utilities
|
||||
usz get_size() const { return sizeof(sys_config_service_event_t)-1 + data.size(); }
|
||||
shared_ptr<lv2_config_service> get_shared_ptr () const { return idm::get_unlocked<lv2_config_service>(idm_id); }
|
||||
shared_ptr<lv2_config_service> get_shared_ptr () const { return stx::make_shared_from_this<lv2_config_service>(this); }
|
||||
u32 get_id() const { return idm_id; }
|
||||
};
|
||||
|
||||
@@ -342,7 +341,7 @@ public:
|
||||
|
||||
// Utilities
|
||||
u32 get_id() const { return idm_id; }
|
||||
shared_ptr<lv2_config_service_listener> get_shared_ptr() const { return idm::get_unlocked<lv2_config_service_listener>(idm_id); }
|
||||
shared_ptr<lv2_config_service_listener> get_shared_ptr() const { return stx::make_shared_from_this<lv2_config_service_listener>(this); }
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -360,6 +359,10 @@ class lv2_config_service_event
|
||||
return g_fxo->get<service_event_id>().next_id++;
|
||||
}
|
||||
|
||||
atomic_t<bool> m_destroyed = false;
|
||||
|
||||
friend class lv2_config;
|
||||
|
||||
public:
|
||||
const u32 id;
|
||||
|
||||
@@ -391,8 +394,7 @@ public:
|
||||
|
||||
// Destructor
|
||||
lv2_config_service_event& operator=(thread_state s) noexcept;
|
||||
|
||||
~lv2_config_service_event() noexcept = default;
|
||||
~lv2_config_service_event() noexcept;
|
||||
|
||||
// Notify queue that this event exists
|
||||
bool notify() const;
|
||||
|
||||
@@ -37,8 +37,8 @@ lv2_event_queue::lv2_event_queue(utils::serial& ar) noexcept
|
||||
|
||||
std::function<void(void*)> lv2_event_queue::load(utils::serial& ar)
|
||||
{
|
||||
auto queue = make_shared<lv2_event_queue>(ar);
|
||||
return [ptr = lv2_obj::load(queue->key, queue)](void* storage) { *static_cast<shared_ptr<lv2_obj>*>(storage) = ptr; };
|
||||
auto queue = make_shared<lv2_event_queue>(stx::exact_t<utils::serial&>(ar));
|
||||
return [ptr = lv2_obj::load(queue->key, queue)](void* storage) { *static_cast<atomic_ptr<lv2_obj>*>(storage) = ptr; };
|
||||
}
|
||||
|
||||
void lv2_event_queue::save(utils::serial& ar)
|
||||
@@ -420,10 +420,8 @@ error_code sys_event_queue_tryreceive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sy
|
||||
while (count < size && !queue->events.empty())
|
||||
{
|
||||
auto& dest = events[count++];
|
||||
const auto event = queue->events.front();
|
||||
std::tie(dest.source, dest.data1, dest.data2, dest.data3) = queue->events.front();
|
||||
queue->events.pop_front();
|
||||
|
||||
std::tie(dest.source, dest.data1, dest.data2, dest.data3) = event;
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
#include "sys_event_flag.h"
|
||||
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
||||
LOG_CHANNEL(sys_event_flag);
|
||||
@@ -24,7 +21,7 @@ lv2_event_flag::lv2_event_flag(utils::serial& ar)
|
||||
|
||||
std::function<void(void*)> lv2_event_flag::load(utils::serial& ar)
|
||||
{
|
||||
return load_func(make_shared<lv2_event_flag>(ar));
|
||||
return load_func(make_shared<lv2_event_flag>(stx::exact_t<utils::serial&>(ar)));
|
||||
}
|
||||
|
||||
void lv2_event_flag::save(utils::serial& ar)
|
||||
|
||||
@@ -79,7 +79,7 @@ void fmt_class_string<lv2_file>::format(std::string& out, u64 arg)
|
||||
const usz pos = file.file ? file.file.pos() : umax;
|
||||
const usz size = file.file ? file.file.size() : umax;
|
||||
|
||||
fmt::append(out, u8"%s, “%sâ€, Mode: 0x%x, Flags: 0x%x, Pos/Size: %s/%s (0x%x/0x%x)", file.type, file.name.data(), file.mode, file.flags, get_size(pos), get_size(size), pos, size);
|
||||
fmt::append(out, u8"%s, '%s', Mode: 0x%x, Flags: 0x%x, Pos/Size: %s/%s (0x%x/0x%x)", file.type, file.name.data(), file.mode, file.flags, get_size(pos), get_size(size), pos, size);
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -87,7 +87,7 @@ void fmt_class_string<lv2_dir>::format(std::string& out, u64 arg)
|
||||
{
|
||||
const auto& dir = get_object(arg);
|
||||
|
||||
fmt::append(out, u8"Directory, “%sâ€, Entries: %u/%u", dir.name.data(), std::min<u64>(dir.pos, dir.entries.size()), dir.entries.size());
|
||||
fmt::append(out, u8"Directory, '%s', Entries: %u/%u", dir.name.data(), std::min<u64>(dir.pos, dir.entries.size()), dir.entries.size());
|
||||
}
|
||||
|
||||
bool has_fs_write_rights(std::string_view vpath)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "util/vm.hpp"
|
||||
#include "util/asm.hpp"
|
||||
|
||||
LOG_CHANNEL(sys_memory);
|
||||
@@ -33,7 +32,7 @@ std::function<void(void*)> lv2_memory_container::load(utils::serial& ar)
|
||||
// Use idm::last_id() only for the instances at IDM
|
||||
return [ptr = make_shared<lv2_memory_container>(stx::exact_t<utils::serial&>(ar), true)](void* storage)
|
||||
{
|
||||
*static_cast<shared_ptr<lv2_memory_container>*>(storage) = ptr;
|
||||
*static_cast<atomic_ptr<lv2_memory_container>*>(storage) = ptr;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -36,12 +36,8 @@ lv2_memory::lv2_memory(u32 size, u32 align, u64 flags, u64 key, bool pshared, lv
|
||||
, key(key)
|
||||
, pshared(pshared)
|
||||
, ct(ct)
|
||||
, shm(std::make_shared<utils::shm>(size, 1 /* shareable flag */))
|
||||
, shm(null_ptr)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
// Optimization that's useless on Windows :puke:
|
||||
utils::memory_lock(shm->map_self(), size);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv2_memory::lv2_memory(utils::serial& ar)
|
||||
@@ -51,23 +47,17 @@ lv2_memory::lv2_memory(utils::serial& ar)
|
||||
, key(ar)
|
||||
, pshared(ar)
|
||||
, ct(lv2_memory_container::search(ar.pop<u32>()))
|
||||
, shm([&](u32 addr)
|
||||
, shm([&](u32 addr) -> shared_ptr<std::shared_ptr<utils::shm>>
|
||||
{
|
||||
if (addr)
|
||||
{
|
||||
return ensure(vm::get(vm::any, addr)->peek(addr).second);
|
||||
return make_single_value(ensure(vm::get(vm::any, addr)->peek(addr).second));
|
||||
}
|
||||
|
||||
const auto _shm = std::make_shared<utils::shm>(size, 1);
|
||||
ar(std::span(_shm->map_self(), size));
|
||||
return _shm;
|
||||
return null_ptr;
|
||||
}(ar.pop<u32>()))
|
||||
, counter(ar)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
// Optimization that's useless on Windows :puke:
|
||||
utils::memory_lock(shm->map_self(), size);
|
||||
#endif
|
||||
}
|
||||
|
||||
CellError lv2_memory::on_id_create()
|
||||
@@ -84,7 +74,7 @@ CellError lv2_memory::on_id_create()
|
||||
|
||||
std::function<void(void*)> lv2_memory::load(utils::serial& ar)
|
||||
{
|
||||
auto mem = make_shared<lv2_memory>(ar);
|
||||
auto mem = make_shared<lv2_memory>(stx::exact_t<utils::serial&>(ar));
|
||||
mem->exists++; // Disable on_id_create()
|
||||
auto func = load_func(mem, +mem->pshared);
|
||||
mem->exists--;
|
||||
@@ -96,13 +86,7 @@ void lv2_memory::save(utils::serial& ar)
|
||||
USING_SERIALIZATION_VERSION(lv2_memory);
|
||||
|
||||
ar(size, align, flags, key, pshared, ct->id);
|
||||
ar(counter ? vm::get_shm_addr(shm) : 0);
|
||||
|
||||
if (!counter)
|
||||
{
|
||||
ar(std::span(shm->map_self(), size));
|
||||
}
|
||||
|
||||
ar(counter ? vm::get_shm_addr(*shm.load()) : 0);
|
||||
ar(counter);
|
||||
}
|
||||
|
||||
@@ -645,6 +629,22 @@ error_code sys_mmapper_map_shared_memory(ppu_thread& ppu, u32 addr, u32 mem_id,
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
for (stx::shared_ptr<std::shared_ptr<utils::shm>> to_insert, null; !mem.shm;)
|
||||
{
|
||||
// Insert atomically the memory handle (laziliy allocated)
|
||||
if (!to_insert)
|
||||
{
|
||||
to_insert = make_single_value(std::make_shared<utils::shm>(mem.size, 1 /* shareable flag */));
|
||||
}
|
||||
|
||||
null.reset();
|
||||
|
||||
if (mem.shm.compare_exchange(null, to_insert))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mem.counter++;
|
||||
return {};
|
||||
});
|
||||
@@ -659,7 +659,9 @@ error_code sys_mmapper_map_shared_memory(ppu_thread& ppu, u32 addr, u32 mem_id,
|
||||
return mem.ret;
|
||||
}
|
||||
|
||||
if (!area->falloc(addr, mem->size, &mem->shm, mem->align == 0x10000 ? SYS_MEMORY_PAGE_SIZE_64K : SYS_MEMORY_PAGE_SIZE_1M))
|
||||
auto shm_ptr = *mem->shm.load();
|
||||
|
||||
if (!area->falloc(addr, mem->size, &shm_ptr, mem->align == 0x10000 ? SYS_MEMORY_PAGE_SIZE_64K : SYS_MEMORY_PAGE_SIZE_1M))
|
||||
{
|
||||
mem->counter--;
|
||||
|
||||
@@ -697,6 +699,22 @@ error_code sys_mmapper_search_and_map(ppu_thread& ppu, u32 start_addr, u32 mem_i
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
for (stx::shared_ptr<std::shared_ptr<utils::shm>> to_insert, null; !mem.shm;)
|
||||
{
|
||||
// Insert atomically the memory handle (laziliy allocated)
|
||||
if (!to_insert)
|
||||
{
|
||||
to_insert = make_single_value(std::make_shared<utils::shm>(mem.size, 1 /* shareable flag */));
|
||||
}
|
||||
|
||||
null.reset();
|
||||
|
||||
if (mem.shm.compare_exchange(null, to_insert))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mem.counter++;
|
||||
return {};
|
||||
});
|
||||
@@ -711,7 +729,9 @@ error_code sys_mmapper_search_and_map(ppu_thread& ppu, u32 start_addr, u32 mem_i
|
||||
return mem.ret;
|
||||
}
|
||||
|
||||
const u32 addr = area->alloc(mem->size, &mem->shm, mem->align, mem->align == 0x10000 ? SYS_MEMORY_PAGE_SIZE_64K : SYS_MEMORY_PAGE_SIZE_1M);
|
||||
auto shm_ptr = *mem->shm.load();
|
||||
|
||||
const u32 addr = area->alloc(mem->size, &shm_ptr, mem->align, mem->align == 0x10000 ? SYS_MEMORY_PAGE_SIZE_64K : SYS_MEMORY_PAGE_SIZE_1M);
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
@@ -755,7 +775,7 @@ error_code sys_mmapper_unmap_shared_memory(ppu_thread& ppu, u32 addr, vm::ptr<u3
|
||||
|
||||
const auto mem = idm::select<lv2_obj, lv2_memory>([&](u32 id, lv2_memory& mem) -> u32
|
||||
{
|
||||
if (mem.shm.get() == shm.second.get())
|
||||
if (auto shm0 = mem.shm.load(); shm0 && shm0->get() == shm.second.get())
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
|
||||
#include "util/shared_ptr.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct lv2_memory_container;
|
||||
@@ -24,7 +26,7 @@ struct lv2_memory : lv2_obj
|
||||
const u64 key; // IPC key
|
||||
const bool pshared; // Process shared flag
|
||||
lv2_memory_container* const ct; // Associated memory container
|
||||
const std::shared_ptr<utils::shm> shm;
|
||||
atomic_ptr<std::shared_ptr<utils::shm>> shm;
|
||||
|
||||
atomic_t<u32> counter{0};
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
@@ -27,7 +26,7 @@ lv2_mutex::lv2_mutex(utils::serial& ar)
|
||||
|
||||
std::function<void(void*)> lv2_mutex::load(utils::serial& ar)
|
||||
{
|
||||
return load_func(make_shared<lv2_mutex>(ar));
|
||||
return load_func(make_shared<lv2_mutex>(stx::exact_t<utils::serial&>(ar)));
|
||||
}
|
||||
|
||||
void lv2_mutex::save(utils::serial& ar)
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -24,7 +23,6 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#ifdef __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
@@ -33,9 +31,7 @@
|
||||
|
||||
#include "Emu/NP/np_handler.h"
|
||||
#include "Emu/NP/np_helpers.h"
|
||||
#include "Emu/NP/np_dnshook.h"
|
||||
|
||||
#include <chrono>
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include <shared_mutex>
|
||||
|
||||
#include "sys_net/network_context.h"
|
||||
@@ -293,7 +289,7 @@ std::function<void(void*)> lv2_socket::load(utils::serial& ar)
|
||||
sock_lv2->bind(sock_lv2->last_bound_addr);
|
||||
}
|
||||
|
||||
return [ptr = sock_lv2](void* storage) { *static_cast<shared_ptr<lv2_socket>*>(storage) = ptr; };;
|
||||
return [ptr = sock_lv2](void* storage) { *static_cast<atomic_ptr<lv2_socket>*>(storage) = ptr; };;
|
||||
}
|
||||
|
||||
void lv2_socket::save(utils::serial& ar, bool save_only_this_class)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "Emu/Cell/PPUAnalyser.h"
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#include "sys_sync.h"
|
||||
#include <vector>
|
||||
|
||||
struct lv2_overlay final : ppu_module<lv2_obj>
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "sys_memory.h"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
#include <thread>
|
||||
|
||||
LOG_CHANNEL(sys_ppu_thread);
|
||||
|
||||
|
||||
@@ -271,7 +271,7 @@ error_code _sys_process_get_paramsfo(vm::ptr<char> buffer)
|
||||
{
|
||||
sys_process.warning("_sys_process_get_paramsfo(buffer=0x%x)", buffer);
|
||||
|
||||
if (!Emu.GetTitleID().length())
|
||||
if (Emu.GetTitleID().empty())
|
||||
{
|
||||
return CELL_ENOENT;
|
||||
}
|
||||
@@ -498,6 +498,9 @@ void lv2_exitspawn(ppu_thread& ppu, std::vector<std::string>& argv, std::vector<
|
||||
};
|
||||
|
||||
signal_system_cache_can_stay();
|
||||
|
||||
// Make sure we keep the game window opened
|
||||
//Emu.SetContinuousMode(true);
|
||||
Emu.Kill(false);
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "sys_semaphore.h"
|
||||
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
|
||||
@@ -553,7 +553,7 @@ error_code sys_ss_individual_info_manager(u64 pkg_id, u64 a2, vm::ptr<u64> out_s
|
||||
case 0x17002:
|
||||
{
|
||||
// TODO
|
||||
vm::write<u64>(a5, a4); // Write back size of buffer
|
||||
vm::write<u64>(static_cast<u32>(a5), a4); // Write back size of buffer
|
||||
break;
|
||||
}
|
||||
// Get EID size
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utilities/mutex.h"
|
||||
#include "Utilities/sema.h"
|
||||
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include "Emu/Memory/vm_reservation.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include "util/shared_ptr.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
||||
// attr_protocol (waiting scheduling policy)
|
||||
enum lv2_protocol : u8
|
||||
{
|
||||
@@ -449,7 +444,7 @@ public:
|
||||
static std::function<void(void*)> load_func(shared_ptr<T> make, u64 pshared = umax)
|
||||
{
|
||||
const u64 key = make->key;
|
||||
return [ptr = load<T>(key, make, pshared)](void* storage) { *static_cast<shared_ptr<Storage>*>(storage) = ptr; };
|
||||
return [ptr = load<T>(key, make, pshared)](void* storage) { *static_cast<atomic_ptr<Storage>*>(storage) = ptr; };
|
||||
}
|
||||
|
||||
static bool wait_timeout(u64 usec, ppu_thread* cpu = {}, bool scale = true, bool is_usleep = false);
|
||||
|
||||
@@ -378,7 +378,7 @@ error_code sys_time_get_current_time(vm::ptr<s64> sec, vm::ptr<s64> nsec)
|
||||
if (g_cfg.core.clocks_scale == 100)
|
||||
{
|
||||
// get the seconds from the system clock, and add the console time offset (which might be negative)
|
||||
*sec = ts.tv_sec;// + g_cfg.sys.console_time_offset;
|
||||
*sec = ts.tv_sec + g_cfg.sys.console_time_offset;
|
||||
|
||||
if (!nsec)
|
||||
{
|
||||
@@ -410,7 +410,7 @@ error_code sys_time_get_current_time(vm::ptr<s64> sec, vm::ptr<s64> nsec)
|
||||
tv_nsec = stv_nsec + (tv_nsec * g_cfg.core.clocks_scale / 100);
|
||||
|
||||
// Scale seconds and add from nanoseconds / 1'000'000'000, and add the console time offset (which might be negative)
|
||||
*sec = stv_sec + (tv_sec * g_cfg.core.clocks_scale / 100u) + (tv_nsec / 1000000000ull);// + g_cfg.sys.console_time_offset;
|
||||
*sec = stv_sec + (tv_sec * g_cfg.core.clocks_scale / 100u) + (tv_nsec / 1000000000ull) + g_cfg.sys.console_time_offset;
|
||||
|
||||
if (!nsec)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "sys_event.h"
|
||||
|
||||
#include "Utilities/Thread.h"
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include "Emu/Memory/vm_locking.h"
|
||||
|
||||
sys_vm_t::sys_vm_t(u32 _addr, u32 vsize, lv2_memory_container* ct, u32 psize)
|
||||
: ct(ct)
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace vm
|
||||
extern u8* const g_free_addr;
|
||||
extern u8 g_reservations[65536 / 128 * 64];
|
||||
|
||||
static constexpr u64 g_exec_addr_seg_offset = 0x2'0000'0000ULL;
|
||||
|
||||
struct writer_lock;
|
||||
|
||||
enum memory_location_t : uint
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user