VOGONS


First post, by xtreger

User metadata
Rank Member
Rank
Member

I had made a thread on trying to get redbook games working in DOS via SMEMU or VSBHDA, but I feel it's important to have a separate thread for the question in the title.

Context
On modern-ish (late 2000s or 2010s) motherboards it's almost impossible to get redbook CD-based games like Carmageddon or Tomb Raider working with full audio, since many PCI sound cards won't play nice with these motherboards despite having native DOS drivers. Using either SBEMU or VSBHDA, we can get digital sounds (i.e. the in-game sound effects) working but the CD audio (i.e. music) will not play.

Interesting observation
MPXPlay in particular is able to play music CD tracks without SBEMU / VSBHDA loaded, with no connector between the CD drive's audio out and sound card's CD-in. It's like in Windows when we enable digital CD audio for a particular CD drive - and CD audio gets played directly even for SATA CD drives (which have neither audio out at the back nor a 3.5mm input in the front). MPXPlay is able to replicate this functionality natively in DOS. A couple of posts in this thread also mention this: Help with understanding how to get (digital) CD audio to play in DOS. I've tested this behavior with ES1371 and Audigy 2 ZS, and it works. But with a YMF724 card MPXPlay just says no soundcard detected.
Also, this doesn't work with other DOS-based CD players that I tried, like CDM32, ACP112, CDPLAY14.

My question is, it seems all elements to play redbook games with full audio in DOS already exist. Are there any technical challenges to achieve this? Both SBEMU and VSBHDA seem to based on MPXPlay to an extent, so what would need to be done so that while in a redbook game with SBEMU/VSBHDA activated, the relevant MPXPlay routines are invoked to play the relevant CD track when the game requests it? Sorry if this is a noob question but I'm a beginner to all this, and curious to learn more.

Reply 1 of 19, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie

The method that MPXPlay is using is greatly different from just playing redbook audio.
With the old method, you just tell the CD drive to play from sectors X to Y and forget about it. The drive handles everything, the software doesn't really have to do anything besides occasionally checking the playback position. Data reads to the disc are also interleaved automatically by the drive.
With the digital extraction method every sector has to manually be retrieved from the disc, then manually mixed with any other audio that is being generated before being sent to the audio device. It's a huge increase in CPU overhead, it all needs to be synchronized so as to not corrupt the existing audio or drop samples and we're talking about an OS here that doesn't even support multithreading.

Reply 2 of 19, by xtreger

User metadata
Rank Member
Rank
Member
jmarsh wrote on Yesterday, 08:16:

The method that MPXPlay is using is greatly different from just playing redbook audio.
With the old method, you just tell the CD drive to play from sectors X to Y and forget about it. The drive handles everything, the software doesn't really have to do anything besides occasionally checking the playback position. Data reads to the disc are also interleaved automatically by the drive.
With the digital extraction method every sector has to manually be retrieved from the disc, then manually mixed with any other audio that is being generated before being sent to the audio device. It's a huge increase in CPU overhead, it all needs to be synchronized so as to not corrupt the existing audio or drop samples and we're talking about an OS here that doesn't even support multithreading.

Thanks for the explanation! So from what I understood, we can't just parallely invoke the relevant MPXPlay routine whenever the game sends a request for a CD track to play (since no multithreading). But it would still be doable if a program could, as you said, get every sector from the CD and manually synchronize it with the digital sound output (i.e. the output SBEMU/VSBHDA ordinarily produces) before routing to audio device, right? Would this be possible with the modern-ish CPUs that are compatible with the modern-ish motherboards? (Typically they're >= 3 GHz which is quite a lot more than MHz CPUs that DOS software can run on)

Reply 3 of 19, by wierd_w

User metadata
Rank Oldbie
Rank
Oldbie

You need a way for your sound engine and the virtual cdrom drive to communicate a playback stream with each other.

If there was gobs and gobs of RAM available, just dumping the redbook tracks into xms, then instructing vsbhda to do playback might work, but it would locically be bass ackwards:

Normally, a game just tells the drive 'start playing music at this timestamp, on this track, and the drive does it.

