Compare commits

...

9 commits

Author SHA1 Message Date
Elad b2eeabe1f2
Merge cbdef37228 into 67f7119717 2025-12-04 18:58:40 +01:00
Elad 67f7119717
Make RSX FIFO Atomic fetching default (#17810)
Some checks failed
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux-aarch64.sh, gcc, rpcs3/rpcs3-ci-jammy-aarch64:1.7, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux.sh, gcc, rpcs3/rpcs3-ci-jammy:1.7, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1, rpcs3/rpcs3-binaries-linux-arm64, /rpcs3/.ci/build-linux-aarch64.sh, clang, rpcs3/rpcs3-ci-jammy-aarch64:1.7, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (d812f1254a1157c80fd402f94446310560f54e5f, rpcs3/rpcs3-binaries-linux, /rpcs3/.ci/build-linux.sh, clang, rpcs3/rpcs3-ci-jammy:1.7, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (51ae32f468089a8169aaf1567de355ff4a3e0842, rpcs3/rpcs3-binaries-mac, .ci/build-mac.sh, Intel) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (8e21bdbc40711a3fccd18fbf17b742348b0f4281, rpcs3/rpcs3-binaries-mac-arm64, .ci/build-mac-arm64.sh, Apple Silicon) (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Build RPCS3 / RPCS3 Windows Clang (win64, clang, clang64) (push) Waiting to run
Build RPCS3 / RPCS3 FreeBSD (push) Waiting to run
Generate Translation Template / Generate Translation Template (push) Has been cancelled
2025-12-04 18:17:39 +02:00
Megamouse 133b19f205 Update Qt for macOs to 6.10.1
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux-aarch64.sh, gcc, rpcs3/rpcs3-ci-jammy-aarch64:1.7, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux.sh, gcc, rpcs3/rpcs3-ci-jammy:1.7, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1, rpcs3/rpcs3-binaries-linux-arm64, /rpcs3/.ci/build-linux-aarch64.sh, clang, rpcs3/rpcs3-ci-jammy-aarch64:1.7, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (d812f1254a1157c80fd402f94446310560f54e5f, rpcs3/rpcs3-binaries-linux, /rpcs3/.ci/build-linux.sh, clang, rpcs3/rpcs3-ci-jammy:1.7, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (51ae32f468089a8169aaf1567de355ff4a3e0842, rpcs3/rpcs3-binaries-mac, .ci/build-mac.sh, Intel) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (8e21bdbc40711a3fccd18fbf17b742348b0f4281, rpcs3/rpcs3-binaries-mac-arm64, .ci/build-mac-arm64.sh, Apple Silicon) (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Build RPCS3 / RPCS3 Windows Clang (win64, clang, clang64) (push) Waiting to run
Build RPCS3 / RPCS3 FreeBSD (push) Waiting to run
2025-12-03 22:54:59 +01:00
Megamouse fce393024a Update Qt for macOs to 6.9.3 2025-12-03 22:54:59 +01:00
Megamouse 7d3cf831d5 Qt/macOS: Fix GUI freezes on Qt 6.8+ 2025-12-03 22:54:59 +01:00
Megamouse dc27047ed4 Qt: fix game list refresh order when changing the language
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux-aarch64.sh, gcc, rpcs3/rpcs3-ci-jammy-aarch64:1.7, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux.sh, gcc, rpcs3/rpcs3-ci-jammy:1.7, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1, rpcs3/rpcs3-binaries-linux-arm64, /rpcs3/.ci/build-linux-aarch64.sh, clang, rpcs3/rpcs3-ci-jammy-aarch64:1.7, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (d812f1254a1157c80fd402f94446310560f54e5f, rpcs3/rpcs3-binaries-linux, /rpcs3/.ci/build-linux.sh, clang, rpcs3/rpcs3-ci-jammy:1.7, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (51ae32f468089a8169aaf1567de355ff4a3e0842, rpcs3/rpcs3-binaries-mac, .ci/build-mac.sh, Intel) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (8e21bdbc40711a3fccd18fbf17b742348b0f4281, rpcs3/rpcs3-binaries-mac-arm64, .ci/build-mac-arm64.sh, Apple Silicon) (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Build RPCS3 / RPCS3 Windows Clang (win64, clang, clang64) (push) Waiting to run
Build RPCS3 / RPCS3 FreeBSD (push) Waiting to run
2025-12-03 21:17:46 +01:00
Megamouse b9a9c1af07 Qt: revert setting UserRole. this doesn't seem to have been the culprit for multiselection 2025-12-03 21:17:46 +01:00
Elad cbdef37228 SaveStates: Support HLE message dialogs 2025-01-30 13:53:37 +02:00
Elad 545e971ba2 SaveStates: Support relocatable HLE code 2025-01-30 13:53:15 +02:00
16 changed files with 227 additions and 83 deletions

View file

@ -38,17 +38,14 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
git clone https://github.com/engnr/qt-downloader.git git clone https://github.com/engnr/qt-downloader.git
cd qt-downloader cd qt-downloader
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597 git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
# nested Qt 6.10.1 URL workaround sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
# archived Qt 6.7.3 URL workaround
sed -i '' "s/official_releases/archive/g" qt-downloader
cd "/tmp/Qt" cd "/tmp/Qt"
"$BREW_PATH/bin/pipenv" run pip3 uninstall py7zr requests semantic_version lxml "$BREW_PATH/bin/pipenv" run pip3 uninstall py7zr requests semantic_version lxml
"$BREW_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml --no-cache "$BREW_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml --no-cache
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64" mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.10.1 workaround sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader"
"$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64" "$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats -o "$QT_VER/clang_64"
fi fi
cd "$WORKDIR" cd "$WORKDIR"

View file

@ -38,16 +38,13 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
git clone https://github.com/engnr/qt-downloader.git git clone https://github.com/engnr/qt-downloader.git
cd qt-downloader cd qt-downloader
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597 git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
# nested Qt 6.10.1 URL workaround sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
# archived Qt 6.7.3 URL workaround
sed -i '' "s/official_releases/archive/g" qt-downloader
cd "/tmp/Qt" cd "/tmp/Qt"
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run pip3 install py7zr requests semantic_version lxml "/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run pip3 install py7zr requests semantic_version lxml
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64" mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.10.1 workaround sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader"
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64" "/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats -o "$QT_VER/clang_64"
fi fi
cd "$WORKDIR" cd "$WORKDIR"

View file

@ -134,7 +134,7 @@ jobs:
runs-on: macos-14 runs-on: macos-14
env: env:
CCACHE_DIR: /tmp/ccache_dir CCACHE_DIR: /tmp/ccache_dir
QT_VER: '6.7.3' QT_VER: '6.10.1'
QT_VER_MAIN: '6' QT_VER_MAIN: '6'
LLVM_COMPILER_VER: '21' LLVM_COMPILER_VER: '21'
RELEASE_MESSAGE: ../GitHubReleaseMessage.txt RELEASE_MESSAGE: ../GitHubReleaseMessage.txt

View file

@ -158,13 +158,64 @@ struct msg_dlg_thread_info
using msg_dlg_thread = named_thread<msg_dlg_thread_info>; using msg_dlg_thread = named_thread<msg_dlg_thread_info>;
// Forward decleration for opened_dialog_context
error_code open_msg_dialog(bool is_blocking, u32 type, std::string msg_string, msg_dialog_source source, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam, s32* return_code);
struct opened_dialog_context
{
bool is_opened = false;
u32 type{};
std::string msg_string;
msg_dialog_source source{};
vm::ptr<CellMsgDialogCallback> callback{};
vm::ptr<void> userData{};
vm::ptr<void> extParam{};
SAVESTATE_INIT_POS(54);
opened_dialog_context(const opened_dialog_context&) = delete;
opened_dialog_context& operator=(const opened_dialog_context&) = delete;
opened_dialog_context() noexcept
{
g_fxo->need<msg_dlg_thread>();
}
opened_dialog_context(utils::serial& ar) noexcept
: opened_dialog_context()
{
save(ar);
if (is_opened)
{
g_fxo->get<msg_dlg_thread>().wait_until = ar.pop<u64>();
Emu.PostponeInitCode([=]()
{
ensure(open_msg_dialog(false, type, msg_string, source, callback, userData, extParam, nullptr) == CELL_OK);
});
}
}
void save(utils::serial& ar)
{
ar(is_opened);
if (!is_opened)
{
return;
}
ar(type, msg_string, source, callback, userData, extParam, +g_fxo->get<msg_dlg_thread>().wait_until);
}
};
// forward declaration for open_msg_dialog // forward declaration for open_msg_dialog
error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam); error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam);
// wrapper to call for other hle dialogs error_code open_msg_dialog(bool is_blocking, u32 type, std::string msg_string, msg_dialog_source source, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam, s32* return_code)
error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString, msg_dialog_source source, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam, s32* return_code)
{ {
cellSysutil.notice("open_msg_dialog(is_blocking=%d, type=0x%x, msgString=%s, source=%s, callback=*0x%x, userData=*0x%x, extParam=*0x%x, return_code=*0x%x)", is_blocking, type, msgString, source, callback, userData, extParam, return_code); cellSysutil.notice("open_msg_dialog(is_blocking=%d, type=0x%x, msg_string=%s, source=%s, callback=*0x%x, userData=*0x%x, extParam=*0x%x, return_code=*0x%x)", is_blocking, type, msg_string, source, callback, userData, extParam, return_code);
const MsgDialogType _type{ type }; const MsgDialogType _type{ type };
@ -173,6 +224,9 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
*return_code = CELL_MSGDIALOG_BUTTON_NONE; *return_code = CELL_MSGDIALOG_BUTTON_NONE;
} }
const auto ppu = cpu_thread::get_current<ppu_thread>();
const bool loaded_from_savestate = ppu && ppu->loaded_from_savestate;
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>()) if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())
{ {
if (manager->get<rsx::overlays::message_dialog>()) if (manager->get<rsx::overlays::message_dialog>())
@ -180,14 +234,29 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
return CELL_SYSUTIL_ERROR_BUSY; return CELL_SYSUTIL_ERROR_BUSY;
} }
if (s32 ret = sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0); ret < 0) if (s32 ret = loaded_from_savestate ? 0 : sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0); ret < 0)
{ {
return CellSysutilError{ret + 0u}; return CellSysutilError{ret + 0u};
} }
const auto notify = std::make_shared<atomic_t<u32>>(0); const auto notify = std::make_shared<atomic_t<u32>>(0);
const auto res = manager->create<rsx::overlays::message_dialog>()->show(is_blocking, msgString.get_ptr(), _type, source, [callback, userData, &return_code, is_blocking, notify](s32 status) auto dlg = manager->create<rsx::overlays::message_dialog>();
if (!is_blocking)
{
auto& ctxt = g_fxo->get<opened_dialog_context>();
ctxt.is_opened = true;
ctxt.type = type;
ctxt.msg_string = msg_string;
ctxt.source = source;
ctxt.callback = callback;
ctxt.userData = userData;
ctxt.extParam = extParam;
}
const auto res = dlg->show(is_blocking, msg_string, _type, source, [callback, userData, &return_code, is_blocking, notify](s32 status)
{ {
if (is_blocking && return_code) if (is_blocking && return_code)
{ {
@ -210,12 +279,28 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
*notify = 1; *notify = 1;
notify->notify_one(); notify->notify_one();
} }
auto& ctxt = g_fxo->get<opened_dialog_context>();
ctxt.is_opened = false;
}); });
// Wait for on_close // Wait for on_close
while (is_blocking && !Emu.IsStopped() && !*notify) while (!*notify)
{ {
notify->wait(false, atomic_wait_timeout{1'000'000}); if (ppu)
{
if (ppu->is_stopped())
{
ppu->state += cpu_flag::again;
return {};
}
}
else if (Emu.IsStopped())
{
return {};
}
thread_ctrl::wait_on(*notify, 0);
} }
return res; return res;
@ -228,15 +313,30 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
return CELL_SYSUTIL_ERROR_BUSY; return CELL_SYSUTIL_ERROR_BUSY;
} }
if (s32 ret = sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0); ret < 0) if (s32 ret = loaded_from_savestate ? 0 : sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0); ret < 0)
{ {
return CellSysutilError{ret + 0u}; return CellSysutilError{ret + 0u};
} }
if (!is_blocking)
{
auto& ctxt = g_fxo->get<opened_dialog_context>();
ctxt.is_opened = true;
ctxt.type = type;
ctxt.msg_string = msg_string;
ctxt.source = source;
ctxt.callback = callback;
ctxt.userData = userData;
ctxt.extParam = extParam;
}
dlg->type = _type; dlg->type = _type;
dlg->source = source; dlg->source = source;
dlg->on_close = [callback, userData, is_blocking, &return_code, wptr = std::weak_ptr<MsgDialogBase>(dlg)](s32 status) const auto notify = std::make_shared<atomic_t<u32>>(0);
dlg->on_close = [notify, callback, userData, is_blocking, &return_code, wptr = std::weak_ptr<MsgDialogBase>(dlg)](s32 status)
{ {
if (is_blocking && return_code) if (is_blocking && return_code)
{ {
@ -245,7 +345,9 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
const auto dlg = wptr.lock(); const auto dlg = wptr.lock();
if (dlg && dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close)) const bool closed = dlg && dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close);
if (closed)
{ {
sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0); sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
@ -263,53 +365,67 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
} }
input::SetIntercepted(false); input::SetIntercepted(false);
auto& ctxt = g_fxo->get<opened_dialog_context>();
ctxt.is_opened = false;
if (closed)
{
*notify = 1;
notify->notify_one();
}
}; };
input::SetIntercepted(true); input::SetIntercepted(true);
auto& ppu = *get_current_cpu_thread(); if (ppu)
lv2_obj::sleep(ppu); {
lv2_obj::sleep(*ppu);
// PS3 memory must not be accessed by Main thread }
std::string msg_string = msgString.get_ptr();
// Run asynchronously in GUI thread // Run asynchronously in GUI thread
Emu.CallFromMainThread([&, msg_string = std::move(msg_string)]() Emu.CallFromMainThread([&, is_blocking, notify, msg_string = std::move(msg_string)]()
{ {
dlg->Create(msg_string); dlg->Create(msg_string);
lv2_obj::awake(&ppu);
if (!is_blocking)
{
*notify = 1;
notify->notify_one();
}
}); });
while (auto state = ppu.state.fetch_sub(cpu_flag::signal)) while (!*notify)
{ {
if (is_stopped(state)) if (ppu)
{
if (ppu->is_stopped())
{
ppu->state += cpu_flag::again;
return {};
}
}
else if (Emu.IsStopped())
{ {
return {}; return {};
} }
if (state & cpu_flag::signal) thread_ctrl::wait_on(*notify, 0);
{
break;
}
ppu.state.wait(state);
}
if (is_blocking)
{
while (auto dlg = g_fxo->get<msg_info>().get())
{
if (Emu.IsStopped() || dlg->state != MsgDialogState::Open)
{
break;
}
std::this_thread::yield();
}
} }
return CELL_OK; return CELL_OK;
} }
// wrapper to call for other hle dialogs
error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString, msg_dialog_source source, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam, s32* return_code)
{
// PS3 memory must not be accessed by Main thread
std::string msg_string;
ensure(vm::read_string(msgString.addr(), CELL_MSGDIALOG_STRING_SIZE, msg_string, true), "Secret access violation");
return open_msg_dialog(is_blocking, type, std::move(msg_string), source, callback, userData, extParam, return_code);
}
void close_msg_dialog() void close_msg_dialog()
{ {
cellSysutil.notice("close_msg_dialog()"); cellSysutil.notice("close_msg_dialog()");
@ -376,7 +492,7 @@ error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMs
{ {
cellSysutil.warning("cellMsgDialogOpen2(type=0x%x, msgString=%s, callback=*0x%x, userData=*0x%x, extParam=*0x%x)", type, msgString, callback, userData, extParam); cellSysutil.warning("cellMsgDialogOpen2(type=0x%x, msgString=%s, callback=*0x%x, userData=*0x%x, extParam=*0x%x)", type, msgString, callback, userData, extParam);
if (!msgString || std::strlen(msgString.get_ptr()) >= CELL_MSGDIALOG_STRING_SIZE || type & -0x33f8) if (!msgString || !std::memchr(msgString.get_ptr(), '\0', CELL_MSGDIALOG_STRING_SIZE - 1) || type & -0x33f8)
{ {
return CELL_MSGDIALOG_ERROR_PARAM; return CELL_MSGDIALOG_ERROR_PARAM;
} }

View file

@ -114,26 +114,34 @@ void ppu_module_manager::register_module(ppu_static_module* _module)
ppu_module_manager::get().emplace(_module->name, _module); ppu_module_manager::get().emplace(_module->name, _module);
} }
ppu_static_function& ppu_module_manager::access_static_function(const char* _module, u32 fnid) ppu_static_function& ppu_module_manager::access_static_function(const char* _module, u32 fnid, bool for_creation)
{ {
auto& res = ::at32(ppu_module_manager::get(), _module)->functions[fnid]; auto& res = ::at32(ppu_module_manager::get(), _module)->functions[fnid];
if (res.name) if (for_creation && res.name)
{ {
fmt::throw_exception("PPU FNID duplication in module %s (%s, 0x%x)", _module, res.name, fnid); fmt::throw_exception("PPU FNID duplication in module %s (%s, 0x%x)", _module, res.name, fnid);
} }
else if (!for_creation && !res.name)
{
fmt::throw_exception("PPU FNID unregistered in module %s (%s, 0x%x)", _module, res.name, fnid);
}
return res; return res;
} }
ppu_static_variable& ppu_module_manager::access_static_variable(const char* _module, u32 vnid) ppu_static_variable& ppu_module_manager::access_static_variable(const char* _module, u32 vnid, bool for_creation)
{ {
auto& res = ::at32(ppu_module_manager::get(), _module)->variables[vnid]; auto& res = ::at32(ppu_module_manager::get(), _module)->variables[vnid];
if (res.name) if (for_creation && res.name)
{ {
fmt::throw_exception("PPU VNID duplication in module %s (%s, 0x%x)", _module, res.name, vnid); fmt::throw_exception("PPU VNID duplication in module %s (%s, 0x%x)", _module, res.name, vnid);
} }
else if (!for_creation && !res.name)
{
fmt::throw_exception("PPU VNID unregistered in module %s (%s, 0x%x)", _module, res.name, vnid);
}
return res; return res;
} }
@ -153,6 +161,11 @@ void ppu_module_manager::initialize_modules()
} }
} }
u32 ppu_symbol_addr(std::string_view _module, std::string_view nid) noexcept
{
return *ppu_module_manager::find_static_function(_module.data(), ppu_generate_id(nid)).export_addr;
}
// Global linkage information // Global linkage information
struct ppu_linkage_info struct ppu_linkage_info
{ {

View file

@ -106,9 +106,9 @@ class ppu_module_manager final
static void register_module(ppu_static_module*); static void register_module(ppu_static_module*);
static ppu_static_function& access_static_function(const char* _module, u32 fnid); static ppu_static_function& access_static_function(const char* _module, u32 fnid, bool for_creation);
static ppu_static_variable& access_static_variable(const char* _module, u32 vnid); static ppu_static_variable& access_static_variable(const char* _module, u32 vnid, bool for_creation);
// Global variable for each registered function // Global variable for each registered function
template <auto* Func> template <auto* Func>
@ -125,7 +125,7 @@ public:
template <auto* Func> template <auto* Func>
static auto& register_static_function(const char* _module, const char* name, ppu_intrp_func_t func, u32 fnid) static auto& register_static_function(const char* _module, const char* name, ppu_intrp_func_t func, u32 fnid)
{ {
auto& info = access_static_function(_module, fnid); auto& info = access_static_function(_module, fnid, true);
info.name = name; info.name = name;
info.index = ppu_function_manager::register_function<decltype(Func), Func>(func); info.index = ppu_function_manager::register_function<decltype(Func), Func>(func);
@ -142,6 +142,11 @@ public:
return *registered<Func>::info; return *registered<Func>::info;
} }
static auto& find_static_function(const char* _module, u32 fnid)
{
return access_static_function(_module, fnid, false);
}
template <auto* Var> template <auto* Var>
static auto& register_static_variable(const char* _module, const char* name, u32 vnid) static auto& register_static_variable(const char* _module, const char* name, u32 vnid)
{ {
@ -149,7 +154,7 @@ public:
static_assert(std::is_same_v<u32, typename gvar::addr_type>, "Static variable registration: vm::gvar<T> expected"); static_assert(std::is_same_v<u32, typename gvar::addr_type>, "Static variable registration: vm::gvar<T> expected");
auto& info = access_static_variable(_module, vnid); auto& info = access_static_variable(_module, vnid, true);
info.name = name; info.name = name;
info.var = &Var->raw(); info.var = &Var->raw();
@ -313,6 +318,8 @@ inline RT ppu_execute(ppu_thread& ppu, Args... args)
return func(ppu, args...); return func(ppu, args...);
} }
u32 ppu_symbol_addr(std::string_view _module, std::string_view name) noexcept;
#define BIND_FUNC_WITH_BLR(func, _module) BIND_FUNC(func, if (cpu_flag::again - ppu.state) ppu.cia = static_cast<u32>(ppu.lr) & ~3; else ppu.current_module = _module) #define BIND_FUNC_WITH_BLR(func, _module) BIND_FUNC(func, if (cpu_flag::again - ppu.state) ppu.cia = static_cast<u32>(ppu.lr) & ~3; else ppu.current_module = _module)
#define REG_FNID(_module, nid, func) ppu_module_manager::register_static_function<&func>(#_module, ppu_select_name(#func, nid), BIND_FUNC_WITH_BLR(func, #_module), ppu_generate_id(nid)) #define REG_FNID(_module, nid, func) ppu_module_manager::register_static_function<&func>(#_module, ppu_select_name(#func, nid), BIND_FUNC_WITH_BLR(func, #_module), ppu_generate_id(nid))

View file

@ -2552,12 +2552,18 @@ ppu_thread::ppu_thread(utils::serial& ar)
ar(lv2_obj::g_priority_order_tag); ar(lv2_obj::g_priority_order_tag);
} }
u32 hle_cia = umax;
if (version >= 3) if (version >= 3)
{ {
// Function and module for HLE function relocation // Function and module for HLE function relocation
// TODO: Use it ar(last_module_storage);
ar.pop<std::string>(); ar(last_function_storage);
ar.pop<std::string>();
if (!last_module_storage.empty() && !last_function_storage.empty())
{
hle_cia = ppu_symbol_addr(last_module_storage, last_function_storage);
}
} }
serialize_common(ar); serialize_common(ar);
@ -2708,6 +2714,12 @@ ppu_thread::ppu_thread(utils::serial& ar)
ppu_tname = make_single<std::string>(ar.pop<std::string>()); ppu_tname = make_single<std::string>(ar.pop<std::string>());
if (hle_cia != cia)
{
ppu_log.success("PPU HLE function has been relocated: OG-CIA: 0x%x, NEW-CIA=0x%x (function: %s)", cia, hle_cia, last_function_storage);
cia = hle_cia;
}
ppu_log.notice("Loading PPU Thread [0x%x: %s]: cia=0x%x, state=%s, status=%s", id, *ppu_tname.load(), cia, +state, ppu_thread_status{status}); ppu_log.notice("Loading PPU Thread [0x%x: %s]: cia=0x%x, state=%s, status=%s", id, *ppu_tname.load(), cia, +state, ppu_thread_status{status});
} }

