Skip to content

Commit c817a07

Browse files
authored
Merge pull request #20332 from hrydgard/fix-various-bugs
Fix reset bug, frame advance bug, translation issues
2 parents e1e352c + 9e0c98a commit c817a07

File tree

9 files changed

+104
-110
lines changed

9 files changed

+104
-110
lines changed

Common/TimeUtil.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <cstdint>
55

66
#include "Common/TimeUtil.h"
7+
#include "Common/Data/Random/Rng.h"
78
#include "Common/Log.h"
89

910
#ifdef HAVE_LIBNX
@@ -339,3 +340,11 @@ void GetCurrentTimeFormatted(char formattedTime[13]) {
339340
// Now tack on the milliseconds
340341
snprintf(formattedTime, 11, "%s:%03u", tmp, milliseconds % 1000);
341342
}
343+
344+
// We don't even bother synchronizing this, it's fine if threads stomp a bit.
345+
static GMRng g_sleepRandom;
346+
347+
void sleep_random(double minSeconds, double maxSeconds) {
348+
const double waitSeconds = minSeconds + (maxSeconds - minSeconds) * g_sleepRandom.F();
349+
sleep_precise(waitSeconds);
350+
}

Common/TimeUtil.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ void sleep_ms(int ms, const char *reason);
2525
// Precise sleep. Can consume a little bit of CPU on Windows at least.
2626
void sleep_precise(double seconds);
2727

28+
// Random sleep, used for debugging.
29+
void sleep_random(double minSeconds, double maxSeconds);
30+
2831
// Yield. Signals that this thread is busy-waiting but wants to allow other hyperthreads to run.
2932
void yield();
3033

Core/HW/Display.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
#pragma once
1919

2020
#include <cstdint>
21+
#include <functional>
2122

2223
class PointerWrap;
2324

24-
typedef void (*VblankCallback)();
25-
// Listen for vblank events.
25+
typedef std::function<void()> VblankCallback;
26+
// Listen for vblank events. Callbacks are cleared in DisplayHWShutdown().
2627
void __DisplayListenVblank(VblankCallback callback);
2728
typedef void (*FlipCallback)(void *userdata);
2829
void __DisplayListenFlip(FlipCallback callback, void *userdata);

UI/EmuScreen.cpp

Lines changed: 62 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,6 @@ using namespace std::placeholders;
111111
static AVIDump avi;
112112
#endif
113113

114-
// TODO: Ugly!
115-
static bool frameStep_;
116-
static int lastNumFlips;
117-
static bool startDumping;
118-
119114
extern bool g_TakeScreenshot;
120115