In this case, the game tells the 'drive' (i am assuming shsucdhd here) to play, but it cant. It has no way to output anything, it's virtual. It needs to have some way to indicate to vsbhda that this playback has been requested.

In theory, shsucdhd could look for vsbhda being loaded, and if it finds it, communicate with it using a private API.

Things it would tell vsbhda:

1) I have these redbook tracks preloaded into XMS memory, at these handles, as raw pcm.

2) I was requested to play track FOO at timestamp BAR.

(And if images get loaded or unloaded)

3) I have ejected my media, old handles are invalidated.

4) I have loaded new media, here are the handles for the preloaded tracks.

After that, it's VSBHDA's show. It accepts instructions to playback pcm wave data starting at the instructed position, from the xms memory designated by the handle, like another digital voice channel.

This would need oodles of ram to work, but 'could' work.

You'd need to fork both shsucdx project, and vsbhda, to introduce the private API to both.

Reply 4 of 19, by xtreger

User metadata
Rank Member
Rank
Member
wierd_w wrote on Yesterday, 12:48:
You need a way for your sound engine and the virtual cdrom drive to communicate a playback stream with each other. […]
Show full quote

You need a way for your sound engine and the virtual cdrom drive to communicate a playback stream with each other.

If there was gobs and gobs of RAM available, just dumping the redbook tracks into xms, then instructing vsbhda to do playback might work, but it would locically be bass ackwards:

Normally, a game just tells the drive 'start playing music at this timestamp, on this track, and the drive does it.

In this case, the game tells the 'drive' (i am assuming shsucdhd here) to play, but it cant. It has no way to output anything, it's virtual. It needs to have some way to indicate to vsbhda that this playback has been requested.

In theory, shsucdhd could look for vsbhda being loaded, and if it finds it, communicate with it using a private API.

Things it would tell vsbhda:

1) I have these redbook tracks preloaded into XMS memory, at these handles, as raw pcm.

2) I was requested to play track FOO at timestamp BAR.

(And if images get loaded or unloaded)

3) I have ejected my media, old handles are invalidated.

4) I have loaded new media, here are the handles for the preloaded tracks.

After that, it's VSBHDA's show. It accepts instructions to playback pcm wave data starting at the instructed position, from the xms memory designated by the handle, like another digital voice channel.

This would need oodles of ram to work, but 'could' work.

You'd need to fork both shsucdx project, and vsbhda, to introduce the private API to both.

Thanks. So this is assuming a virtual drive though. And there are other issues with virtual drives not being compatible with .bin/.cue format, so let's forget about it for now and assume there's a physical CD drive present. With a real CD drive instead of shsucd, would the scenario be exactly the same using prohibitive amount of RAM?

Reply 5 of 19, by wierd_w

User metadata
Rank Oldbie
Rank
Oldbie

You still need a way to get the digital audio data to the playback engine.

You still have a drive that has no way to present it to that endpoint on its own without help.

With an old fashioned cd drive, an analog audio cable does this job.

For digital audio, a means to get the data into memory (where the player can process it), and to tell the player to process it, is required. Regardless of if the drive is virtual, or physical.

If you dont want to blow 100s of megabytes of xms to copy whole redbook tracks for this, you'll need a more robust private API.

Maybe a 'dual playback buffer'?

As the playback engine processes the smaller sample in memory, it asserts a 'progress' value to the disc driver. (Shsucdx or shsucdhd, respectively) This driver then keeps track of that status, and loads more data into the 'inactive' buffer, as needed. The playback engine switches the buffer when it reaches the end, and continues.

With several seconds of time buffered, we'd only need a few MB, instead of a few hundred MB of XMS, but again, the API becomes more complex, with more, and more frequent, interprocess activity and communication.

Reply 6 of 19, by xtreger

User metadata
Rank Member
Rank
Member
wierd_w wrote on Yesterday, 18:03:
You still need a way to get the digital audio data to the playback engine. […]
Show full quote

You still need a way to get the digital audio data to the playback engine.

You still have a drive that has no way to present it to that endpoint on its own without help.

With an old fashioned cd drive, an analog audio cable does this job.

For digital audio, a means to get the data into memory (where the player can process it), and to tell the player to process it, is required. Regardless of if the drive is virtual, or physical.

