CDROM: Implement SetSession command

This commit is contained in:
Connor McLaughlin 2020-03-07 15:10:19 +10:00
parent d0f420de10
commit c700913322
3 changed files with 76 additions and 20 deletions

View file

@ -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<std::array<s16, 29>, 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<const char*, 10> drive_state_names = {{"Idle", "Spinning Up", "Seeking (Physical)",
"Seeking (Logical)", "Reading ID", "Reading TOC",
"Reading", "Playing", "Pausing", "Stopping"}};
static constexpr std::array<const char*, 11> drive_state_names = {
{"Idle", "Spinning Up", "Seeking (Physical)", "Seeking (Logical)", "Reading ID", "Reading TOC", "Reading",
"Playing", "Pausing", "Stopping", "Changing Session"}};
ImGui::Columns(3);

View file

@ -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<std::array<u8, 2>, 2> m_cd_audio_volume_matrix{};
std::array<std::array<u8, 2>, 2> m_next_cd_audio_volume_matrix{};

View file

@ -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;