Skip to content

Let derived CDROM devices asynchronously lag their calls #2622

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion src/dos/cdrom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@

#include "SDL.h"

#include "callback.h"
#include "dosbox.h"
#include "pic.h"
#include "string_utils.h"

CDROM_Interface_SDL::CDROM_Interface_SDL()
Expand Down Expand Up @@ -78,6 +80,7 @@ bool CDROM_Interface_SDL::GetAudioTracks(uint8_t &stTrack, uint8_t &end, TMSF &l
stTrack = 1;
end = cd->numtracks;
leadOut = frames_to_msf(cd->track[cd->numtracks].offset);
LagDriveResponse();
}
return CD_INDRIVE(SDL_CDStatus(cd));
}
Expand All @@ -91,6 +94,7 @@ bool CDROM_Interface_SDL::GetAudioTrackInfo(uint8_t track,
attr = cd->track[track - 1].type << 4; // sdl uses 0 for audio
// and 4 for data. instead
// of 0x00 and 0x40
LagDriveResponse();
}
return CD_INDRIVE(SDL_CDStatus(cd));
}
Expand All @@ -107,6 +111,7 @@ bool CDROM_Interface_SDL::GetAudioSub(unsigned char &attr,
attr = cd->track[track].type << 4;
relPos = frames_to_msf(cd->cur_frame);
absPos = frames_to_msf(cd->cur_frame + cd->track[track].offset);
LagDriveResponse();
}
return CD_INDRIVE(SDL_CDStatus(cd));
}
Expand All @@ -116,6 +121,7 @@ bool CDROM_Interface_SDL::GetAudioStatus(bool &playing, bool &pause)
if (CD_INDRIVE(SDL_CDStatus(cd))) {
playing = (cd->status == CD_PLAYING);
pause = (cd->status == CD_PAUSED);
LagDriveResponse();
}
return CD_INDRIVE(SDL_CDStatus(cd));
}
Expand All @@ -129,8 +135,10 @@ bool CDROM_Interface_SDL::GetMediaTrayStatus(bool &mediaPresent,
mediaChanged = (oldLeadOut != cd->track[cd->numtracks].offset);
trayOpen = !mediaPresent;
oldLeadOut = cd->track[cd->numtracks].offset;
if (mediaChanged)
if (mediaChanged) {
SDL_CDStatus(cd);
LagDriveResponse();
}
return true;
}

Expand All @@ -144,6 +152,7 @@ bool CDROM_Interface_SDL::PlayAudioSector(const uint32_t start, uint32_t len)

bool CDROM_Interface_SDL::PauseAudio(bool resume)
{
LagDriveResponse();
if (resume)
return (SDL_CDResume(cd) == 0);
else
Expand All @@ -155,11 +164,14 @@ bool CDROM_Interface_SDL::StopAudio()
// Has to be there, otherwise wrong cd status report (dunno why, sdl bug ?)
SDL_CDClose(cd);
cd = SDL_CDOpen(driveID);

LagDriveResponse();
return (SDL_CDStop(cd) == 0);
}

bool CDROM_Interface_SDL::LoadUnloadMedia([[maybe_unused]] bool unload)
{
LagDriveResponse();
return (SDL_CDEject(cd) == 0);
}

Expand Down Expand Up @@ -206,6 +218,8 @@ bool CDROM_Interface_Fake::GetAudioTracks(uint8_t& stTrack, uint8_t& end, TMSF&
stTrack = end = 1;
leadOut.min = 60;
leadOut.sec = leadOut.fr = 0;

LagDriveResponse();
return true;
}

Expand All @@ -214,6 +228,8 @@ bool CDROM_Interface_Fake::GetAudioTrackInfo(uint8_t track, TMSF& start, unsigne
start.min = start.fr = 0;
start.sec = 2;
attr = 0x60; // data / permitted

LagDriveResponse();
return true;
}

Expand All @@ -222,17 +238,46 @@ bool CDROM_Interface_Fake :: GetAudioSub(unsigned char& attr, unsigned char& tra
track = index = 1;
relPos.min = relPos.fr = 0; relPos.sec = 2;
absPos.min = absPos.fr = 0; absPos.sec = 2;

LagDriveResponse();
return true;
}