If you dont want to blow 100s of megabytes of xms to copy whole redbook tracks for this, you'll need a more robust private API.

Maybe a 'dual playback buffer'?

As the playback engine processes the smaller sample in memory, it asserts a 'progress' value to the disc driver. (Shsucdx or shsucdhd, respectively) This driver then keeps track of that status, and loads more data into the 'inactive' buffer, as needed. The playback engine switches the buffer when it reaches the end, and continues.

With several seconds of time buffered, we'd only need a few MB, instead of a few hundred MB of XMS, but again, the API becomes more complex, with more, and more frequent, interprocess activity and communication.

I wish I had your knowledge and I could seriously try my luck at it (even if probably destined to fail, would be fun to try). Do you know of any resources or literature I can read to get an idea about all this stuff?

Reply 7 of 19, by wierd_w

User metadata
Rank Oldbie
Rank
Oldbie

I am thinking hypothetically. What you would need to do, and why.

Implementations are much harder than ideas.

Ideas are free. Implementations are not.

Reply 8 of 19, by cyclone3d

User metadata
Rank l33t++
Rank
l33t++

This has me intrigued. I might have a crack at it with the help of AI.

Logic great, programming skills ok. Figuring out how to communicate directly with hardware... not so great but learning.

Yamaha modified setupds and drivers
Yamaha XG repository
YMF7x4 Guide
Aopen AW744L II SB-LINK

Reply 9 of 19, by ludicrous_peridot

User metadata
Rank Member
Rank
Member

Not to discourage, or anything, but I for one, never set my aim that high, and still keep the system with IDE port running for the games of this kind. Partly also because I can use S/PDIF to route out of the "noisy" PC case and mix the way I like outside.

Technically, though, provided one can solve for inserting a "layer" between user application and real MSCDEX to allow "covertly" reading "redbook" sectors from the sound driver TSR (assuming one) but still keeping interface for the programs fully operational, this could probably be done. After all the game using Ausio CD music is extremely unlikely to also pull data from it at the same time.

And then, if the system is so new it can't run IDE, I bet it would have sufficient RAM to cache the whole CD, so provided one can live with somewhat long loading time, TSR requests for data could instead be "forwarded" to this cache instead of the real drive.

GA-G41M-Combo G41/ICH7 - Core 2 Quad Q9550 - DDR3 1033 - Radeon RX570 - CMI-8738 - X3MB (Buran)
Beetle/M/i815+ICH2 - Celeron 566Mhz - Opti 924
https://archive.org/details/peridot-26

Reply 10 of 19, by wierd_w

User metadata
Rank Oldbie
Rank
Oldbie

In this case, vsbhda already knows how to read and play pcm formatted audio.

Additionally, shsucdx already knows how to request raw sectors from a cdrom driver.

Redbook audio is not fancy. It's just 14400hz 16bit pcm audio written on raw sectors.

The tricky bits are getting shsucdx to allocate XMS memory, and to communicate with vsbhda.

edit:

There is no need to intercept mscdex. Shsucdx is a foss replacement for mscdex. We can get all the functionality we need with a private api between shsucdx and vsbhda.

Reply 11 of 19, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie

The commands to read raw audio sectors are different from data reads, there's a reasonable chance shsucdx doesn't implement them.

After all the game using Ausio CD music is extremely unlikely to also pull data from it at the same time.

This is definitely not true. Half the motivation behind games using cd audio was so they didn't have to bother caring about when their disc access happens (with regards to music playback).

Reply 12 of 19, by NeoG_

User metadata
Rank Oldbie
Rank
Oldbie
jmarsh wrote on Yesterday, 23:58:

The commands to read raw audio sectors are different from data reads, there's a reasonable chance shsucdx doesn't implement them.

After all the game using Ausio CD music is extremely unlikely to also pull data from it at the same time.

This is definitely not true. Half the motivation behind games using cd audio was so they didn't have to bother caring about when their disc access happens (with regards to music playback).

How does software access data on an optical disc without interrupting audio playback? I didn't think that was possible

