CDROM: Trigger INT5 on shell open
This behaviour has been verified on console. Fixes disc swap detection in "Arc the Lad III"
This commit is contained in:
parent
2292292956
commit
0e0bd2852f
|
@ -43,6 +43,7 @@ void CDROM::SoftReset()
|
||||||
m_drive_event->Deactivate();
|
m_drive_event->Deactivate();
|
||||||
m_status.bits = 0;
|
m_status.bits = 0;
|
||||||
m_secondary_status.bits = 0;
|
m_secondary_status.bits = 0;
|
||||||
|
m_secondary_status.motor_on = HasMedia();
|
||||||
m_mode.bits = 0;
|
m_mode.bits = 0;
|
||||||
m_interrupt_enable_register = INTERRUPT_REGISTER_MASK;
|
m_interrupt_enable_register = INTERRUPT_REGISTER_MASK;
|
||||||
m_interrupt_flag_register = 0;
|
m_interrupt_flag_register = 0;
|
||||||
|
@ -170,6 +171,9 @@ void CDROM::InsertMedia(std::unique_ptr<CDImage> media)
|
||||||
Log_InfoPrintf("Inserting new media, disc region: %s, console region: %s", Settings::GetDiscRegionName(m_disc_region),
|
Log_InfoPrintf("Inserting new media, disc region: %s, console region: %s", Settings::GetDiscRegionName(m_disc_region),
|
||||||
Settings::GetConsoleRegionName(m_system->GetRegion()));
|
Settings::GetConsoleRegionName(m_system->GetRegion()));
|
||||||
|
|
||||||
|
// motor automatically spins up
|
||||||
|
m_secondary_status.motor_on = true;
|
||||||
|
|
||||||
m_reader.SetMedia(std::move(media));
|
m_reader.SetMedia(std::move(media));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,17 +185,19 @@ void CDROM::RemoveMedia()
|
||||||
Log_InfoPrintf("Removing CD...");
|
Log_InfoPrintf("Removing CD...");
|
||||||
m_reader.RemoveMedia();
|
m_reader.RemoveMedia();
|
||||||
|
|
||||||
|
m_secondary_status.motor_on = false;
|
||||||
m_secondary_status.shell_open = true;
|
m_secondary_status.shell_open = true;
|
||||||
|
m_secondary_status.ClearActiveBits();
|
||||||
m_disc_region = DiscRegion::Other;
|
m_disc_region = DiscRegion::Other;
|
||||||
|
|
||||||
// If the drive was doing anything, we need to abort the command.
|
// If the drive was doing anything, we need to abort the command.
|
||||||
if (m_drive_state != DriveState::Idle)
|
|
||||||
{
|
|
||||||
// TODO: Verify this.
|
|
||||||
Log_WarningPrintf("Aborting drive operation");
|
|
||||||
SendAsyncErrorResponse(0x08);
|
|
||||||
m_drive_state = DriveState::Idle;
|
m_drive_state = DriveState::Idle;
|
||||||
}
|
m_command = Command::None;
|
||||||
|
m_command_event->Deactivate();
|
||||||
|
m_drive_event->Deactivate();
|
||||||
|
|
||||||
|
// The console sends an interrupt when the shell is opened regardless of whether a command was executing.
|
||||||
|
SendAsyncErrorResponse(STAT_ERROR, 0x08);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::SetUseReadThread(bool enabled)
|
void CDROM::SetUseReadThread(bool enabled)
|
||||||
|
@ -761,12 +767,12 @@ void CDROM::ExecuteCommand()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::Init:
|
case Command::Reset:
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("CDROM init command");
|
Log_DebugPrintf("CDROM reset command");
|
||||||
SendACKAndStat();
|
SendACKAndStat();
|
||||||
|
|
||||||
m_drive_state = DriveState::SpinningUp;
|
m_drive_state = DriveState::Resetting;
|
||||||
m_drive_event->Schedule(80000);
|
m_drive_event->Schedule(80000);
|
||||||
|
|
||||||
EndCommand();
|
EndCommand();
|
||||||
|
@ -785,7 +791,7 @@ void CDROM::ExecuteCommand()
|
||||||
{
|
{
|
||||||
SendACKAndStat();
|
SendACKAndStat();
|
||||||
|
|
||||||
m_drive_state = DriveState::SpinningUp;
|
m_drive_state = DriveState::Resetting;
|
||||||
m_drive_event->Schedule(80000);
|
m_drive_event->Schedule(80000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,8 +1039,8 @@ void CDROM::ExecuteDrive(TickCount ticks_late)
|
||||||
{
|
{
|
||||||
switch (m_drive_state)
|
switch (m_drive_state)
|
||||||
{
|
{
|
||||||
case DriveState::SpinningUp:
|
case DriveState::Resetting:
|
||||||
DoSpinUpComplete();
|
DoResetComplete(ticks_late);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DriveState::SeekingPhysical:
|
case DriveState::SeekingPhysical:
|
||||||
|
@ -1164,7 +1170,7 @@ void CDROM::BeginSeeking(bool logical, bool read_after_seek, bool play_after_see
|
||||||
m_reader.QueueReadSector(m_last_requested_sector);
|
m_reader.QueueReadSector(m_last_requested_sector);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::DoSpinUpComplete()
|
void CDROM::DoResetComplete(TickCount ticks_late)
|
||||||
{
|
{
|
||||||
m_drive_state = DriveState::Idle;
|
m_drive_state = DriveState::Idle;
|
||||||
m_drive_event->Deactivate();
|
m_drive_event->Deactivate();
|
||||||
|
@ -1174,9 +1180,24 @@ void CDROM::DoSpinUpComplete()
|
||||||
m_mode.bits = 0;
|
m_mode.bits = 0;
|
||||||
m_mode.read_raw_sector = true;
|
m_mode.read_raw_sector = true;
|
||||||
|
|
||||||
|
if (!HasMedia())
|
||||||
|
{
|
||||||
|
Log_DevPrintf("CDROM reset - no disc");
|
||||||
|
m_secondary_status.shell_open = true;
|
||||||
|
m_secondary_status.motor_on = false;
|
||||||
|
SendAsyncErrorResponse(STAT_ERROR, 0x08);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_async_response_fifo.Clear();
|
m_async_response_fifo.Clear();
|
||||||
m_async_response_fifo.Push(m_secondary_status.bits);
|
m_async_response_fifo.Push(m_secondary_status.bits);
|
||||||
SetAsyncInterrupt(Interrupt::Complete);
|
SetAsyncInterrupt(Interrupt::Complete);
|
||||||
|
|
||||||
|
if (!HasMedia())
|
||||||
|
{
|
||||||
|
m_secondary_status.motor_on = false;
|
||||||
|
m_secondary_status.shell_open = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::DoSeekComplete(TickCount ticks_late)
|
void CDROM::DoSeekComplete(TickCount ticks_late)
|
||||||
|
@ -1329,6 +1350,7 @@ void CDROM::DoTOCRead()
|
||||||
Log_DebugPrintf("TOC read complete");
|
Log_DebugPrintf("TOC read complete");
|
||||||
m_drive_state = DriveState::Idle;
|
m_drive_state = DriveState::Idle;
|
||||||
m_drive_event->Deactivate();
|
m_drive_event->Deactivate();
|
||||||
|
|
||||||
m_async_response_fifo.Clear();
|
m_async_response_fifo.Clear();
|
||||||
m_async_response_fifo.Push(m_secondary_status.bits);
|
m_async_response_fifo.Push(m_secondary_status.bits);
|
||||||
SetAsyncInterrupt(Interrupt::Complete);
|
SetAsyncInterrupt(Interrupt::Complete);
|
||||||
|
@ -1754,7 +1776,7 @@ void CDROM::DrawDebugWindow()
|
||||||
if (ImGui::CollapsingHeader("Status/Mode", ImGuiTreeNodeFlags_DefaultOpen))
|
if (ImGui::CollapsingHeader("Status/Mode", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
{
|
{
|
||||||
static constexpr std::array<const char*, 11> drive_state_names = {
|
static constexpr std::array<const char*, 11> drive_state_names = {
|
||||||
{"Idle", "Spinning Up", "Seeking (Physical)", "Seeking (Logical)", "Reading ID", "Reading TOC", "Reading",
|
{"Idle", "Resetting", "Seeking (Physical)", "Seeking (Logical)", "Reading ID", "Reading TOC", "Reading",
|
||||||
"Playing", "Pausing", "Stopping", "Changing Session"}};
|
"Playing", "Pausing", "Stopping", "Changing Session"}};
|
||||||
|
|
||||||
ImGui::Columns(3);
|
ImGui::Columns(3);
|
||||||
|
|
|
@ -83,7 +83,7 @@ private:
|
||||||
MotorOn = 0x07,
|
MotorOn = 0x07,
|
||||||
Stop = 0x08,
|
Stop = 0x08,
|
||||||
Pause = 0x09,
|
Pause = 0x09,
|
||||||
Init = 0x0A,
|
Reset = 0x0A,
|
||||||
Mute = 0x0B,
|
Mute = 0x0B,
|
||||||
Demute = 0x0C,
|
Demute = 0x0C,
|
||||||
Setfilter = 0x0D,
|
Setfilter = 0x0D,
|
||||||
|
@ -101,7 +101,7 @@ private:
|
||||||
Test = 0x19,
|
Test = 0x19,
|
||||||
GetID = 0x1A,
|
GetID = 0x1A,
|
||||||
ReadS = 0x1B,
|
ReadS = 0x1B,
|
||||||
Reset = 0x1C,
|
Init = 0x1C,
|
||||||
GetQ = 0x1D,
|
GetQ = 0x1D,
|
||||||
ReadTOC = 0x1E,
|
ReadTOC = 0x1E,
|
||||||
VideoCD = 0x1F,
|
VideoCD = 0x1F,
|
||||||
|
@ -112,7 +112,7 @@ private:
|
||||||
enum class DriveState : u8
|
enum class DriveState : u8
|
||||||
{
|
{
|
||||||
Idle,
|
Idle,
|
||||||
SpinningUp,
|
Resetting,
|
||||||
SeekingPhysical,
|
SeekingPhysical,
|
||||||
SeekingLogical,
|
SeekingLogical,
|
||||||
ReadingID,
|
ReadingID,
|
||||||
|
@ -215,7 +215,7 @@ private:
|
||||||
void ExecuteDrive(TickCount ticks_late);
|
void ExecuteDrive(TickCount ticks_late);
|
||||||
void BeginReading(TickCount ticks_late = 0);
|
void BeginReading(TickCount ticks_late = 0);
|
||||||
void BeginPlaying(u8 track_bcd, TickCount ticks_late = 0);
|
void BeginPlaying(u8 track_bcd, TickCount ticks_late = 0);
|
||||||
void DoSpinUpComplete();
|
void DoResetComplete(TickCount ticks_late);
|
||||||
void DoSeekComplete(TickCount ticks_late);
|
void DoSeekComplete(TickCount ticks_late);
|
||||||
void DoPauseComplete();
|
void DoPauseComplete();
|
||||||
void DoStopComplete();
|
void DoStopComplete();
|
||||||
|
|
Loading…
Reference in New Issue