View file

@ -301,6 +301,8 @@ public:
const char* current_function{}; // Current function name for diagnosis, optimized for speed. const char* current_function{}; // Current function name for diagnosis, optimized for speed.
const char* last_function{}; // Sticky copy of current_function, is not cleared on function return const char* last_function{}; // Sticky copy of current_function, is not cleared on function return
const char* current_module{}; // Current module name, for savestates. const char* current_module{}; // Current module name, for savestates.
std::string last_module_storage{}; // Possible storage for current_module
std::string last_function_storage{}; // Possible storage for last_function
const bool is_interrupt_thread; // True for interrupts-handler threads const bool is_interrupt_thread; // True for interrupts-handler threads

View file

@ -40,7 +40,7 @@ static std::array<serial_ver_t, 27> s_serial_versions;
return ::s_serial_versions[identifier].current_version;\ return ::s_serial_versions[identifier].current_version;\
} }
SERIALIZATION_VER(global_version, 0, 19) // For stuff not listed here SERIALIZATION_VER(global_version, 0, 20) // For stuff not listed here
SERIALIZATION_VER(ppu, 1, 1, 2/*PPU sleep order*/, 3/*PPU FNID and module*/) SERIALIZATION_VER(ppu, 1, 1, 2/*PPU sleep order*/, 3/*PPU FNID and module*/)
SERIALIZATION_VER(spu, 2, 1) SERIALIZATION_VER(spu, 2, 1)
SERIALIZATION_VER(lv2_sync, 3, 1) SERIALIZATION_VER(lv2_sync, 3, 1)