98/DOS Rig: BabyAT AladdinV, K6-2+/550, V3 2000, 128MB PC100, 20GB HDD, 128GB SD2IDE, SB Live!, SB16-SCSI, PicoGUS, WP32 McCake, iNFRA CD, ZIP100
XP Rig: Lian Li PC-10 ATX, Gigabyte X38-DQ6, Core2Duo E6850, ATi HD5870, 2GB DDR2, 2TB HDD, X-Fi XtremeGamer

Reply 13 of 19, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie
NeoG_ wrote on Today, 00:14:

How does software access data on an optical disc without interrupting audio playback? I didn't think that was possible

It just does it like normal. The drive is responsible for buffering the audio data to avoid dropouts.

Reply 14 of 19, by NeoG_

User metadata
Rank Oldbie
Rank
Oldbie
jmarsh wrote on Today, 00:19:
NeoG_ wrote on Today, 00:14:

How does software access data on an optical disc without interrupting audio playback? I didn't think that was possible

It just does it like normal. The drive is responsible for buffering the audio data to avoid dropouts.

Do you have any examples of DOS software that does this? My understanding is that when the CD-ROM drive receives a request to play an audio track, the disc spins at 1x and does very little buffering (just enough to ensure the DAC is fed correctly) like a regular CD player

98/DOS Rig: BabyAT AladdinV, K6-2+/550, V3 2000, 128MB PC100, 20GB HDD, 128GB SD2IDE, SB Live!, SB16-SCSI, PicoGUS, WP32 McCake, iNFRA CD, ZIP100
XP Rig: Lian Li PC-10 ATX, Gigabyte X38-DQ6, Core2Duo E6850, ATi HD5870, 2GB DDR2, 2TB HDD, X-Fi XtremeGamer

Reply 15 of 19, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie

You can test it with any mixed CD; just use a text based CD player (there were several) to start the audio playing and you can still browse the disc's directories and run programs from it without interrupting the music.

Reply 16 of 19, by NeoG_

User metadata
Rank Oldbie
Rank
Oldbie
jmarsh wrote on Today, 03:34:

You can test it with any mixed CD; just use a text based CD player (there were several) to start the audio playing and you can still browse the disc's directories and run programs from it without interrupting the music.

I just tried this, in all the scenarios I tried I got a CR101: Error reading drive when attempting to do anything with the drive that wasn't cached. I tried a physical drive with playback started in software, physical drive with playback started using the front panel and a PicoGUS virtual drive with playback started from software.

If I did a DIR list before starting playback I could still do it after starting playback as it has been cached. But anything that needed to go to the drive for fresh data (e.g. browsing to a new directory or running a program) resulted in an error accessing the drive. I also tried three mixed mode CDs in case it was a problem with one (Blood, Descent II and Mechwarrior 2).

Windows 98 was a bit more resilient, however accessing the drive with CD playback running stopped playback until data access was finished and then started playing the next track.

98/DOS Rig: BabyAT AladdinV, K6-2+/550, V3 2000, 128MB PC100, 20GB HDD, 128GB SD2IDE, SB Live!, SB16-SCSI, PicoGUS, WP32 McCake, iNFRA CD, ZIP100
XP Rig: Lian Li PC-10 ATX, Gigabyte X38-DQ6, Core2Duo E6850, ATi HD5870, 2GB DDR2, 2TB HDD, X-Fi XtremeGamer

Reply 17 of 19, by xtreger

User metadata
Rank Member
Rank
Member

I used AI (as much as I don't like its misuse, it's still a useful tool for some ideas/prototypes) to generate a broad summary of approach. I'll summarize that summary:

