mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-23 16:19:44 +00:00
Add a basic debug console UI to the devmenu that shows some log scrollback and has a little command line.
Useful for debugging on non-Windows in the future. For now non-mobile only (although may lift that restriction later)
This commit is contained in:
parent
23893ffba8
commit
a9b010b0cd
@ -103,6 +103,7 @@ LogManager::LogManager() {
|
||||
consoleLog_ = NULL;
|
||||
debuggerLog_ = NULL;
|
||||
#endif
|
||||
ringLog_ = new RingbufferLogListener();
|
||||
|
||||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) {
|
||||
log_[i]->SetEnable(true);
|
||||
@ -113,6 +114,7 @@ LogManager::LogManager() {
|
||||
if (IsDebuggerPresent() && debuggerLog_ != NULL && LOG_MSC_OUTPUTDEBUG)
|
||||
log_[i]->AddListener(debuggerLog_);
|
||||
#endif
|
||||
log_[i]->AddListener(ringLog_);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -285,3 +287,18 @@ void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) {
|
||||
OutputDebugStringUTF8(msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RingbufferLogListener::Log(LogTypes::LOG_LEVELS level, const char *msg) {
|
||||
if (!enabled_)
|
||||
return;
|
||||
levels_[curMessage_] = (u8)level;
|
||||
int len = (int)strlen(msg);
|
||||
if (len >= sizeof(messages_[0]))
|
||||
len = sizeof(messages_[0]) - 1;
|
||||
memcpy(messages_[curMessage_], msg, len);
|
||||
messages_[curMessage_][len] = 0;
|
||||
curMessage_++;
|
||||
if (curMessage_ >= MAX_LOGS)
|
||||
curMessage_ -= MAX_LOGS;
|
||||
count_++;
|
||||
}
|
||||
|
@ -61,6 +61,27 @@ public:
|
||||
void Log(LogTypes::LOG_LEVELS, const char *msg);
|
||||
};
|
||||
|
||||
class RingbufferLogListener : public LogListener {
|
||||
public:
|
||||
RingbufferLogListener() : curMessage_(0), count_(0), enabled_(false) {}
|
||||
void Log(LogTypes::LOG_LEVELS, const char *msg);
|
||||
|
||||
bool IsEnabled() const { return enabled_; }
|
||||
void SetEnable(bool enable) { enabled_ = enable; }
|
||||
|
||||
int GetCount() const { return count_ < MAX_LOGS ? count_ : MAX_LOGS; }
|
||||
const char *TextAt(int i) { return messages_[(curMessage_ - i - 1) & (MAX_LOGS - 1)]; }
|
||||
LogTypes::LOG_LEVELS LevelAt(int i) { return (LogTypes::LOG_LEVELS)levels_[(curMessage_ - i - 1) & (MAX_LOGS - 1)]; }
|
||||
|
||||
private:
|
||||
enum { MAX_LOGS = 128 };
|
||||
char messages_[MAX_LOGS][1024];
|
||||
u8 levels_[MAX_LOGS];
|
||||
int curMessage_;
|
||||
int count_;
|
||||
bool enabled_;
|
||||
};
|
||||
|
||||
// TODO: A simple buffered log that can be used to display the log in-window
|
||||
// on Android etc.
|
||||
// class BufferedLogListener { ... }
|
||||
@ -105,6 +126,7 @@ private:
|
||||
FileLogListener *fileLog_;
|
||||
ConsoleListener *consoleLog_;
|
||||
DebuggerLogListener *debuggerLog_;
|
||||
RingbufferLogListener *ringLog_;
|
||||
static LogManager *logManager_; // Singleton. Ugh.
|
||||
std::mutex log_lock_;
|
||||
|
||||
@ -157,6 +179,10 @@ public:
|
||||
return debuggerLog_;
|
||||
}
|
||||
|
||||
RingbufferLogListener *GetRingbufferListener() const {
|
||||
return ringLog_;
|
||||
}
|
||||
|
||||
static LogManager* GetInstance() {
|
||||
return logManager_;
|
||||
}
|
||||
|
@ -774,9 +774,9 @@ namespace DX9 {
|
||||
const u32 rh = PSP_CoreParameter().pixelHeight;
|
||||
const RECT srcRect = {(LONG)(u0 * vfb->renderWidth), (LONG)(v0 * vfb->renderHeight), (LONG)(u1 * vfb->renderWidth), (LONG)(v1 * vfb->renderHeight)};
|
||||
const RECT dstRect = {x * rw / w, y * rh / h, (x + w) * rw / w, (y + h) * rh / h};
|
||||
HRESULT hr = fbo_blit_color(vfb->fbo, &srcRect, nullptr, &dstRect, g_Config.iBufFilter == SCALE_LINEAR ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
if (FAILED(hr)) {
|
||||
ERROR_LOG_REPORT_ONCE(blit_fail, G3D, "fbo_blit_color failed on display: %08x", hr);
|
||||
//HRESULT hr = fbo_blit_color(vfb->fbo, &srcRect, nullptr, &dstRect, g_Config.iBufFilter == SCALE_LINEAR ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
//if (FAILED(hr)) {
|
||||
// ERROR_LOG_REPORT_ONCE(blit_fail, G3D, "fbo_blit_color failed on display: %08x", hr);
|
||||
dxstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
|
||||
// These are in the output display coordinates
|
||||
if (g_Config.iBufFilter == SCALE_LINEAR) {
|
||||
@ -789,7 +789,7 @@ namespace DX9 {
|
||||
dxstate.texMipFilter.set(D3DTEXF_NONE);
|
||||
dxstate.texMipLodBias.set(0);
|
||||
DrawActiveTexture(colorTexture, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, false, u0, v0, u1, v1);
|
||||
}
|
||||
//}
|
||||
}
|
||||
/*
|
||||
else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) {
|
||||
|
@ -55,11 +55,25 @@ void DevMenu::CreatePopupContents(UI::ViewGroup *parent) {
|
||||
I18NCategory *de = GetI18NCategory("Developer");
|
||||
I18NCategory *sy = GetI18NCategory("System");
|
||||
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
parent->Add(new Choice(de->T("Log View")))->OnClick.Handle(this, &DevMenu::OnLogView);
|
||||
#endif
|
||||
parent->Add(new Choice(de->T("Logging Channels")))->OnClick.Handle(this, &DevMenu::OnLogConfig);
|
||||
parent->Add(new Choice(sy->T("Developer Tools")))->OnClick.Handle(this, &DevMenu::OnDeveloperTools);
|
||||
parent->Add(new Choice(de->T("Jit Compare")))->OnClick.Handle(this, &DevMenu::OnJitCompare);
|
||||
parent->Add(new Choice(de->T("Toggle Freeze")))->OnClick.Handle(this, &DevMenu::OnFreezeFrame);
|
||||
parent->Add(new Choice(de->T("Dump Frame GPU Commands")))->OnClick.Handle(this, &DevMenu::OnDumpFrame);
|
||||
|
||||
RingbufferLogListener *ring = LogManager::GetInstance()->GetRingbufferListener();
|
||||
if (ring) {
|
||||
ring->SetEnable(true);
|
||||
}
|
||||
}
|
||||
|
||||
UI::EventReturn DevMenu::OnLogView(UI::EventParams &e) {
|
||||
UpdateUIState(UISTATE_PAUSEMENU);
|
||||
screenManager()->push(new LogScreen());
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn DevMenu::OnLogConfig(UI::EventParams &e) {
|
||||
@ -100,6 +114,67 @@ void DevMenu::dialogFinished(const Screen *dialog, DialogResult result) {
|
||||
// screenManager()->finishDialog(this, DR_OK);
|
||||
}
|
||||
|
||||
void LogScreen::UpdateLog() {
|
||||
using namespace UI;
|
||||
RingbufferLogListener *ring = LogManager::GetInstance()->GetRingbufferListener();
|
||||
if (!ring)
|
||||
return;
|
||||
vert_->Clear();
|
||||
for (int i = ring->GetCount() - 1; i >= 0; i--) {
|
||||
TextView *v = vert_->Add(new TextView(ring->TextAt(i), FLAG_DYNAMIC_ASCII, false));
|
||||
uint32_t color = 0xFFFFFF;
|
||||
switch (ring->LevelAt(i)) {
|
||||
case LogTypes::LDEBUG: color = 0xE0E0E0; break;
|
||||
case LogTypes::LWARNING: color = 0x50FFFF; break;
|
||||
case LogTypes::LERROR: color = 0x5050FF; break;
|
||||
case LogTypes::LNOTICE: color = 0x30FF30; break;
|
||||
case LogTypes::LINFO: color = 0xFFFFFF; break;
|
||||
}
|
||||
v->SetTextColor(0xFF000000 | color);
|
||||
}
|
||||
toBottom_ = true;
|
||||
}
|
||||
|
||||
void LogScreen::update(InputState &input) {
|
||||
UIDialogScreenWithBackground::update(input);
|
||||
if (toBottom_) {
|
||||
toBottom_ = false;
|
||||
scroll_->ScrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
void LogScreen::CreateViews() {
|
||||
using namespace UI;
|
||||
I18NCategory *di = GetI18NCategory("Dialog");
|
||||
|
||||
LinearLayout *outer = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
|
||||
root_ = outer;
|
||||
|
||||
scroll_ = outer->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0)));
|
||||
LinearLayout *bottom = outer->Add(new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
bottom->Add(new Button(di->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
|
||||
cmdLine_ = bottom->Add(new TextEdit("", "Command Line", new LinearLayoutParams(1.0)));
|
||||
cmdLine_->OnEnter.Handle(this, &LogScreen::OnSubmit);
|
||||
bottom->Add(new Button(di->T("Submit")))->OnClick.Handle(this, &LogScreen::OnSubmit);
|
||||
|
||||
vert_ = scroll_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
vert_->SetSpacing(0);
|
||||
|
||||
UpdateLog();
|
||||
}
|
||||
|
||||
UI::EventReturn LogScreen::OnSubmit(UI::EventParams &e) {
|
||||
std::string cmd = cmdLine_->GetText();
|
||||
|
||||
// TODO: Can add all sorts of fun stuff here that we can't be bothered writing proper UI for, like various memdumps etc.
|
||||
|
||||
NOTICE_LOG(HLE, "Submitted: %s", cmd.c_str());
|
||||
|
||||
UpdateLog();
|
||||
cmdLine_->SetText("");
|
||||
cmdLine_->SetFocus();
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
void LogConfigScreen::CreateViews() {
|
||||
using namespace UI;
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
virtual void dialogFinished(const Screen *dialog, DialogResult result);
|
||||
|
||||
protected:
|
||||
UI::EventReturn OnLogView(UI::EventParams &e);
|
||||
UI::EventReturn OnLogConfig(UI::EventParams &e);
|
||||
UI::EventReturn OnJitCompare(UI::EventParams &e);
|
||||
UI::EventReturn OnFreezeFrame(UI::EventParams &e);
|
||||
@ -54,6 +55,21 @@ private:
|
||||
UI::EventReturn OnLogLevelChange(UI::EventParams &e);
|
||||
};
|
||||
|
||||
class LogScreen : public UIDialogScreenWithBackground {
|
||||
public:
|
||||
LogScreen() : toBottom_(false) {}
|
||||
void CreateViews() override;
|
||||
void update(InputState &input) override;
|
||||
|
||||
private:
|
||||
void UpdateLog();
|
||||
UI::EventReturn OnSubmit(UI::EventParams &e);
|
||||
UI::TextEdit *cmdLine_;
|
||||
UI::LinearLayout *vert_;
|
||||
UI::ScrollView *scroll_;
|
||||
bool toBottom_;
|
||||
};
|
||||
|
||||
class LogLevelScreen : public ListPopupScreen {
|
||||
public:
|
||||
LogLevelScreen(const std::string &title);
|
||||
|
2
native
2
native
@ -1 +1 @@
|
||||
Subproject commit 3ebd4675091e3d08e0da3ad8d3d66d1adff1697a
|
||||
Subproject commit 40848ae4b64907fec31b2562fc977c043133a275
|
Loading…
Reference in New Issue
Block a user