View file

@ -53,7 +53,7 @@ struct cfg_root : cfg::node
} }
}; };
fifo_setting rsx_fifo_accuracy{this, "RSX FIFO Accuracy", rsx_fifo_mode::fast }; fifo_setting rsx_fifo_accuracy{this, "RSX FIFO Fetch Accuracy", rsx_fifo_mode::atomic };
cfg::_bool spu_verification{ this, "SPU Verification", true }; // Should be enabled cfg::_bool spu_verification{ this, "SPU Verification", true }; // Should be enabled
cfg::_bool spu_cache{ this, "SPU Cache", true }; cfg::_bool spu_cache{ this, "SPU Cache", true };
cfg::_bool spu_prof{ this, "SPU Profiler", false }; cfg::_bool spu_prof{ this, "SPU Profiler", false };

View file

@ -435,6 +435,12 @@ QCoreApplication* create_application(std::span<char* const> qt_argv)
{ {
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0"); qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0");
} }
#elif __APPLE__
// set the QT_MTL_NO_TRANSACTION variable in order to prevent Qt GUI freeze
qputenv("QT_MTL_NO_TRANSACTION", "1");
// set the QT_MAC_NO_CONTAINER_LAYER variable in order to prevent swapchain crash
qputenv("QT_MAC_NO_CONTAINER_LAYER", "1");
#endif #endif
bool use_high_dpi = true; bool use_high_dpi = true;

