void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> xaio, int error, int xid, u64 size)> func) { while (g_FsAioReadCur != xid) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); if (Emu.IsStopped()) { LOG_WARNING(HLE, "fsAioRead() aborted"); return; } } vfsFileBase* orig_file; if(!sys_fs->CheckId(fd, orig_file)) return; u64 nbytes = aio->size; u32 buf_addr = aio->buf_addr; u32 error = CELL_OK; vfsStream& file = *(vfsStream*)orig_file; const u64 old_pos = file.Tell(); file.Seek((u64)aio->offset); // TODO: use code from cellFsRead or something u64 res = 0; if (nbytes != (u32)nbytes) { error = CELL_ENOMEM; } else { res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0; } file.Seek(old_pos); if (Ini.HLELogging.GetValue()) LOG_NOTICE(HLE, "*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, error=0x%x, res=0x%x, xid=0x%x [%s])", fd, (u64)aio->offset, buf_addr, (u64)aio->size, error, res, xid, orig_file->GetPath().c_str()); if (func) // start callback thread { func.async(aio, error, xid, res); } g_FsAioReadCur++; }
void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> xaio, int error, int xid, u64 size)> func) { while (g_FsAioReadCur != xid) { Sleep(1); if (Emu.IsStopped()) { ConLog.Warning("fsAioRead() aborted"); return; } } vfsFileBase* orig_file; if(!sys_fs.CheckId(fd, orig_file)) return; std::string path = orig_file->GetPath(); std::string::size_type first_slash = path.find('/'); if (first_slash == std::string::npos) { path = ""; } else { path = path.substr(first_slash+1,std::string::npos); } u64 nbytes = aio->size; u32 buf_addr = aio->buf_addr; u32 res = 0; u32 error = CELL_OK; vfsStream& file = *(vfsStream*)orig_file; const u64 old_pos = file.Tell(); file.Seek((u64)aio->offset); u32 count = nbytes; if (nbytes != (u64)count) { error = CELL_ENOMEM; goto fin; } if (!Memory.IsGoodAddr(buf_addr)) { error = CELL_EFAULT; goto fin; } if (count) if (u32 frag = buf_addr & 4095) // memory page fragment { u32 req = min(count, 4096 - frag); u32 read = file.Read(Memory + buf_addr, req); buf_addr += req; res += read; count -= req; if (read < req) goto fin; } for (u32 pages = count / 4096; pages > 0; pages--) // full pages { if (!Memory.IsGoodAddr(buf_addr)) goto fin; // ??? (probably EFAULT) u32 read = file.Read(Memory + buf_addr, 4096); buf_addr += 4096; res += read; count -= 4096; if (read < 4096) goto fin; } if (count) // last fragment { if (!Memory.IsGoodAddr(buf_addr)) goto fin; res += file.Read(Memory + buf_addr, count); } fin: file.Seek(old_pos); ConLog.Warning("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, error=0x%x, res=0x%x, xid=0x%x [%s])", fd, (u64)aio->offset, buf_addr, (u64)aio->size, error, res, xid, path.c_str()); if (func) // start callback thread { func.async(aio, error, xid, res); } /*CPUThread& thr = Emu.GetCallbackThread(); while (thr.IsAlive()) { Sleep(1); if (Emu.IsStopped()) { ConLog.Warning("fsAioRead() aborted"); break; } }*/ g_FsAioReadCur++; }
int cellMsgDialogOpen2(u32 type, mem_list_ptr_t<u8> msgString, mem_func_ptr_t<CellMsgDialogCallback> callback, u32 userData, u32 extParam) { cellSysutil->Warning("cellMsgDialogOpen2(type=0x%x, msgString_addr=0x%x, callback_addr=0x%x, userData=0x%x, extParam=0x%x)", type, msgString.GetAddr(), callback.GetAddr(), userData, extParam); if (!msgString.IsGood() || !callback.IsGood()) { return CELL_EFAULT; } //type |= CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE; //type |= CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO; MsgDialogState old = msgDialogNone; if (!g_msg_dialog_state.compare_exchange_strong(old, msgDialogOpen)) { return CELL_SYSUTIL_ERROR_BUSY; } thread t("MsgDialog thread", [=]() { switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE) { case CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL: LOG_WARNING(Log::HLE, "%s", msgString.GetString()); break; case CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR: LOG_ERROR(Log::HLE, "%s", msgString.GetString()); break; } switch (type & CELL_MSGDIALOG_TYPE_SE_MUTE) // TODO { case CELL_MSGDIALOG_TYPE_SE_MUTE_OFF: break; case CELL_MSGDIALOG_TYPE_SE_MUTE_ON: break; } switch (type & CELL_MSGDIALOG_TYPE_BG) // TODO { case CELL_MSGDIALOG_TYPE_BG_INVISIBLE: break; case CELL_MSGDIALOG_TYPE_BG_VISIBLE: break; } switch (type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR) // TODO { case CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NO: break; default: break; } u64 status = CELL_MSGDIALOG_BUTTON_NONE; volatile bool m_signal = false; wxGetApp().CallAfter([&]() { wxWindow* parent = nullptr; // TODO: align it better m_gauge1 = nullptr; m_gauge2 = nullptr; m_text1 = nullptr; m_text2 = nullptr; wxButton* m_button_ok = nullptr; wxButton* m_button_yes = nullptr; wxButton* m_button_no = nullptr; g_msg_dialog = new wxDialog(parent, wxID_ANY, type & CELL_MSGDIALOG_TYPE_SE_TYPE ? "" : "Error", wxDefaultPosition, wxDefaultSize); g_msg_dialog->SetExtraStyle(g_msg_dialog->GetExtraStyle() | wxWS_EX_TRANSIENT); wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL); wxStaticText* m_text = new wxStaticText(g_msg_dialog, wxID_ANY, wxString(msgString.GetString(), wxConvUTF8)); sizer1->Add(m_text, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16); switch (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR) { case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE: m_gauge2 = new wxGauge(g_msg_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH); m_text2 = new wxStaticText(g_msg_dialog, wxID_ANY, ""); m_text2->SetAutoLayout(true); case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: m_gauge1 = new wxGauge(g_msg_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH); m_text1 = new wxStaticText(g_msg_dialog, wxID_ANY, ""); m_text1->SetAutoLayout(true); case CELL_MSGDIALOG_TYPE_PROGRESSBAR_NONE: break; } if (m_gauge1) { sizer1->Add(m_text1, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 8); sizer1->Add(m_gauge1, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, 16); m_gauge1->SetValue(0); } if (m_gauge2) { sizer1->Add(m_text2, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 8); sizer1->Add(m_gauge2, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, 16); m_gauge2->SetValue(0); } wxBoxSizer* buttons = new wxBoxSizer(wxHORIZONTAL); switch (type & CELL_MSGDIALOG_TYPE_BUTTON_TYPE) { case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE: break; case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO: m_button_yes = new wxButton(g_msg_dialog, wxID_YES); buttons->Add(m_button_yes, 0, wxALIGN_CENTER_HORIZONTAL | wxRIGHT, 8); m_button_no = new wxButton(g_msg_dialog, wxID_NO); buttons->Add(m_button_no, 0, wxALIGN_CENTER_HORIZONTAL, 16); sizer1->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16); break; case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK: m_button_ok = new wxButton(g_msg_dialog, wxID_OK); buttons->Add(m_button_ok, 0, wxALIGN_CENTER_HORIZONTAL, 16); sizer1->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16); break; } sizer1->AddSpacer(16); g_msg_dialog->SetSizerAndFit(sizer1); g_msg_dialog->Centre(wxBOTH); g_msg_dialog->Show(); g_msg_dialog->Enable(); g_msg_dialog->Bind(wxEVT_BUTTON, [&](wxCommandEvent& event) { status = (event.GetId() == wxID_NO) ? CELL_MSGDIALOG_BUTTON_NO : CELL_MSGDIALOG_BUTTON_YES /* OK */; g_msg_dialog->Hide(); m_wait_until = get_system_time(); g_msg_dialog_state = msgDialogClose; }); g_msg_dialog->Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent& event) { if (type & CELL_MSGDIALOG_TYPE_DISABLE_CANCEL) { } else { status = CELL_MSGDIALOG_BUTTON_ESCAPE; g_msg_dialog->Hide(); m_wait_until = get_system_time(); g_msg_dialog_state = msgDialogClose; } }); m_signal = true; }); while (!m_signal) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } while (g_msg_dialog_state == msgDialogOpen || get_system_time() < m_wait_until) { if (Emu.IsStopped()) { g_msg_dialog_state = msgDialogAbort; break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } if (callback && (g_msg_dialog_state != msgDialogAbort)) callback.async(status, userData); wxGetApp().CallAfter([&]() { delete g_msg_dialog; g_msg_dialog = nullptr; }); g_msg_dialog_state = msgDialogNone; }); t.detach(); return CELL_OK; }