diff --git a/src/core/cdrom.cpp b/src/core/cdrom.cpp index 22d3935b2..da5295538 100644 --- a/src/core/cdrom.cpp +++ b/src/core/cdrom.cpp @@ -112,6 +112,7 @@ bool CDROM::DoState(StateWrapper& sw) sw.DoBytes(&m_last_subq, sizeof(m_last_subq)); sw.Do(&m_last_cdda_report_frame_nibble); sw.Do(&m_play_track_number_bcd); + sw.Do(&m_async_command_parameter); sw.Do(&m_cd_audio_volume_matrix); sw.Do(&m_next_cd_audio_volume_matrix); sw.Do(&m_xa_last_samples); @@ -464,14 +465,14 @@ void CDROM::SendErrorResponse(u8 reason /*= 0x80*/) { m_response_fifo.Push(m_secondary_status.bits | 0x01); m_response_fifo.Push(reason); - SetInterrupt(Interrupt::INT5); + SetInterrupt(Interrupt::Error); } void CDROM::SendAsyncErrorResponse(u8 reason /*= 0x80*/) { m_async_response_fifo.Push(m_secondary_status.bits | 0x01); m_async_response_fifo.Push(reason); - SetAsyncInterrupt(Interrupt::INT5); + SetAsyncInterrupt(Interrupt::Error); } void CDROM::UpdateStatusRegister() @@ -674,6 +675,32 @@ void CDROM::ExecuteCommand() return; } + case Command::SetSession: + { + const u8 session = m_param_fifo.IsEmpty() ? 0 : m_param_fifo.Peek(0); + Log_DebugPrintf("CDROM SetSession command, session=%u", session); + + if (!HasMedia() || m_drive_state == DriveState::Reading || m_drive_state == DriveState::Playing) + { + SendErrorResponse(0x80); + } + else if (session == 0) + { + SendErrorResponse(0x10); + } + else + { + SendACKAndStat(); + + m_async_command_parameter = session; + m_drive_state = DriveState::ChangingSession; + m_drive_event->Schedule(MASTER_CLOCK / 2); // half a second + } + + EndCommand(); + return; + } + case Command::ReadN: case Command::ReadS: { @@ -1011,6 +1038,10 @@ void CDROM::ExecuteDrive(TickCount ticks_late) DoSectorRead(); break; + case DriveState::ChangingSession: + DoChangeSessionComplete(); + break; + case DriveState::Idle: default: break; @@ -1114,7 +1145,7 @@ void CDROM::DoSpinUpComplete() m_async_response_fifo.Clear(); m_async_response_fifo.Push(m_secondary_status.bits); - SetAsyncInterrupt(Interrupt::INT2); + SetAsyncInterrupt(Interrupt::Complete); } void CDROM::DoSeekComplete(TickCount ticks_late) @@ -1164,7 +1195,7 @@ void CDROM::DoSeekComplete(TickCount ticks_late) else { m_async_response_fifo.Push(m_secondary_status.bits); - SetAsyncInterrupt(Interrupt::INT2); + SetAsyncInterrupt(Interrupt::Complete); } } else @@ -1192,7 +1223,7 @@ void CDROM::DoPauseComplete() m_async_response_fifo.Clear(); m_async_response_fifo.Push(m_secondary_status.bits); - SetAsyncInterrupt(Interrupt::INT2); + SetAsyncInterrupt(Interrupt::Complete); } void CDROM::DoStopComplete() @@ -1208,7 +1239,29 @@ void CDROM::DoStopComplete() m_async_response_fifo.Clear(); m_async_response_fifo.Push(m_secondary_status.bits); - SetAsyncInterrupt(Interrupt::INT2); + SetAsyncInterrupt(Interrupt::Complete); +} + +void CDROM::DoChangeSessionComplete() +{ + Log_DebugPrintf("Changing session complete"); + m_drive_state = DriveState::Idle; + m_drive_event->Deactivate(); + m_secondary_status.ClearActiveBits(); + m_secondary_status.motor_on = true; + + m_async_response_fifo.Clear(); + if (m_async_command_parameter == 0x01) + { + m_async_response_fifo.Push(m_secondary_status.bits); + SetAsyncInterrupt(Interrupt::Complete); + } + else + { + // we don't emulate multisession discs.. for now + m_secondary_status.seek_error = true; + SendAsyncErrorResponse(0x40); + } } void CDROM::DoIDRead() @@ -1226,7 +1279,7 @@ void CDROM::DoIDRead() m_async_response_fifo.Clear(); m_async_response_fifo.Push(m_secondary_status.bits); m_async_response_fifo.PushRange(response2, countof(response2)); - SetAsyncInterrupt(Interrupt::INT2); + SetAsyncInterrupt(Interrupt::Complete); } void CDROM::DoTOCRead() @@ -1236,7 +1289,7 @@ void CDROM::DoTOCRead() m_drive_event->Deactivate(); m_async_response_fifo.Clear(); m_async_response_fifo.Push(m_secondary_status.bits); - SetAsyncInterrupt(Interrupt::INT2); + SetAsyncInterrupt(Interrupt::Complete); } void CDROM::DoSectorRead() @@ -1265,7 +1318,7 @@ void CDROM::DoSectorRead() ClearAsyncInterrupt(); m_async_response_fifo.Push(m_secondary_status.bits); - SetAsyncInterrupt(Interrupt::INT4); + SetAsyncInterrupt(Interrupt::DataEnd); m_secondary_status.ClearActiveBits(); m_drive_state = DriveState::Idle; @@ -1375,7 +1428,7 @@ void CDROM::ProcessDataSector(const u8* raw_sector, const CDImage::SubChannelQ& } m_async_response_fifo.Push(m_secondary_status.bits); - SetAsyncInterrupt(Interrupt::INT1); + SetAsyncInterrupt(Interrupt::DataReady); } static std::array, 7> s_zigzag_table = { @@ -1550,7 +1603,7 @@ void CDROM::ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ& m_async_response_fifo.Push(0); // peak low m_async_response_fifo.Push(0); // peak high - SetAsyncInterrupt(Interrupt::INT1); + SetAsyncInterrupt(Interrupt::DataReady); } } @@ -1632,9 +1685,9 @@ void CDROM::DrawDebugWindow() if (ImGui::CollapsingHeader("Status/Mode", ImGuiTreeNodeFlags_DefaultOpen)) { - static constexpr std::array drive_state_names = {{"Idle", "Spinning Up", "Seeking (Physical)", - "Seeking (Logical)", "Reading ID", "Reading TOC", - "Reading", "Playing", "Pausing", "Stopping"}}; + static constexpr std::array drive_state_names = { + {"Idle", "Spinning Up", "Seeking (Physical)", "Seeking (Logical)", "Reading ID", "Reading TOC", "Reading", + "Playing", "Pausing", "Stopping", "Changing Session"}}; ImGui::Columns(3); diff --git a/src/core/cdrom.h b/src/core/cdrom.h index f22c6ba6a..baab989af 100644 --- a/src/core/cdrom.h +++ b/src/core/cdrom.h @@ -64,11 +64,11 @@ private: enum class Interrupt : u8 { - INT1 = 0x01, - INT2 = 0x02, + DataReady = 0x01, + Complete = 0x02, ACK = 0x03, - INT4 = 0x04, - INT5 = 0x05 + DataEnd = 0x04, + Error = 0x05 }; enum class Command : u16 @@ -120,7 +120,8 @@ private: Reading, Playing, Pausing, - Stopping + Stopping, + ChangingSession }; union StatusRegister @@ -208,6 +209,7 @@ private: void DoSeekComplete(TickCount ticks_late); void DoPauseComplete(); void DoStopComplete(); + void DoChangeSessionComplete(); void DoIDRead(); void DoTOCRead(); void DoSectorRead(); @@ -253,6 +255,7 @@ private: CDImage::SubChannelQ m_last_subq{}; u8 m_last_cdda_report_frame_nibble = 0xFF; u8 m_play_track_number_bcd = 0xFF; + u8 m_async_command_parameter = 0x00; std::array, 2> m_cd_audio_volume_matrix{}; std::array, 2> m_next_cd_audio_volume_matrix{}; diff --git a/src/core/save_state_version.h b/src/core/save_state_version.h index b73137f3e..4798136cf 100644 --- a/src/core/save_state_version.h +++ b/src/core/save_state_version.h @@ -2,4 +2,4 @@ #include "types.h" static constexpr u32 SAVE_STATE_MAGIC = 0x43435544; -static constexpr u32 SAVE_STATE_VERSION = 3; +static constexpr u32 SAVE_STATE_VERSION = 4;