View file

@ -1198,10 +1198,10 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_
case emu_settings_type::FIFOAccuracy: case emu_settings_type::FIFOAccuracy:
switch (static_cast<rsx_fifo_mode>(index)) switch (static_cast<rsx_fifo_mode>(index))
{ {
case rsx_fifo_mode::fast: return tr("Fast", "RSX FIFO Accuracy"); case rsx_fifo_mode::fast: return tr("Fast", "RSX FIFO Fetch Accuracy");
case rsx_fifo_mode::atomic: return tr("Atomic", "RSX FIFO Accuracy"); case rsx_fifo_mode::atomic: return tr("Atomic", "RSX FIFO Fetch Accuracy");
case rsx_fifo_mode::atomic_ordered: return tr("Ordered & Atomic", "RSX FIFO Accuracy"); case rsx_fifo_mode::atomic_ordered: return tr("Ordered & Atomic", "RSX FIFO Fetch Accuracy");
case rsx_fifo_mode::as_ps3: return tr("PS3", "RSX FIFO Accuracy"); case rsx_fifo_mode::as_ps3: return tr("PS3", "RSX FIFO Fetch Accuracy");
} }
break; break;
case emu_settings_type::PerfOverlayDetailLevel: case emu_settings_type::PerfOverlayDetailLevel:

