CDROM: Special case immediate GetlocP after play/read before int

Fixes CDDA in Mad Panic Coaster.
This commit is contained in:
Connor McLaughlin 2021-10-27 20:03:55 +10:00
parent 58f05498e5
commit 25f69e7f8c
15 changed files with 68 additions and 60 deletions

View File

@ -1913,7 +1913,18 @@ void CDROM::UpdatePhysicalPosition(bool update_logical)
const u32 ticks = TimingEvents::GetGlobalTickCounter();
if (IsSeeking() || IsReadingOrPlaying() || !m_secondary_status.motor_on)
{
// set by the event
// If we're seeking+reading the first sector (no stat bits set), we need to return the set/current lba, not the last
// physical LBA. Failing to do so may result in a track-jumped position getting returned in GetlocP, which causes
// Mad Panic Coaster to go into a seek+play loop.
if ((m_secondary_status.bits & (STAT_READING | STAT_PLAYING_CDDA | STAT_MOTOR_ON)) == STAT_MOTOR_ON &&
m_current_lba != m_physical_lba)
{
Log_WarningPrintf("Jumping to hold position [%u->%u] while %s first sector", m_physical_lba, m_current_lba,
(m_drive_state == DriveState::Reading) ? "reading" : "playing");
SetHoldPosition(m_current_lba, true);
}
// Otherwise, this gets updated by the read event.
return;
}

View File

@ -456,25 +456,6 @@ bool HostInterface::SaveState(const char* filename)
return result;
}
void HostInterface::OnSystemCreated() {}
void HostInterface::OnSystemPaused(bool paused) {}
void HostInterface::OnSystemDestroyed() {}
void HostInterface::OnSystemPerformanceCountersUpdated() {}
void HostInterface::OnDisplayInvalidated() {}
void HostInterface::OnSystemStateSaved(bool global, s32 slot) {}
void HostInterface::OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code,
const std::string& game_title)
{
}
void HostInterface::OnControllerTypeChanged(u32 slot) {}
std::string HostInterface::GetShaderCacheBasePath() const
{
return GetUserDirectoryRelativePath("cache/");
@ -1197,13 +1178,3 @@ void HostInterface::RecreateSystem()
System::ResetThrottler();
OnDisplayInvalidated();
}
void HostInterface::SetMouseMode(bool relative, bool hide_cursor) {}
void HostInterface::DisplayLoadingScreen(const char* message, int progress_min /*= -1*/, int progress_max /*= -1*/,
int progress_value /*= -1*/)
{
Log_InfoPrintf("Loading: %s %d of %d-%d", message, progress_value, progress_min, progress_max);
}
void HostInterface::GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title) {}

View File

@ -88,10 +88,10 @@ public:
/// Displays a loading screen with the logo, rendered with ImGui. Use when executing possibly-time-consuming tasks
/// such as compiling shaders when starting up.
virtual void DisplayLoadingScreen(const char* message, int progress_min = -1, int progress_max = -1,
int progress_value = -1);
int progress_value = -1) = 0;
/// Retrieves information about specified game from game list.
virtual void GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title);
virtual void GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title) = 0;
/// Returns the directory where per-game memory cards will be saved.
virtual std::string GetMemoryCardDirectory() const;
@ -147,11 +147,11 @@ public:
virtual std::unique_ptr<ByteStream> OpenPackageFile(const char* path, u32 flags) = 0;
virtual void OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code,
const std::string& game_title);
virtual void OnSystemPerformanceCountersUpdated();
const std::string& game_title) = 0;
virtual void OnSystemPerformanceCountersUpdated() = 0;
/// Called when the display is invalidated (e.g. a state is loaded).
virtual void OnDisplayInvalidated();
virtual void OnDisplayInvalidated() = 0;
protected:
virtual bool AcquireHostDisplay() = 0;
@ -159,11 +159,10 @@ protected:
virtual std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) = 0;
virtual s32 GetAudioOutputVolume() const;
virtual void OnSystemCreated();
virtual void OnSystemPaused(bool paused);
virtual void OnSystemDestroyed();
virtual void OnSystemStateSaved(bool global, s32 slot);
virtual void OnControllerTypeChanged(u32 slot);
virtual void OnSystemCreated() = 0;
virtual void OnSystemPaused(bool paused) = 0;
virtual void OnSystemDestroyed() = 0;
virtual void OnControllerTypeChanged(u32 slot) = 0;
/// Restores all settings to defaults.
virtual void SetDefaultSettings(SettingsInterface& si);
@ -184,7 +183,7 @@ protected:
virtual void RecreateSystem();
/// Enables "relative" mouse mode, locking the cursor position and returning relative coordinates.
virtual void SetMouseMode(bool relative, bool hide_cursor);
virtual void SetMouseMode(bool relative, bool hide_cursor) = 0;
/// Call when host display size changes, use with "match display" aspect ratio setting.
virtual void OnHostDisplayResized();