bool CDROM_Interface_Fake :: GetAudioStatus(bool& playing, bool& pause) {
playing = pause = false;

LagDriveResponse();
return true;
}

bool CDROM_Interface_Fake :: GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) {
mediaPresent = true;
mediaChanged = false;
trayOpen = false;

LagDriveResponse();
return true;
}

// Simulate the delay a physical CD-ROM drive took to respond to queries. When
// added to calls, this ensures that back-to-back queries report monotonically
// increasing Minute-Second-Frame (MSF) time values.
//
void CDROM_Interface::LagDriveResponse() const
{
// Always simulate a very small amount of drive response time
CALLBACK_Idle();

// Handle tick-rollover
static decltype(PIC_Ticks) prev_ticks = 0;
prev_ticks = std::min(PIC_Ticks, prev_ticks);

// Ensure results a monotonically increasing
auto since_last_response_ms = [=]() { return PIC_Ticks - prev_ticks; };
constexpr auto monotonic_response_ms = 1000 / REDBOOK_FRAMES_PER_SECOND;
while (since_last_response_ms() < monotonic_response_ms) {
CALLBACK_Idle();
}

prev_ticks = PIC_Ticks;
}
3 changes: 3 additions & 0 deletions src/dos/cdrom.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ class CDROM_Interface
virtual bool ReadSectorsHost (void* buffer, bool raw, unsigned long sector, unsigned long num) = 0;
virtual bool LoadUnloadMedia (bool unload) = 0;
virtual void InitNewMedia () {}

protected:
void LagDriveResponse() const;
};

class CDROM_Interface_SDL : public CDROM_Interface
Expand Down
14 changes: 12 additions & 2 deletions src/dos/cdrom_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ bool CDROM_Interface_Image::GetAudioTracks(uint8_t& start_track_num,
lead_out_msf.sec,
lead_out_msf.fr);
#endif
LagDriveResponse();
return true;
}

Expand Down Expand Up @@ -613,6 +614,7 @@ bool CDROM_Interface_Image::GetAudioTrackInfo(uint8_t requested_track_num,
start_msf.fr,
msf_to_frames(start_msf));
#endif
LagDriveResponse();
return true;
}

Expand Down Expand Up @@ -671,6 +673,7 @@ bool CDROM_Interface_Image::GetAudioSub(unsigned char& attr,
absolute_sector + REDBOOK_FRAME_PADDING, track_num, relative_msf.min,
relative_msf.sec, relative_msf.fr, relative_sector);
#endif
LagDriveResponse();
return true;
}

Expand All @@ -683,6 +686,7 @@ bool CDROM_Interface_Image::GetAudioStatus(bool& playing, bool& pause)
playing ? "is playing" : "stopped",
pause ? "paused" : "not paused");
#endif
LagDriveResponse();
return true;
}

Expand All @@ -697,6 +701,7 @@ bool CDROM_Interface_Image::GetMediaTrayStatus(bool& mediaPresent, bool& mediaCh
mediaChanged ? "was changed" : "hasn't been changed",
trayOpen ? "open" : "closed");
#endif
LagDriveResponse();
return true;
}

Expand Down Expand Up @@ -807,8 +812,10 @@ bool CDROM_Interface_Image::PlayAudioSector(uint32_t start, uint32_t len)
bool CDROM_Interface_Image::PauseAudio(bool resume)
{
player.isPaused = !resume;
if (player.channel)
if (player.channel) {
player.channel->Enable(resume);
LagDriveResponse();
}
#ifdef DEBUG
LOG_MSG("CDROM: PauseAudio => audio is now %s",
resume ? "unpaused" : "paused");
Expand All @@ -820,8 +827,10 @@ bool CDROM_Interface_Image::StopAudio(void)
{
player.isPlaying = false;
player.isPaused = false;
if (player.channel)
if (player.channel) {
player.channel->Enable(false);
LagDriveResponse();
}
#ifdef DEBUG
LOG_MSG("CDROM: StopAudio => stopped playback and halted the mixer");
#endif
Expand Down Expand Up @@ -946,6 +955,7 @@ track_iter CDROM_Interface_Image::GetTrack(const uint32_t sector)
}
}
#endif
LagDriveResponse();
return track;
}

Expand Down