View file

@ -235,7 +235,7 @@ inline static const std::map<emu_settings_type, cfg_location> settings_location
{ emu_settings_type::AccurateSpuDMA, { "Core", "Accurate SPU DMA"}}, { emu_settings_type::AccurateSpuDMA, { "Core", "Accurate SPU DMA"}},
{ emu_settings_type::AccurateClineStores, { "Core", "Accurate Cache Line Stores"}}, { emu_settings_type::AccurateClineStores, { "Core", "Accurate Cache Line Stores"}},
{ emu_settings_type::AccurateRSXAccess, { "Core", "Accurate RSX reservation access"}}, { emu_settings_type::AccurateRSXAccess, { "Core", "Accurate RSX reservation access"}},
{ emu_settings_type::FIFOAccuracy, { "Core", "RSX FIFO Accuracy"}}, { emu_settings_type::FIFOAccuracy, { "Core", "RSX FIFO Fetch Accuracy"}},
{ emu_settings_type::XFloatAccuracy, { "Core", "XFloat Accuracy"}}, { emu_settings_type::XFloatAccuracy, { "Core", "XFloat Accuracy"}},
{ emu_settings_type::MFCCommandsShuffling, { "Core", "MFC Commands Shuffling Limit"}}, { emu_settings_type::MFCCommandsShuffling, { "Core", "MFC Commands Shuffling Limit"}},
{ emu_settings_type::SetDAZandFTZ, { "Core", "Set DAZ and FTZ"}}, { emu_settings_type::SetDAZandFTZ, { "Core", "Set DAZ and FTZ"}},