Mixed-mode games issue play audio commands (Int 0x2F, AX=0x1510, device command 132) to the CD driver. SBEMU already handles SB digital effects, so we want to intercept MSCDEX (or SHSUCDX) play commands, digitally extract CD audio, mix with SB emulated audio and send to PCI card <-- this matches exactly what jmarsh and wierd_w said earlier.
Technical challenges in order:
1. Intercept MSCDEX commands - games use Int 0x2F (AX=0x1510) to send device driver requests to CD drive): command 132 (0x84) is for play, 133 (0x85) for stop, 136 (0x88) for resume. SBEMU hooks real mode interrupts (for TSR communication via int 0x2D). So similarly we need to hook int 0x2F, inspect the command structures and intercept play/stop/pause while passing everything else through (like directory reads, file access, etc.)
2. Reading CD sectors from interrupt context (main problem) - This is the hardest part. SBEMU audio pipeline runs inside a PCI card ISR (MAIN_Interrupt()). But mpxplay's MSCDEX_read_sectors_cda() calls Int 0x2F itself (which is a real mode interrupt), which we generally can't do from within a hardware ISR. A couple of approaches:
2a. Background read with a double buffer: Don't read CD sectors in the ISR. Instead pre-read a large chunk of CD audio into a ring buffer during the int 0x2F hook (when game says "play track N"). Use a timer interrupt (Int 0x08 / IRQ 0) to periodically read more sectors and keep the ring buffer topped up. The PCI ISR just reads from the ring buffer. This decouples the CD I/O from the audio output timing
2b. Read in the Int 0x2F hook itself: when the game says "play track N", immediately start pre-reading a large batch of sectors into a buffer before returning control. Then top up from the timer.

(personally with my limited knowledge I'm not fully clear on difference between 2a and 2b but I'll ask it follow-ups later)

3. Mixing two audio streams - SBEMU's MAIN_Interrupt() already mixes SB digital audio with OPL3 FM synthesis. Adding a third CD audio stream follows the same pattern.
4. Volume control: SBEMU already emulates SB mixer's CD volume register (SBEMU_MIXERREG_CDVOL). Currently it maps this to PCI card's analog CD-IN channel. Instead we cam apply this volume to the digitally mixed CD stream.

So what could be borrowed from mpxplay for a potential SBEMU fork: MSCDEX_read_sectors_cda() - the core sector reading function, mscdex_cdrom_test() / mpxplay_diskdrive_mscdex_is_drive_cd() - drive detection, MSCDEX_get_diskinfo() / MSCDEX_get_trackinfos() - TOC reading, DOS conventional memory allocation pattern for DPMI-to-real-mode bridging.

Reply 18 of 19, by wierd_w

User metadata
Rank Oldbie
Rank
Oldbie

1)
The code for SHSUCDX is available for free. Instead of trying to monkey in the middle against it, we can just have it respond to the game's Play, Stop, and Resume messages by sending a private API message, such as writing on a bit of mutually-agreed scratchpad memory with some flags, and sending IO port messages.

Sourcecode can be found (at least a fork of it anyway) here: https://github.com/adoxa/shsucd

This means we dont need to trap any IO writes to catch this message from the game. SHSUCDX is already trapping for these messages. Since SHSUCDX is able to play redbook audio, it is already listening for, and responding to these messages. Instead, we need a way to instruct SHSUCDX that it should not attempt to tell the downstream interface driver to do redbook playback, as a command line option on load. This would deactivate that codepath, and activate the digital playback codepath instead. This new codepath looks for VSBHDA to be loaded first, by scanning for its device driver identifier name, then creating the scratchpad, allocating XMS buffers, then signalling to VSBHDA that it has loaded, and is ready to coordinate digital audio extraction for playback. If it does not find VSBHDA, it should alert this error condition to the console output, then default to normal redbook audio behavior.

2)
Since SHSUCDX is the primary handler for accessing cdrom drives in this scenario, any request for data of any kind from a program that involves a CDROM will go through it first. This makes it the ideal candidate to leverage. When a game issues the Play, Stop or Resume commands, SHSUCDX handles this request. If the "Do Digital Extraction method" codepath is activated from its load arguments, then it will inspect the play command for track number and position, read the cd's TOC to find that track, allocate both playback buffers from XMS, populate both playback buffers at this time, then communicate to VSBHDA by creating the shared communication scratch pad, and writing the needed information in it, then communicating the location of this scratchpad to VSBHDA with an IOport write. It will then set up a polled timer interrupt to read this pad, and make actions accordingly, or write on this pad to communicate with VSBHDA, accordingly.

Things in the scratch pad:

A bitfield, containing:
Currently active buffer [1/0] [Which XMS playback buffer is currently being read by VSBHDA? 0, or 1?]

