diff --git a/rpcs3/Emu/Cell/Modules/sysPrxForUser.cpp b/rpcs3/Emu/Cell/Modules/sysPrxForUser.cpp index 17f4c5b334..291937051d 100644 --- a/rpcs3/Emu/Cell/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/Cell/Modules/sysPrxForUser.cpp @@ -6,14 +6,13 @@ #include "Emu/Cell/lv2/sys_interrupt.h" #include "Emu/Cell/lv2/sys_process.h" #include "Emu/Cell/lv2/sys_ss.h" +#include "Emu/Cell/lv2/sys_tty.h" #include "sysPrxForUser.h" logs::channel sysPrxForUser("sysPrxForUser"); extern u64 get_system_time(); -extern fs::file g_tty; - vm::gvar sys_prx_version; // ??? vm::gvar> g_ppu_atexitspawn; vm::gvar> g_ppu_at_Exitspawn; @@ -97,20 +96,16 @@ s32 console_getc() fmt::throw_exception("Unimplemented" HERE); } -s32 console_putc() +void console_putc(char ch) { - fmt::throw_exception("Unimplemented" HERE); + sysPrxForUser.trace("console_putc(ch=0x%x)", ch); + sys_tty_write(0, vm::var(ch), 1, vm::var{}); } -s32 console_write(vm::ptr data, u32 len) +error_code console_write(vm::ptr data, u32 len) { - sysPrxForUser.warning("console_write(data=*0x%x, len=%d)", data, len); - - if (g_tty) - { - g_tty.write(data.get_ptr(), len); - } - + sysPrxForUser.trace("console_write(data=*0x%x, len=%d)", data, len); + sys_tty_write(0, data, len, vm::var{}); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/sys_libc_.cpp b/rpcs3/Emu/Cell/Modules/sys_libc_.cpp index 3498bdbbc0..45a1abf67a 100644 --- a/rpcs3/Emu/Cell/Modules/sys_libc_.cpp +++ b/rpcs3/Emu/Cell/Modules/sys_libc_.cpp @@ -1,15 +1,12 @@ #include "stdafx.h" +#include "Emu/Cell/lv2/sys_tty.h" #include "Emu/Cell/PPUModule.h" #include "Utilities/cfmt.h" #include #include - - extern logs::channel sysPrxForUser; -extern fs::file g_tty; - // cfmt implementation (TODO) using qsortcmp = s32(vm::cptr e1, vm::cptr e2); @@ -420,10 +417,9 @@ s32 _sys_printf(ppu_thread& ppu, vm::cptr fmt, ppu_va_args_t va_args) { sysPrxForUser.warning("_sys_printf(fmt=%s, ...)", fmt); - if (g_tty) - { - g_tty.write(ps3_fmt(ppu, fmt, va_args.count)); - } + const auto buf = vm::make_str(ps3_fmt(ppu, fmt, va_args.count)); + + sys_tty_write(0, buf, buf.get_count() - 1, vm::var{}); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_tty.cpp b/rpcs3/Emu/Cell/lv2/sys_tty.cpp index 7a5cef8021..0a4a7db0f6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_tty.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_tty.cpp @@ -1,11 +1,10 @@ #include "stdafx.h" #include "sys_tty.h" - - logs::channel sys_tty("sys_tty"); extern fs::file g_tty; +extern atomic_t g_tty_size; error_code sys_tty_read(s32 ch, vm::ptr buf, u32 len, vm::ptr preadlen) { @@ -28,7 +27,10 @@ error_code sys_tty_write(s32 ch, vm::cptr buf, u32 len, vm::ptr pwrit if (written_len > 0 && g_tty) { + // Lock size by making it negative + g_tty_size -= (1ll << 48); g_tty.write(buf.get_ptr(), len); + g_tty_size += (1ll << 48) + len; } if (!pwritelen) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 43e6c8c800..4117a06280 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -44,6 +44,7 @@ extern std::shared_ptr ppu_load_prx(const ppu_prx_object&, const extern void network_thread_init(); fs::file g_tty; +atomic_t g_tty_size{0}; template <> void fmt_class_string::format(std::string& out, u64 arg) diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp index 95c04c5c04..37c0aad546 100644 --- a/rpcs3/rpcs3qt/log_frame.cpp +++ b/rpcs3/rpcs3qt/log_frame.cpp @@ -9,6 +9,8 @@ #include #include +extern atomic_t g_tty_size; + constexpr auto qstr = QString::fromStdString; struct gui_listener : logs::listener @@ -193,7 +195,7 @@ void log_frame::CreateAndConnectActions() auto l_initAct = [this](QAction* act, logs::level logLevel) { act->setCheckable(true); - + // This sets the log level properly when the action is triggered. connect(act, &QAction::triggered, [this, logLevel]() { @@ -302,47 +304,30 @@ void log_frame::RepaintTextColors() void log_frame::UpdateUI() { - std::vector buf(4096); - - // Get UTF-8 string from file - auto get_utf8 = [&](const fs::file& file, u64 size) -> QString - { - size = file.read(buf.data(), size); - - for (u64 i = 0; i < size; i++) - { - // Get UTF-8 sequence length (no real validation performed) - const u64 tail = - (buf[i] & 0xF0) == 0xF0 ? 3 : - (buf[i] & 0xE0) == 0xE0 ? 2 : - (buf[i] & 0xC0) == 0xC0 ? 1 : 0; - - if (i + tail >= size) - { // Copying is expensive-- O(i)-- but I suspect this corruption will be exceptionally unlikely. - file.seek(i - size, fs::seek_cur); - std::vector sub(&buf[0], &buf[i]); - return QString(sub.data()); - } - } - return QString(buf.data()); - }; - const auto start = steady_clock::now(); // Check TTY logs - - while (const u64 size = std::min(buf.size(), m_tty_file.size() - m_tty_file.pos())) + while (const u64 size = std::max(0, g_tty_size.load() - m_tty_file.pos())) { - QString text = get_utf8(m_tty_file, size); + std::string buf; + buf.resize(size); + buf.resize(m_tty_file.read(&buf.front(), buf.size())); - // Hackily used the state of the check.. be better if I actually stored this value. - if (m_TTYAct->isChecked()) + if (buf.find_first_of('\0') != -1) { - text.chop(1); // remove newline since Qt automatically adds a newline. - m_tty->append(text); + m_tty_file.seek(s64{0} - buf.size(), fs::seek_mode::seek_cur); + break; } + + if (buf.size() && m_TTYAct->isChecked()) + { + QTextCursor text_cursor{m_tty->document()}; + text_cursor.movePosition(QTextCursor::End); + text_cursor.insertText(qstr(buf)); + } + // Limit processing time - if (steady_clock::now() >= start + 4ms || text.isEmpty()) break; + if (steady_clock::now() >= start + 4ms || buf.empty()) break; } // Check main logs diff --git a/rpcs3/rpcs3qt/log_frame.h b/rpcs3/rpcs3qt/log_frame.h index afa17878ea..bbf8375711 100644 --- a/rpcs3/rpcs3qt/log_frame.h +++ b/rpcs3/rpcs3qt/log_frame.h @@ -48,8 +48,8 @@ private: QList m_color; QColor m_color_stack; - QTextEdit *m_log; - QTextEdit *m_tty; + QTextEdit* m_log; + QTextEdit* m_tty; QString m_old_text; ullong m_log_counter; bool m_stack_log;