CDROM: Simulate holding position for GetlocP
Fixes lockups in Tomb Raider.
This commit is contained in:
parent
0d13e1013d
commit
2c1999e622
|
@ -127,6 +127,7 @@ void CDROM::SoftReset()
|
|||
m_pending_async_interrupt = 0;
|
||||
m_setloc_position = {};
|
||||
m_current_lba = 0;
|
||||
ResetPhysicalPosition();
|
||||
if (m_reader.HasMedia())
|
||||
m_reader.QueueReadSector(m_current_lba);
|
||||
m_seek_start_lba = 0;
|
||||
|
@ -185,6 +186,8 @@ bool CDROM::DoState(StateWrapper& sw)
|
|||
sw.Do(&m_current_lba);
|
||||
sw.Do(&m_seek_start_lba);
|
||||
sw.Do(&m_seek_end_lba);
|
||||
sw.DoEx(&m_physical_lba, 49, m_current_lba);
|
||||
sw.DoEx(&m_physical_lba_update_tick, 49, static_cast<u32>(0));
|
||||
sw.Do(&m_setloc_pending);
|
||||
sw.Do(&m_read_after_seek);
|
||||
sw.Do(&m_play_after_seek);
|
||||
|
@ -203,8 +206,7 @@ bool CDROM::DoState(StateWrapper& sw)
|
|||
sw.Do(&m_play_track_number_bcd);
|
||||
sw.Do(&m_async_command_parameter);
|
||||
|
||||
// TODO: Uncomment on the next save state version bump.
|
||||
// sw.Do(&m_fast_forward_rate);
|
||||
sw.DoEx(&m_fast_forward_rate, 49, static_cast<s8>(0));
|
||||
|
||||
sw.Do(&m_cd_audio_volume_matrix);
|
||||
sw.Do(&m_next_cd_audio_volume_matrix);
|
||||
|
@ -236,7 +238,6 @@ bool CDROM::DoState(StateWrapper& sw)
|
|||
m_reader.QueueReadSector(requested_sector);
|
||||
UpdateCommandEvent();
|
||||
m_drive_event->SetState(!IsDriveIdle());
|
||||
m_fast_forward_rate = 0;
|
||||
}
|
||||
|
||||
return !sw.HasError();
|
||||
|
@ -283,6 +284,7 @@ void CDROM::InsertMedia(std::unique_ptr<CDImage> media)
|
|||
|
||||
m_reader.SetMedia(std::move(media));
|
||||
m_current_lba = 0;
|
||||
ResetPhysicalPosition();
|
||||
}
|
||||
|
||||
std::unique_ptr<CDImage> CDROM::RemoveMedia(bool force /* = false */)
|
||||
|
@ -1166,12 +1168,13 @@ void CDROM::ExecuteCommand()
|
|||
{
|
||||
if (IsSeeking())
|
||||
UpdatePositionWhileSeeking();
|
||||
else
|
||||
UpdatePhysicalPosition();
|
||||
|
||||
Log_DebugPrintf("CDROM GetlocP command - T%02x I%02x R[%02x:%02x:%02x] A[%02x:%02x:%02x]",
|
||||
m_last_subq.track_number_bcd, m_last_subq.index_number_bcd, m_last_subq.relative_minute_bcd,
|
||||
m_last_subq.relative_second_bcd, m_last_subq.relative_frame_bcd,
|
||||
m_last_subq.absolute_minute_bcd, m_last_subq.absolute_second_bcd,
|
||||
m_last_subq.absolute_frame_bcd);
|
||||
Log_DevPrintf("CDROM GetlocP command - T%02x I%02x R[%02x:%02x:%02x] A[%02x:%02x:%02x]",
|
||||
m_last_subq.track_number_bcd, m_last_subq.index_number_bcd, m_last_subq.relative_minute_bcd,
|
||||
m_last_subq.relative_second_bcd, m_last_subq.relative_frame_bcd, m_last_subq.absolute_minute_bcd,
|
||||
m_last_subq.absolute_second_bcd, m_last_subq.absolute_frame_bcd);
|
||||
|
||||
m_response_fifo.Push(m_last_subq.track_number_bcd);
|
||||
m_response_fifo.Push(m_last_subq.index_number_bcd);
|
||||
|
@ -1582,6 +1585,58 @@ void CDROM::UpdatePositionWhileSeeking()
|
|||
{
|
||||
m_last_subq = subq;
|
||||
m_current_lba = current_lba;
|
||||
ResetPhysicalPosition();
|
||||
}
|
||||
}
|
||||
|
||||
void CDROM::ResetPhysicalPosition()
|
||||
{
|
||||
const u32 ticks = TimingEvents::GetGlobalTickCounter();
|
||||
m_physical_lba = m_physical_lba;
|
||||
m_physical_lba_update_tick = ticks;
|
||||
}
|
||||
|
||||
void CDROM::UpdatePhysicalPosition()
|
||||
{
|
||||
const u32 ticks = TimingEvents::GetGlobalTickCounter();
|
||||
if (IsSeeking() || IsReadingOrPlaying() || !m_secondary_status.motor_on)
|
||||
{
|
||||
// set by the event
|
||||
return;
|
||||
}
|
||||
|
||||
const CDImage::LBA SECTORS_TO_JUMP_BACK = 9;
|
||||
|
||||
const u32 diff = ticks - m_physical_lba_update_tick;
|
||||
const u32 sector_diff = diff / GetTicksForRead();
|
||||
if (sector_diff > 0)
|
||||
{
|
||||
const CDImage::LBA base =
|
||||
(m_current_lba >= SECTORS_TO_JUMP_BACK) ? (m_current_lba - SECTORS_TO_JUMP_BACK) : m_current_lba;
|
||||
if (m_physical_lba < base)
|
||||
m_physical_lba = base;
|
||||
|
||||
const CDImage::LBA old_offset = m_physical_lba - base;
|
||||
const CDImage::LBA new_offset = (old_offset + sector_diff) % SECTORS_TO_JUMP_BACK;
|
||||
const CDImage::LBA new_physical_lba = base + new_offset;
|
||||
#ifdef _DEBUG
|
||||
const CDImage::Position old_pos(CDImage::Position::FromLBA(m_physical_lba));
|
||||
const CDImage::Position new_pos(CDImage::Position::FromLBA(new_physical_lba));
|
||||
Log_DevPrintf("Tick diff %u, sector diff %u, old pos %02u:%02u:%02u, new pos %02u:%02u:%02u", diff, sector_diff,
|
||||
old_pos.minute, old_pos.second, old_pos.frame, new_pos.minute, new_pos.second, new_pos.frame);
|
||||
#endif
|
||||
if (m_physical_lba != new_physical_lba)
|
||||
{
|
||||
m_physical_lba = new_physical_lba;
|
||||
|
||||
CDImage::SubChannelQ subq;
|
||||
if (!m_reader.ReadSectorUncached(new_physical_lba, &subq, nullptr))
|
||||
Log_ErrorPrintf("Failed to read subq for sector %u for physical position", new_physical_lba);
|
||||
else if (subq.IsCRCValid())
|
||||
m_last_subq = subq;
|
||||
|
||||
m_physical_lba_update_tick = ticks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1615,6 +1670,7 @@ void CDROM::DoResetComplete(TickCount ticks_late)
|
|||
}
|
||||
|
||||
m_current_lba = 0;
|
||||
ResetPhysicalPosition();
|
||||
m_reader.QueueReadSector(0);
|
||||
|
||||
m_async_response_fifo.Clear();
|
||||
|
@ -1683,6 +1739,7 @@ void CDROM::DoSeekComplete(TickCount ticks_late)
|
|||
}
|
||||
|
||||
m_current_lba = m_reader.GetLastReadSector();
|
||||
ResetPhysicalPosition();
|
||||
|
||||
if (seek_okay)
|
||||
{
|
||||
|
@ -1782,6 +1839,7 @@ void CDROM::DoIDRead()
|
|||
{
|
||||
// this is where it would get read from the start of the disc?
|
||||
m_current_lba = 0;
|
||||
ResetPhysicalPosition();
|
||||
m_reader.QueueReadSector(0);
|
||||
|
||||
if (!IsMediaPS1Disc())
|
||||
|
@ -1839,6 +1897,7 @@ void CDROM::DoSectorRead()
|
|||
|
||||
// TODO: Queue the next read here and swap the buffer.
|
||||
m_current_lba = m_reader.GetLastReadSector();
|
||||
ResetPhysicalPosition();
|
||||
|
||||
// TODO: Error handling
|
||||
const CDImage::SubChannelQ& subq = m_reader.GetSectorSubQ();
|
||||
|
|
|
@ -271,6 +271,8 @@ private:
|
|||
void StopReadingWithDataEnd();
|
||||
void BeginSeeking(bool logical, bool read_after_seek, bool play_after_seek);
|
||||
void UpdatePositionWhileSeeking();
|
||||
void ResetPhysicalPosition();
|
||||
void UpdatePhysicalPosition();
|
||||
void ResetCurrentXAFile();
|
||||
void ResetAudioDecoder();
|
||||
void LoadDataFIFO();
|
||||
|
@ -299,6 +301,8 @@ private:
|
|||
CDImage::LBA m_current_lba{};
|
||||
CDImage::LBA m_seek_start_lba{};
|
||||
CDImage::LBA m_seek_end_lba{};
|
||||
CDImage::LBA m_physical_lba{};
|
||||
u32 m_physical_lba_update_tick = 0;
|
||||
bool m_setloc_pending = false;
|
||||
bool m_read_after_seek = false;
|
||||
bool m_play_after_seek = false;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "types.h"
|
||||
|
||||
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 48;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 49;
|
||||
static constexpr u32 SAVE_STATE_MINIMUM_VERSION = 42;
|
||||
|
||||
static_assert(SAVE_STATE_VERSION >= SAVE_STATE_MINIMUM_VERSION);
|
||||
|
|
Loading…
Reference in New Issue