Playback requested [1/0] [Has SHSUCDX requested that redbook audio should be getting played from the buffer? Yes/No]

currently playing [1/0] [Is VSBHDA currently playing redbook audio? Yes/No]

Restart at top of next buffer [1/0] [This is used to tell VSBHDA that it should stop playing this buffer, and immediately switch to the next buffer, then resume playing. VSBHDA sets this to 0 after completion. It's used when say, a game switches the redbook audio play location suddenly. This allows SHSUCDX to load the new play location data into the inactive buffer, then trigger VSBHDA to stop what its doing on the active buffer, and switch.]

SHSUCDX has topped up buffer [1/0] [When VSBHDA switches the buffer, it sets this to 0. SHSUCDX monitors for this bit, and then knows it needs to populate the now inactive buffer while VSBHDA is playing the active one. Once it is populated, it sets this to 1. This lets VSBHDA know it is OK to switch to the inactive buffer when it runs out.]

VSBHDA ready/error status [1/0] [VSBHDA sets this to 1 after it has received the initial IO port message containing this table, and configured itself for redbook playback, and is read to get messages from SHSUCDX. If any kind of error condition happens, it lets SHSUCDX know that things are amiss by setting this to 0]

SHSUCDX ready/error status [1/0] [SHSUCDX sets this to 1 when it starts its monitoring loop for this scratchpad. If something odd happens, like an unrecoverable media error, it sets this to 0, to let VSBHDA know that it cannot service the buffer.]

Write on scratchpad OK [1/0] [Writes on the scratch pads are OK to do if this value is 1, and forbidden/"presumed to be locked by the other process" when this is set to 0]

Long values containing the XMS handles of Buffer 0, and Buffer 1.

to initiate communication with VSBHDA, an IOport is written to that is monitored by VSBHDA. This IOwrite contains a message stating where the scratchpad is located in low memory. (memory owned by SHSUCDX, but which is OK to be written on/checked, by VSBHDA.)

2a)
VSBHDA monitors for this message, and when it gets it, it knows it needs to service digital CD audio. It locates the scratchpad from the message, then reads or writes on it using a polled interrupt, or after so many samples of PCM are played, to make sure it should continue. It reads the XMS handles for both buffers, and configures itself for playback, then waits.

SHSUCDX then is in charge of telling VSBHDA to start, stop, or resume playback, loading data into the buffers, setting bitflags when it has loaded data into a buffer, or when it has encountered an error.

VSBHDA is in charge of designating the currently active buffer, playing the buffered audio, requesting that the inactive buffer be filled, reporting its current playback status, and reporting its error condition.

They coordinate to avoid race condition by the use of the Write On Scratchpad bit. If this bit is 0, it means the other process is doing something with the scratch pad.

3) and 4) are wholly the job of VSBHDA

I am CERTAIN I have missed something, because I have not fully flowcharted out the logic for this. That should give a very basic skeleton to hang meat on though.

Reply 19 of 19, by xtreger

User metadata
Rank Member
Rank
Member
wierd_w wrote on Today, 15:18:
1) The code for SHSUCDX is available for free. Instead of trying to monkey in the middle against it, we can just have it respo […]
Show full quote

1)
The code for SHSUCDX is available for free. Instead of trying to monkey in the middle against it, we can just have it respond to the game's Play, Stop, and Resume messages by sending a private API message, such as writing on a bit of mutually-agreed scratchpad memory with some flags, and sending IO port messages.

Sourcecode can be found (at least a fork of it anyway) here: https://github.com/adoxa/shsucd

This means we dont need to trap any IO writes to catch this message from the game. SHSUCDX is already trapping for these messages. Since SHSUCDX is able to play redbook audio, it is already listening for, and responding to these messages. Instead, we need a way to instruct SHSUCDX that it should not attempt to tell the downstream interface driver to do redbook playback, as a command line option on load. This would deactivate that codepath, and activate the digital playback codepath instead. This new codepath looks for VSBHDA to be loaded first, by scanning for its device driver identifier name, then creating the scratchpad, allocating XMS buffers, then signalling to VSBHDA that it has loaded, and is ready to coordinate digital audio extraction for playback. If it does not find VSBHDA, it should alert this error condition to the console output, then default to normal redbook audio behavior.