121116
static void AssertCancelCallback(const char *message, void *userdata) {
@@ -127,35 +122,6 @@ static void AssertCancelCallback(const char *message, void *userdata) {
127122
emuScreen->SendImDebuggerCommand(ImCommand{ ImCmd::SHOW_IN_CPU_DISASM, currentMIPS->pc });
128123
}
129124

130-
static void __EmuScreenVblank()
131-
{
132-
auto sy = GetI18NCategory(I18NCat::SYSTEM);
133-
134-
if (frameStep_ && lastNumFlips != gpuStats.numFlips) {
135-
frameStep_ = false;
136-
Core_Break(BreakReason::FrameAdvance, 0);
137-
lastNumFlips = gpuStats.numFlips;
138-
}
139-
#ifndef MOBILE_DEVICE
140-
if (g_Config.bDumpFrames && !startDumping)
141-
{
142-
avi.Start(PSP_CoreParameter().renderWidth, PSP_CoreParameter().renderHeight);
143-
g_OSD.Show(OSDType::MESSAGE_INFO, sy->T("AVI Dump started."), 1.0f);
144-
startDumping = true;
145-
}
146-
if (g_Config.bDumpFrames && startDumping)
147-
{
148-
avi.AddFrame();
149-
}
150-
else if (!g_Config.bDumpFrames && startDumping)
151-
{
152-
avi.Stop();
153-
g_OSD.Show(OSDType::MESSAGE_INFO, sy->T("AVI Dump stopped."), 1.0f);
154-
startDumping = false;
155-
}
156-
#endif
157-
}
158-
159125
// Handles control rotation due to internal screen rotation.
160126
static void SetPSPAnalog(int stick, float x, float y) {
161127
switch (g_Config.iInternalScreenRotation) {
@@ -189,10 +155,6 @@ static void SetPSPAnalog(int stick, float x, float y) {
189155
EmuScreen::EmuScreen(const Path &filename)
190156
: gamePath_(filename) {
191157
saveStateSlot_ = SaveState::GetCurrentSlot();
192-
__DisplayListenVblank(__EmuScreenVblank);
193-
frameStep_ = false;
194-
lastNumFlips = gpuStats.numFlips;
195-
startDumping = false;
196158
controlMapper_.SetCallbacks(
197159
std::bind(&EmuScreen::onVKey, this, _1, _2),
198160
std::bind(&EmuScreen::onVKeyAnalog, this, _1, _2),
@@ -366,6 +328,8 @@ void EmuScreen::ProcessGameBoot(const Path &filename) {
366328

367329
// Only call this on successful boot.
368330
void EmuScreen::bootComplete() {
331+
__DisplayListenVblank([this]() {HandleVBlank(); });
332+
369333
// Initialize retroachievements, now that we're on the right thread.
370334
if (g_Config.bAchievementsEnable) {
371335
std::string errorString;
@@ -440,8 +404,10 @@ void EmuScreen::bootComplete() {
440404

441405
saveStateSlot_ = SaveState::GetCurrentSlot();
442406

443-
loadingViewColor_->Divert(0x00FFFFFF, 0.2f);
444-
loadingViewVisible_->Divert(UI::V_INVISIBLE, 0.2f);
407+
if (loadingViewColor_)
408+
loadingViewColor_->Divert(0x00FFFFFF, 0.2f);
409+
if (loadingViewVisible_)
410+
loadingViewVisible_->Divert(UI::V_INVISIBLE, 0.2f);
445411

446412
std::string gameID = g_paramSFO.GetValueString("DISC_ID");
447413
g_Config.TimeTracker().Start(gameID);
@@ -475,11 +441,11 @@ EmuScreen::~EmuScreen() {
475441
g_logManager.EnableOutput(LogOutput::RingBuffer);
476442

477443
#ifndef MOBILE_DEVICE
478-
if (g_Config.bDumpFrames && startDumping)
444+
if (g_Config.bDumpFrames && startDumping_)
479445
{
480446
avi.Stop();
481447
g_OSD.Show(OSDType::MESSAGE_INFO, "AVI Dump stopped.", 2.0f);
482-
startDumping = false;
448+
startDumping_ = false;
483449
}
484450
#endif
485451

@@ -801,14 +767,6 @@ void EmuScreen::onVKey(VirtKey virtualKeyCode, bool down) {
801767
}
802768
break;
803769

804-
case VIRTKEY_FRAME_ADVANCE:
805-
// Can't do this reliably in an async fashion, so we just set a variable.
806-
// Is this used by anyone? There's no good way to resume, other than PAUSE_NO_MENU or the debugger.
807-
if (down && !NetworkWarnUserIfOnlineAndCantSpeed()) {
808-
doFrameAdvance_.store(true);
809-
}
810-
break;
811-
812770
case VIRTKEY_RESET_EMULATION:
813771
if (down) {
814772
System_PostUIMessage(UIMessage::REQUEST_GAME_RESET);
@@ -1007,6 +965,19 @@ void EmuScreen::ProcessVKey(VirtKey virtKey) {
1007965
break;
1008966
}
1009967

968+
case VIRTKEY_FRAME_ADVANCE:
969+
// Can't do this reliably in an async fashion, so we just set a variable.
970+
// Is this used by anyone? There's no user-friendly way to resume, other than PAUSE_NO_MENU or the debugger.
971+
if (!NetworkWarnUserIfOnlineAndCantSpeed()) {
972+
if (Core_IsStepping()) {
973+
Core_Resume();
974+
frameStep_ = true;
975+
} else {
976+
Core_Break(BreakReason::FrameAdvance);
977+
}
978+
}
979+
break;
980+
1010981
default:
1011982
break;
1012983
}
@@ -1217,7 +1188,14 @@ void EmuScreen::CreateViews() {
12171188
root_->Add(buttons);
12181189

12191190
resumeButton_ = buttons->Add(new Button(dev->T("Resume")));
1220-
resumeButton_->OnClick.Handle(this, &EmuScreen::OnResume);
1191+
resumeButton_->OnClick.Add([this](UI::EventParams &) {
1192+
if (coreState == CoreState::CORE_RUNTIME_ERROR) {
1193+
// Force it!
1194+
Memory::MemFault_IgnoreLastCrash();
1195+
coreState = CoreState::CORE_RUNNING_CPU;
1196+
}
1197+
return UI::EVENT_DONE;
1198+
});
12211199
resumeButton_->SetVisibility(V_GONE);
12221200

12231201
resetButton_ = buttons->Add(new Button(dev->T("Reset")));
@@ -1237,7 +1215,10 @@ void EmuScreen::CreateViews() {
12371215
backButton_->SetVisibility(V_GONE);
12381216

12391217
cardboardDisableButton_ = root_->Add(new Button(sc->T("Cardboard VR OFF"), new AnchorLayoutParams(bounds.centerX(), NONE, NONE, 30, true)));
1240-
cardboardDisableButton_->OnClick.Handle(this, &EmuScreen::OnDisableCardboard);
1218+
cardboardDisableButton_->OnClick.Add([](UI::EventParams &) {
1219+
g_Config.bEnableCardboardVR = false;
1220+
return UI::EVENT_DONE;
1221+
});
12411222
cardboardDisableButton_->SetVisibility(V_GONE);
12421223
cardboardDisableButton_->SetScale(0.65f); // make it smaller - this button can be in the way otherwise.
12431224

@@ -1331,11 +1312,6 @@ UI::EventReturn EmuScreen::OnDevTools(UI::EventParams &params) {
13311312
return UI::EVENT_DONE;
13321313
}
13331314

1334-
UI::EventReturn EmuScreen::OnDisableCardboard(UI::EventParams &params) {
1335-
g_Config.bEnableCardboardVR = false;
1336-
return UI::EVENT_DONE;
1337-
}
1338-
13391315
UI::EventReturn EmuScreen::OnChat(UI::EventParams &params) {
13401316
if (chatButton_ != nullptr && chatButton_->GetVisibility() == UI::V_VISIBLE) {
13411317
chatButton_->SetVisibility(UI::V_GONE);
@@ -1357,15 +1333,6 @@ UI::EventReturn EmuScreen::OnChat(UI::EventParams &params) {
13571333
return UI::EVENT_DONE;
13581334
}
13591335

1360-
UI::EventReturn EmuScreen::OnResume(UI::EventParams &params) {
1361-
if (coreState == CoreState::CORE_RUNTIME_ERROR) {
1362-
// Force it!
1363-
Memory::MemFault_IgnoreLastCrash();
1364-
coreState = CoreState::CORE_RUNNING_CPU;
1365-
}
1366-
return UI::EVENT_DONE;
1367-
}
1368-
13691336
// To avoid including proAdhoc.h, which includes a lot of stuff.
13701337
int GetChatMessageCount();
13711338

@@ -1512,6 +1479,26 @@ void EmuScreen::darken() {
15121479
}
15131480
}
15141481

1482+
// TODO: We probably shouldn't even handle frame dumping at vblank, we can just as well handle it directly in EmuScreen.
1483+
void EmuScreen::HandleVBlank() {
1484+
#ifndef MOBILE_DEVICE
1485+
if (g_Config.bDumpFrames && !startDumping_) {
1486+
auto sy = GetI18NCategory(I18NCat::SYSTEM);
1487+
avi.Start(PSP_CoreParameter().renderWidth, PSP_CoreParameter().renderHeight);
1488+
g_OSD.Show(OSDType::MESSAGE_INFO, sy->T("AVI Dump started."), 1.0f);
1489+
startDumping_ = true;
1490+
}
1491+
if (g_Config.bDumpFrames && startDumping_) {
1492+
avi.AddFrame();
1493+
} else if (!g_Config.bDumpFrames && startDumping_) {
1494+
auto sy = GetI18NCategory(I18NCat::SYSTEM);
1495+
avi.Stop();
1496+
g_OSD.Show(OSDType::MESSAGE_INFO, sy->T("AVI Dump stopped."), 1.0f);
1497+
startDumping_ = false;
1498+
}
1499+
#endif
1500+
}
1501+
15151502
ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
15161503
// Moved from update, because we want it to be possible for booting to happen even when the screen
15171504
// is in the background, like when choosing Reset from the pause menu.
@@ -1532,7 +1519,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
15321519

15331520
ProcessQueuedVKeys();
15341521

1535-
bool skipBufferEffects = g_Config.bSkipBufferEffects;
1522+
const bool skipBufferEffects = g_Config.bSkipBufferEffects;
15361523

15371524
bool framebufferBound = false;
15381525

@@ -1631,19 +1618,6 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
16311618

16321619
PSP_UpdateDebugStats((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS || g_Config.bLogFrameDrops);
16331620

1634-
if (doFrameAdvance_.exchange(false)) {
1635-
if (!Achievements::WarnUserIfHardcoreModeActive(false)) {
1636-
// If game is running, pause emulation immediately. Otherwise, advance a single frame.
1637-
if (Core_IsStepping()) {
1638-
frameStep_ = true;
1639-
Core_Resume();
1640-
} else if (!frameStep_) {
1641-
lastNumFlips = gpuStats.numFlips;
1642-
Core_Break(BreakReason::FrameAdvance, 0);
1643-
}
1644-
}
1645-
}
1646-
16471621
// Running it early allows things like direct readbacks of buffers, things we can't do
16481622
// when we have started the final render pass. Well, technically we probably could with some manipulation
16491623
// of pass order in the render managers..
@@ -1665,7 +1639,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
16651639
switch (coreState) {
16661640
case CORE_NEXTFRAME:
16671641
// Reached the end of the frame while running at full blast, all good. Set back to running for the next frame
1668-
coreState = CORE_RUNNING_CPU;
1642+
coreState = frameStep_ ? CORE_STEPPING_CPU : CORE_RUNNING_CPU;
16691643
flags |= ScreenRenderFlags::HANDLED_THROTTLING;
16701644
Achievements::FrameUpdate();
16711645
break;
@@ -1708,6 +1682,13 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
17081682
PSP_EndHostFrame();
17091683
}
17101684

1685+
if (frameStep_) {
1686+
frameStep_ = false;
1687+
if (coreState == CORE_RUNNING_CPU) {
1688+
Core_Break(BreakReason::FrameAdvance, 0);
1689+
}
1690+
}
1691+
17111692
if (gpu && gpu->PresentedThisFrame()) {
17121693
framebufferBound = true;
17131694
}

UI/EmuScreen.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,9 @@ class EmuScreen : public UIScreen {
7474
private:
7575
void CreateViews() override;
7676
UI::EventReturn OnDevTools(UI::EventParams &params);
77-
UI::EventReturn OnDisableCardboard(UI::EventParams &params);
7877
UI::EventReturn OnChat(UI::EventParams &params);
79-
UI::EventReturn OnResume(UI::EventParams &params);
8078

79+
void HandleVBlank();
8180
void ProcessGameBoot(const Path &filename);
8281
bool bootAllowStorage(const Path &filename);
8382
void bootComplete();
@@ -132,8 +131,6 @@ class EmuScreen : public UIScreen {
132131

133132
std::string extraAssertInfoStr_;
134133

135-
std::atomic<bool> doFrameAdvance_{};
136-
137134
ControlMapper controlMapper_;
138135

139136
std::unique_ptr<ImDebugger> imDebugger_ = nullptr;
@@ -153,6 +150,10 @@ class EmuScreen : public UIScreen {
153150
std::vector<VirtKey> queuedVirtKeys_;
154151

155152
ImGuiContext *ctx_ = nullptr;
153+
154+
// TODO: Ugly!
155+
bool frameStep_ = false;
156+
bool startDumping_ = false;
156157
};
157158

158159
bool MustRunBehind();

android/build.gradle

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,8 @@ android {
7373
} else {
7474
println "(not using these:) Android Version Name, Code: " + androidGitVersion.name() + " " + androidGitVersion.code()
7575
}
76-
77-
new File("versionname.txt").write(androidGitVersion.name())
78-
new File("versioncode.txt").write(androidGitVersion.code().toString())
76+
file("versionname.txt").text = androidGitVersion.name()
77+
file("versioncode.txt").text = androidGitVersion.code().toString()
7978

8079
minSdk 9
8180
targetSdk 35

assets/lang/ru_RU.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1380,7 +1380,7 @@ Off = Выкл.
13801380
Oldest Save = Самое старое сохранение
13811381
Only JPG and PNG images are supported = Поддерживаются только изображения в формате JPG и PNG
13821382
Path does not exist! = Пути не существует!
1383-
Pause when not focused = &Пауза, когда окно не в фокусе
1383+
Pause when not focused = Пауза, когда окно не в фокусе
13841384
Plugins = Плагины
13851385
PSP Memory Stick = Карта памяти PSP
13861386
PSP Model = Модель PSP

0 commit comments

Comments
 (0)