View file

@ -2340,6 +2340,12 @@ void main_window::RetranslateUI(const QStringList& language_codes, const QString
ui->retranslateUi(this); ui->retranslateUi(this);
// Refresh game list first to prevent localization mismatches in further Refresh calls
if (m_game_list_frame)
{
m_game_list_frame->Refresh(true);
}
// Update menu bar size (needed if the corner widget changes its size) // Update menu bar size (needed if the corner widget changes its size)
ui->menuBar->adjustSize(); ui->menuBar->adjustSize();
@ -2354,11 +2360,6 @@ void main_window::RetranslateUI(const QStringList& language_codes, const QString
default: break; default: break;
} }
if (m_game_list_frame)
{
m_game_list_frame->Refresh(true);
}
Q_EMIT RequestDialogRepaint(); Q_EMIT RequestDialogRepaint();
} }

View file

@ -3,15 +3,12 @@
movie_item::movie_item() : QTableWidgetItem(), movie_item_base() movie_item::movie_item() : QTableWidgetItem(), movie_item_base()
{ {
setData(Qt::UserRole, {}); // Set any value to UserRole for proper indexing (e.g. for multiselection)
} }
movie_item::movie_item(const QString& text, int type) : QTableWidgetItem(text, type), movie_item_base() movie_item::movie_item(const QString& text, int type) : QTableWidgetItem(text, type), movie_item_base()
{ {
setData(Qt::UserRole, {}); // Set any value to UserRole for proper indexing (e.g. for multiselection)
} }
movie_item::movie_item(const QIcon& icon, const QString& text, int type) : QTableWidgetItem(icon, text, type), movie_item_base() movie_item::movie_item(const QIcon& icon, const QString& text, int type) : QTableWidgetItem(icon, text, type), movie_item_base()
{ {
setData(Qt::UserRole, {}); // Set any value to UserRole for proper indexing (e.g. for multiselection)
} }

View file

@ -71,14 +71,10 @@ bool qt_camera_video_sink::present(const QVideoFrame& frame)
// Flip image if necessary // Flip image if necessary
if (flip_horizontally || flip_vertically) if (flip_horizontally || flip_vertically)
{ {
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
Qt::Orientations orientation {}; Qt::Orientations orientation {};
orientation.setFlag(Qt::Orientation::Horizontal, flip_horizontally); orientation.setFlag(Qt::Orientation::Horizontal, flip_horizontally);
orientation.setFlag(Qt::Orientation::Vertical, flip_vertically); orientation.setFlag(Qt::Orientation::Vertical, flip_vertically);
image.flip(orientation); image.flip(orientation);
#else
image.mirror(flip_horizontally, flip_vertically);
#endif
} }
if (image.format() != QImage::Format_RGBA8888) if (image.format() != QImage::Format_RGBA8888)