2)
Since SHSUCDX is the primary handler for accessing cdrom drives in this scenario, any request for data of any kind from a program that involves a CDROM will go through it first. This makes it the ideal candidate to leverage. When a game issues the Play, Stop or Resume commands, SHSUCDX handles this request. If the "Do Digital Extraction method" codepath is activated from its load arguments, then it will inspect the play command for track number and position, read the cd's TOC to find that track, allocate both playback buffers from XMS, populate both playback buffers at this time, then communicate to VSBHDA by creating the shared communication scratch pad, and writing the needed information in it, then communicating the location of this scratchpad to VSBHDA with an IOport write. It will then set up a polled timer interrupt to read this pad, and make actions accordingly, or write on this pad to communicate with VSBHDA, accordingly.

Things in the scratch pad:

A bitfield, containing:
Currently active buffer [1/0] [Which XMS playback buffer is currently being read by VSBHDA? 0, or 1?]

Playback requested [1/0] [Has SHSUCDX requested that redbook audio should be getting played from the buffer? Yes/No]

currently playing [1/0] [Is VSBHDA currently playing redbook audio? Yes/No]

Restart at top of next buffer [1/0] [This is used to tell VSBHDA that it should stop playing this buffer, and immediately switch to the next buffer, then resume playing. VSBHDA sets this to 0 after completion. It's used when say, a game switches the redbook audio play location suddenly. This allows SHSUCDX to load the new play location data into the inactive buffer, then trigger VSBHDA to stop what its doing on the active buffer, and switch.]

SHSUCDX has topped up buffer [1/0] [When VSBHDA switches the buffer, it sets this to 0. SHSUCDX monitors for this bit, and then knows it needs to populate the now inactive buffer while VSBHDA is playing the active one. Once it is populated, it sets this to 1. This lets VSBHDA know it is OK to switch to the inactive buffer when it runs out.]

VSBHDA ready/error status [1/0] [VSBHDA sets this to 1 after it has received the initial IO port message containing this table, and configured itself for redbook playback, and is read to get messages from SHSUCDX. If any kind of error condition happens, it lets SHSUCDX know that things are amiss by setting this to 0]

SHSUCDX ready/error status [1/0] [SHSUCDX sets this to 1 when it starts its monitoring loop for this scratchpad. If something odd happens, like an unrecoverable media error, it sets this to 0, to let VSBHDA know that it cannot service the buffer.]

Write on scratchpad OK [1/0] [Writes on the scratch pads are OK to do if this value is 1, and forbidden/"presumed to be locked by the other process" when this is set to 0]

Long values containing the XMS handles of Buffer 0, and Buffer 1.

to initiate communication with VSBHDA, an IOport is written to that is monitored by VSBHDA. This IOwrite contains a message stating where the scratchpad is located in low memory. (memory owned by SHSUCDX, but which is OK to be written on/checked, by VSBHDA.)

2a)
VSBHDA monitors for this message, and when it gets it, it knows it needs to service digital CD audio. It locates the scratchpad from the message, then reads or writes on it using a polled interrupt, or after so many samples of PCM are played, to make sure it should continue. It reads the XMS handles for both buffers, and configures itself for playback, then waits.

SHSUCDX then is in charge of telling VSBHDA to start, stop, or resume playback, loading data into the buffers, setting bitflags when it has loaded data into a buffer, or when it has encountered an error.

VSBHDA is in charge of designating the currently active buffer, playing the buffered audio, requesting that the inactive buffer be filled, reporting its current playback status, and reporting its error condition.

They coordinate to avoid race condition by the use of the Write On Scratchpad bit. If this bit is 0, it means the other process is doing something with the scratch pad.

3) and 4) are wholly the job of VSBHDA

I am CERTAIN I have missed something, because I have not fully flowcharted out the logic for this. That should give a very basic skeleton to hang meat on though.

I will take time to go through the above, I'm making an attempt to learn this stuff. Sorry in advance if my proper response to above is quite a bit delayed. And thanks a lot for the details btw! Looks like I underestimated the utility of SHSUCDX