View File

@ -89,6 +89,10 @@ void NoGUIHostInterface::SetDefaultSettings(SettingsInterface& si)
si.SetStringValue("Hotkeys", "OpenQuickMenu", "Keyboard/Escape");
}
void NoGUIHostInterface::OnDisplayInvalidated() {}
void NoGUIHostInterface::OnSystemPerformanceCountersUpdated() {}
bool NoGUIHostInterface::CreateDisplay(bool fullscreen)
{
std::optional<WindowInfo> wi = GetPlatformWindowInfo();

View File

@ -31,6 +31,9 @@ public:
void RunLater(std::function<void()> callback) override;
virtual void OnDisplayInvalidated() override;
virtual void OnSystemPerformanceCountersUpdated() override;
protected:
enum : u32
{

View File

@ -260,6 +260,8 @@ std::optional<CommonHostInterface::HostKeyCode> SDLHostInterface::GetHostKeyCode
return static_cast<HostKeyCode>(*code);
}
void SDLHostInterface::SetMouseMode(bool relative, bool hide_cursor) {}
void SDLHostInterface::PollAndUpdate()
{
// Process SDL events before the controller interface can steal them.

View File

@ -21,6 +21,8 @@ public:
bool SetFullscreen(bool enabled) override;
protected:
void SetMouseMode(bool relative, bool hide_cursor) override;
void PollAndUpdate() override;
std::optional<HostKeyCode> GetHostKeyCode(const std::string_view key_code) const override;

View File

@ -111,6 +111,8 @@ void VTYHostInterface::PollAndUpdate()
NoGUIHostInterface::PollAndUpdate();
}
void VTYHostInterface::SetMouseMode(bool relative, bool hide_cursor) {}
void VTYHostInterface::OpenEVDevFDs()
{
for (int i = 0; i < 1000; i++)

View File

@ -29,6 +29,8 @@ protected:
void PollAndUpdate() override;
void SetMouseMode(bool relative, bool hide_cursor) override;
private:
static void SIGTERMHandler(int sig);

View File

@ -57,6 +57,8 @@ bool Win32HostInterface::RegisterWindowClass()
return true;
}
void Win32HostInterface::SetMouseMode(bool relative, bool hide_cursor) {}
bool Win32HostInterface::CreatePlatformWindow()
{
m_hwnd = CreateWindowExW(WS_EX_CLIENTEDGE, WINDOW_CLASS_NAME, L"DuckStation", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,

View File

@ -16,6 +16,8 @@ public:
static std::unique_ptr<NoGUIHostInterface> Create();
protected:
void SetMouseMode(bool relative, bool hide_cursor) override;
bool CreatePlatformWindow() override;
void DestroyPlatformWindow() override;
std::optional<WindowInfo> GetPlatformWindowInfo() override;

View File

@ -784,8 +784,6 @@ void QtHostInterface::OnSystemDestroyed()
void QtHostInterface::OnSystemPerformanceCountersUpdated()
{
HostInterface::OnSystemPerformanceCountersUpdated();
GPURenderer renderer = GPURenderer::Count;
u32 render_width = 0;
u32 render_height = 0;

View File

@ -104,8 +104,6 @@ void RegTestHostInterface::GetGameInfo(const char* path, CDImage* image, std::st
void RegTestHostInterface::OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code,
const std::string& game_title)
{
HostInterface::OnRunningGameChanged(path, image, game_code, game_title);
Log_InfoPrintf("Game Path: %s", path.c_str());
Log_InfoPrintf("Game Code: %s", game_code.c_str());
Log_InfoPrintf("Game Title: %s", game_title.c_str());
@ -128,6 +126,10 @@ void RegTestHostInterface::OnRunningGameChanged(const std::string& path, CDImage
UpdateSettings();
}
void RegTestHostInterface::OnSystemPerformanceCountersUpdated() {}
void RegTestHostInterface::OnDisplayInvalidated() {}
std::string RegTestHostInterface::GetStringSettingValue(const char* section, const char* key,
const char* default_value /*= ""*/)
{
@ -284,6 +286,16 @@ std::unique_ptr<AudioStream> RegTestHostInterface::CreateAudioStream(AudioBacken
return AudioStream::CreateNullAudioStream();
}
void RegTestHostInterface::OnSystemCreated() {}
void RegTestHostInterface::OnSystemPaused(bool paused) {}
void RegTestHostInterface::OnSystemDestroyed() {}
void RegTestHostInterface::OnControllerTypeChanged(u32 slot) {}
void RegTestHostInterface::SetMouseMode(bool relative, bool hide_cursor) {}
static void PrintCommandLineVersion()
{
const bool was_console_enabled = Log::IsConsoleOutputEnabled();

View File

@ -2,7 +2,7 @@
#include "core/host_interface.h"
#include "regtest_settings_interface.h"
class RegTestHostInterface : public HostInterface
class RegTestHostInterface final : public HostInterface
{
public:
RegTestHostInterface();
@ -34,12 +34,22 @@ public:
std::unique_ptr<ByteStream> OpenPackageFile(const char* path, u32 flags) override;
void OnSystemPerformanceCountersUpdated() override;
void OnDisplayInvalidated() override;
protected:
bool AcquireHostDisplay() override;
void ReleaseHostDisplay() override;
std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) override;
void OnSystemCreated() override;
void OnSystemPaused(bool paused) override;
void OnSystemDestroyed() override;
void OnControllerTypeChanged(u32 slot) override;
void SetMouseMode(bool relative, bool hide_cursor) override;
private:
void LoadGameSettingsDatabase();
void InitializeSettings();

View File

@ -840,11 +840,7 @@ bool CommonHostInterface::SaveState(bool global, s32 slot)
std::string save_path = global ? GetGlobalSaveStateFileName(slot) : GetGameSaveStateFileName(code.c_str(), slot);
RenameCurrentSaveStateToBackup(save_path.c_str());
if (!SaveState(save_path.c_str()))
return false;
OnSystemStateSaved(global, slot);
return true;
return SaveState(save_path.c_str());
}
bool CommonHostInterface::CanResumeSystemFromFile(const char* filename)
@ -1090,8 +1086,6 @@ void CommonHostInterface::SetUserDirectory()
void CommonHostInterface::OnSystemCreated()
{
HostInterface::OnSystemCreated();
if (m_fullscreen_ui_enabled)
FullscreenUI::SystemCreated();
@ -1127,8 +1121,6 @@ void CommonHostInterface::OnSystemDestroyed()
if (m_display)
m_display->SetDisplayMaxFPS(0.0f);
HostInterface::OnSystemDestroyed();
if (m_fullscreen_ui_enabled)
FullscreenUI::SystemDestroyed();
@ -1139,8 +1131,6 @@ void CommonHostInterface::OnSystemDestroyed()
void CommonHostInterface::OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code,
const std::string& game_title)
{
HostInterface::OnRunningGameChanged(path, image, game_code, game_title);
if (g_settings.apply_game_settings)
ApplySettings(true);
@ -1166,8 +1156,6 @@ void CommonHostInterface::OnRunningGameChanged(const std::string& path, CDImage*
void CommonHostInterface::OnControllerTypeChanged(u32 slot)
{
HostInterface::OnControllerTypeChanged(slot);
UpdateInputMap();
}
@ -2821,8 +2809,8 @@ bool CommonHostInterface::ApplyInputProfile(const char* profile_path)
continue;
}
// We don't need to call ControllerTypeChanged here because we're already updating the input map.
g_settings.controller_types[controller_index - 1] = *ctype;
HostInterface::OnControllerTypeChanged(controller_index - 1);
m_settings_interface->SetStringValue(section_name, "Type", Settings::GetControllerTypeName(*ctype));