Skip to content
Permalink
Browse files
Fix CD audio issue with Monkey Island
  • Loading branch information
Kevin Croft authored and Wengier committed Nov 5, 2020
1 parent 48e9a70 commit 6f3af7089c1cde9d76ee48510dd2516a042216e6
Showing with 28 additions and 6 deletions.
  1. +3 −1 CHANGELOG
  2. +4 −2 src/dos/cdrom.h
  3. +21 −3 src/dos/cdrom_image.cpp
@@ -1,5 +1,7 @@
0.83.8
-
- Fixed Monkey Island CD audio issue with the game
The Secret of Monkey Island when talking to pirate
in the Scumm Bar. Fix logic per kcgen. (Wengier)
0.83.7
- The primary DOSBox-X Wiki is now located at the
URL: https://dosbox-x.com/wiki (Wengier)
@@ -227,7 +227,9 @@ class CDROM_Interface_Image : public CDROM_Interface
virtual uint32_t getRate() = 0;
virtual uint8_t getChannels() = 0;
virtual int getLength() = 0;
virtual void setAudioPosition(uint32_t pos) = 0;
const uint16_t chunkSize = 0;
uint32_t audio_pos = UINT32_MAX; // last position when playing audio
};

//! \brief Binary file reader for the image
@@ -247,6 +249,7 @@ class CDROM_Interface_Image : public CDROM_Interface
uint32_t getRate() { return 44100; }
uint8_t getChannels() { return 2; }
int getLength();
void setAudioPosition(uint32_t pos) { audio_pos = pos; }
private:
std::ifstream *file;
};
@@ -267,10 +270,9 @@ class CDROM_Interface_Image : public CDROM_Interface
uint32_t getRate();
uint8_t getChannels();
int getLength();
void setAudioPosition(uint32_t pos) {}
private:
Sound_Sample *sample = nullptr;
// ensure the first seek isn't cached by starting with an impossibly-large position
uint32_t track_pos = (std::numeric_limits<uint32_t>::max)();
};

public:
@@ -102,9 +102,10 @@ CDROM_Interface_Image::BinaryFile::~BinaryFile()
file = nullptr;
}

bool CDROM_Interface_Image::BinaryFile::read(uint8_t *buffer, int seek, int count)
bool CDROM_Interface_Image::BinaryFile::read(uint8_t *buffer, int offset, int count)
{
file->seekg(seek, ios::beg);
if (!seek(offset)) return false;
file->seekg(offset, ios::beg);
file->read((char*)buffer, count);
return !(file->fail());
}
@@ -129,14 +130,21 @@ uint16_t CDROM_Interface_Image::BinaryFile::getEndian()

bool CDROM_Interface_Image::BinaryFile::seek(uint32_t offset)
{
if (static_cast<uint32_t>(file->tellg()) == offset)
return true;
file->seekg(offset, ios::beg);
return !file->fail();
}

uint16_t CDROM_Interface_Image::BinaryFile::decode(uint8_t *buffer)
{
if (static_cast<uint32_t>(file->tellg()) != audio_pos)
if (!seek(audio_pos)) return 0;

file->read((char*)buffer, chunkSize);
return (uint16_t)file->gcount();
const uint16_t bytes_read = (uint16_t)file->gcount();
audio_pos += bytes_read;
return bytes_read;
}

CDROM_Interface_Image::AudioFile::AudioFile(const char *filename, bool &error)
@@ -182,8 +190,16 @@ bool CDROM_Interface_Image::AudioFile::seek(uint32_t offset)
const auto begin = std::chrono::steady_clock::now();
#endif

if (audio_pos == offset) {
#ifdef DEBUG
LOG_MSG("CDROM: seek to %u avoided with position-tracking", offset);
#endif
return true;
}

// Convert the byte-offset to a time offset (milliseconds)
const bool result = Sound_Seek(sample, lround(offset/176.4f));
audio_pos = result ? offset : UINT32_MAX;

#ifdef DEBUG
const auto end = std::chrono::steady_clock::now();
@@ -196,6 +212,7 @@ bool CDROM_Interface_Image::AudioFile::seek(uint32_t offset)
uint16_t CDROM_Interface_Image::AudioFile::decode(uint8_t *buffer)
{
const uint16_t bytes = Sound_Decode(sample);
audio_pos += bytes;
memcpy(buffer, sample->buffer, bytes);
return bytes;
}
@@ -423,6 +440,7 @@ bool CDROM_Interface_Image::PlayAudioSector(unsigned long start, unsigned long l

// only initialize the player elements if our track is playable
if (is_playable) {
trackFile->setAudioPosition(offset);
const uint8_t channels = trackFile->getChannels();
const uint32_t rate = trackFile->getRate();

0 comments on commit 6f3af70

Please sign in to comment.