Commit f65c7d54 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

Now using the NT CD interface.

parent 5cc6105b
......@@ -3,7 +3,6 @@ TOPOBJDIR = ../../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = mcicda.drv
IMPORTS = ntdll
LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
......
......@@ -16,11 +16,18 @@
#include "wingdi.h"
#include "winuser.h"
#include "mmddk.h"
#include "cdrom.h"
#include "winioctl.h"
#include "ntddstor.h"
#include "ntddcdrm.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(mcicda);
#define CDFRAMES_PERSEC 75
#define CDFRAMES_PERMIN (CDFRAMES_PERSEC * 60)
#define FRAME_OF_ADDR(a) ((a)[1] * CDFRAMES_PERMIN + (a)[2] * CDFRAMES_PERSEC + (a)[3])
#define FRAME_OF_TOC(toc, idx) FRAME_OF_ADDR((toc).TrackData[idx - (toc).FirstTrack].Address)
typedef struct {
UINT wDevID;
int nUseCount; /* Incremented for each shared open */
......@@ -28,8 +35,7 @@ typedef struct {
WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
HANDLE hCallback; /* Callback handle for pending notification */
DWORD dwTimeFormat;
WINE_CDAUDIO wcda;
int mciMode;
HANDLE handle;
} WINE_MCICDAUDIO;
/*-----------------------------------------------------------------------*/
......@@ -80,21 +86,33 @@ static WINE_MCICDAUDIO* MCICDA_GetOpenDrv(UINT wDevID)
}
/**************************************************************************
* MCICDA_Mode [internal]
* MCICDA_GetStatus [internal]
*/
static int MCICDA_Mode(int wcdaMode)
static DWORD MCICDA_GetStatus(WINE_MCICDAUDIO* wmcda)
{
switch (wcdaMode) {
case WINE_CDA_DONTKNOW: return MCI_MODE_STOP;
case WINE_CDA_NOTREADY: return MCI_MODE_STOP;
case WINE_CDA_OPEN: return MCI_MODE_OPEN;
case WINE_CDA_PLAY: return MCI_MODE_PLAY;
case WINE_CDA_STOP: return MCI_MODE_STOP;
case WINE_CDA_PAUSE: return MCI_MODE_PAUSE;
default:
FIXME("Unknown mode %04x\n", wcdaMode);
CDROM_SUB_Q_DATA_FORMAT fmt;
SUB_Q_CHANNEL_DATA data;
DWORD br;
DWORD mode = MCI_MODE_NOT_READY;
fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt),
&data, sizeof(data), &br, NULL)) {
if (GetLastError() == STATUS_NO_MEDIA_IN_DEVICE) mode = MCI_MODE_OPEN;
} else {
switch (data.CurrentPosition.Header.AudioStatus)
{
case AUDIO_STATUS_IN_PROGRESS: mode = MCI_MODE_PLAY; break;
case AUDIO_STATUS_PAUSED: mode = MCI_MODE_PAUSE; break;
case AUDIO_STATUS_PLAY_COMPLETE: mode = MCI_MODE_STOP; break;
case AUDIO_STATUS_PLAY_ERROR:
case AUDIO_STATUS_NOT_SUPPORTED:
case AUDIO_STATUS_NO_STATUS:
default:
break;
}
}
return MCI_MODE_STOP;
return mode;
}
/**************************************************************************
......@@ -102,15 +120,12 @@ static int MCICDA_Mode(int wcdaMode)
*/
static int MCICDA_GetError(WINE_MCICDAUDIO* wmcda)
{
switch (wmcda->wcda.cdaMode) {
case WINE_CDA_DONTKNOW:
case WINE_CDA_NOTREADY: return MCIERR_DEVICE_NOT_READY;
case WINE_CDA_OPEN: return MCIERR_HARDWARE;
case WINE_CDA_PLAY:
case WINE_CDA_STOP:
case WINE_CDA_PAUSE: break;
switch (GetLastError())
{
case STATUS_NO_MEDIA_IN_DEVICE: return MCIERR_DEVICE_NOT_READY;
case STATUS_IO_DEVICE_ERROR: return MCIERR_HARDWARE;
default:
FIXME("Unknown mode %04x\n", wmcda->wcda.cdaMode);
FIXME("Unknown mode %lx\n", GetLastError());
}
return MCIERR_DRIVER_INTERNAL;
}
......@@ -122,6 +137,9 @@ static DWORD MCICDA_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime)
{
DWORD dwFrame = 0;
UINT wTrack;
CDROM_TOC toc;
DWORD br;
BYTE* addr;
TRACE("(%p, %08lX, %lu);\n", wmcda, wmcda->dwTimeFormat, dwTime);
......@@ -140,15 +158,20 @@ static DWORD MCICDA_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime)
case MCI_FORMAT_TMSF:
default: /* unknown format ! force TMSF ! ... */
wTrack = MCI_TMSF_TRACK(dwTime);
TRACE("MSF %02u-%02u:%02u:%02u\n",
MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime),
MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
TRACE("TMSF trackpos[%u]=%lu\n",
wTrack, wmcda->wcda.lpdwTrackPos[wTrack - 1]);
dwFrame = wmcda->wcda.lpdwTrackPos[wTrack - 1];
dwFrame += CDFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
dwFrame += CDFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
dwFrame += MCI_TMSF_FRAME(dwTime);
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL))
return 0;
if (wTrack < toc.FirstTrack || wTrack > toc.LastTrack)
return 0;
TRACE("MSF %02u-%02u:%02u:%02u\n",
MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime),
MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
addr = toc.TrackData[wTrack - toc.FirstTrack].Address;
TRACE("TMSF trackpos[%u]=%d:%d:%d\n",
wTrack, addr[0], addr[1], addr[2]);
dwFrame = CDFRAMES_PERMIN * (addr[0] + MCI_TMSF_MINUTE(dwTime)) +
CDFRAMES_PERSEC * (addr[1] + MCI_TMSF_SECOND(dwTime)) +
addr[2] + MCI_TMSF_FRAME(dwTime);
break;
}
return dwFrame;
......@@ -157,14 +180,15 @@ static DWORD MCICDA_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime)
/**************************************************************************
* MCICDA_CalcTime [internal]
*/
static DWORD MCICDA_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame,
LPDWORD lpRet)
static DWORD MCICDA_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame, LPDWORD lpRet)
{
DWORD dwTime = 0;
UINT wTrack;
UINT wMinutes;
UINT wSeconds;
UINT wFrames;
CDROM_TOC toc;
DWORD br;
TRACE("(%p, %08lX, %lu);\n", wmcda, tf, dwFrame);
......@@ -185,17 +209,23 @@ static DWORD MCICDA_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame,
break;
case MCI_FORMAT_TMSF:
default: /* unknown format ! force TMSF ! ... */
if (dwFrame < wmcda->wcda.dwFirstFrame || dwFrame > wmcda->wcda.dwLastFrame) {
ERR("Out of range value %lu [%lu,%lu]\n",
dwFrame, wmcda->wcda.dwFirstFrame, wmcda->wcda.dwLastFrame);
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL))
return 0;
if (dwFrame < FRAME_OF_TOC(toc, toc.FirstTrack) ||
dwFrame > FRAME_OF_TOC(toc, toc.LastTrack + 1)) {
ERR("Out of range value %lu [%u,%u]\n",
dwFrame, FRAME_OF_TOC(toc, toc.FirstTrack),
FRAME_OF_TOC(toc, toc.LastTrack + 1));
*lpRet = 0;
return 0;
}
for (wTrack = 1; wTrack < wmcda->wcda.nTracks; wTrack++) {
if (wmcda->wcda.lpdwTrackPos[wTrack] > dwFrame)
for (wTrack = toc.FirstTrack; wTrack <= toc.LastTrack; wTrack++) {
if (FRAME_OF_TOC(toc, wTrack) > dwFrame)
break;
}
dwFrame -= wmcda->wcda.lpdwTrackPos[wTrack - 1];
wTrack--;
dwFrame -= FRAME_OF_TOC(toc, wTrack);
wMinutes = dwFrame / CDFRAMES_PERMIN;
wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds;
......@@ -216,9 +246,11 @@ static DWORD MCICDA_Stop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms
static DWORD MCICDA_Open(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
{
DWORD dwDeviceID;
DWORD ret = MCIERR_HARDWARE;
WINE_MCICDAUDIO* wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(wDevID);
MCI_SEEK_PARMS seekParms;
int dev;
char root[7];
int count;
char drive = 0;
TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpOpenParms);
......@@ -244,28 +276,54 @@ static DWORD MCICDA_Open(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenPar
WARN("MCI_OPEN_ELEMENT_ID %8lx ! Abort\n", (DWORD)lpOpenParms->lpstrElementName);
return MCIERR_NO_ELEMENT_ALLOWED;
}
WARN("MCI_OPEN_ELEMENT %s ignored\n",lpOpenParms->lpstrElementName);
/*return MCIERR_NO_ELEMENT_ALLOWED;
bon 19991106 allows cdplayer.exe to run*/
if (!isalpha(lpOpenParms->lpstrElementName[0]) || lpOpenParms->lpstrElementName[1] != ':' ||
lpOpenParms->lpstrElementName[2])
{
WARN("MCI_OPEN_ELEMENT unsupported format: %s\n", lpOpenParms->lpstrElementName);
ret = MCIERR_NO_ELEMENT_ALLOWED;
goto the_error;
}
drive = toupper(lpOpenParms->lpstrElementName[0]);
strcpy(root, "A:\\");
root[0] = drive;
if (GetDriveTypeA(root) != DRIVE_CDROM)
{
ret = MCIERR_INVALID_DEVICE_NAME;
goto the_error;
}
}
else
{
/* drive letter isn't passed... get the dwDeviceID'th cdrom in the system */
strcpy(root, "A:\\");
for (count = 0; root[0] <= 'Z'; root[0]++)
{
if (GetDriveTypeA(root) == DRIVE_CDROM && ++count >= dwDeviceID)
{
drive = root[0];
break;
}
}
if (!drive)
{
ret = MCIERR_INVALID_DEVICE_ID;
goto the_error;
}
}
wmcda->wNotifyDeviceID = dwDeviceID;
if (CDROM_Open(&wmcda->wcda, -1) == -1) {
--wmcda->nUseCount;
return MCIERR_HARDWARE;
}
wmcda->mciMode = MCI_MODE_STOP;
wmcda->dwTimeFormat = MCI_FORMAT_MSF;
dev = CDROM_OpenDev(&wmcda->wcda);
if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda, dev)) {
wmcda->mciMode = MCI_MODE_OPEN;
} else {
MCICDA_Seek(wDevID, MCI_SEEK_TO_START, &seekParms);
}
CDROM_CloseDev(dev);
return 0;
/* now, open the handle */
strcpy(root, "\\\\.\\A:");
root[4] = drive;
wmcda->handle = CreateFileA(root, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if (wmcda->handle != INVALID_HANDLE_VALUE)
return 0;
the_error:
--wmcda->nUseCount;
return ret;
}
/**************************************************************************
......@@ -279,10 +337,9 @@ static DWORD MCICDA_Close(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParm
if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
if (wmcda->nUseCount == 1) {
CDROM_Close(&wmcda->wcda);
if (--wmcda->nUseCount == 0) {
CloseHandle(wmcda->handle);
}
wmcda->nUseCount--;
return 0;
}
......@@ -350,6 +407,36 @@ static DWORD MCICDA_GetDevCaps(UINT wDevID, DWORD dwFlags,
return ret;
}
static DWORD CDROM_Audio_GetSerial(CDROM_TOC* toc)
{
unsigned long serial = 0;
int i;
WORD wMagic;
DWORD dwStart, dwEnd;
/*
* wMagic collects the wFrames from track 1
* dwStart, dwEnd collect the beginning and end of the disc respectively, in
* frames.
* There it is collected for correcting the serial when there are less than
* 3 tracks.
*/
wMagic = toc->TrackData[0].Address[3];
dwStart = FRAME_OF_TOC(*toc, toc->FirstTrack);
for (i = 0; i <= toc->LastTrack - toc->FirstTrack; i++) {
serial += (toc->TrackData[i].Address[1] << 16) |
(toc->TrackData[i].Address[2] << 8) | toc->TrackData[i].Address[3];
}
dwEnd = FRAME_OF_TOC(*toc, toc->LastTrack + 1);
if (toc->LastTrack - toc->FirstTrack + 1 < 3)
serial += wMagic + (dwEnd - dwStart);
return serial;
}
/**************************************************************************
* MCICDA_Info [internal]
*/
......@@ -373,23 +460,16 @@ static DWORD MCICDA_Info(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpParms)
} else if (dwFlags & MCI_INFO_MEDIA_UPC) {
ret = MCIERR_NO_IDENTITY;
} else if (dwFlags & MCI_INFO_MEDIA_IDENTITY) {
DWORD res = 0;
int dev = CDROM_OpenDev(&wmcda->wcda);
DWORD res = 0;
CDROM_TOC toc;
DWORD br;
if (!CDROM_Audio_GetCDStatus(&wmcda->wcda, dev)) {
CDROM_CloseDev(dev);
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL)) {
return MCICDA_GetError(wmcda);
}
CDROM_CloseDev(dev);
res = CDROM_Audio_GetSerial(&wmcda->wcda);
if (wmcda->wcda.nTracks <= 2) {
/* there are some other values added when # of tracks < 3
* for most Audio CD it will do without
*/
FIXME("Value is not correct !! "
"Please report with full audio CD information (-debugmsg +cdrom,mcicda)\n");
}
res = CDROM_Audio_GetSerial(&toc);
sprintf(buffer, "%lu", res);
str = buffer;
} else {
......@@ -415,8 +495,13 @@ static DWORD MCICDA_Info(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpParms)
*/
static DWORD MCICDA_Status(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
{
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
DWORD ret = 0;
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
DWORD idx;
DWORD ret = 0;
CDROM_SUB_Q_DATA_FORMAT fmt;
SUB_Q_CHANNEL_DATA data;
CDROM_TOC toc;
DWORD br;
TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
......@@ -432,33 +517,38 @@ static DWORD MCICDA_Status(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParm
TRACE("dwItem = %lx\n", lpParms->dwItem);
switch (lpParms->dwItem) {
case MCI_STATUS_CURRENT_TRACK:
if (!CDROM_Audio_GetCDStatus(&wmcda->wcda, -1)) {
fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt),
&data, sizeof(data), &br, NULL))
{
return MCICDA_GetError(wmcda);
}
lpParms->dwReturn = wmcda->wcda.nCurTrack;
lpParms->dwReturn = data.CurrentPosition.TrackNumber;
TRACE("CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
break;
case MCI_STATUS_LENGTH:
if (wmcda->wcda.nTracks == 0) {
if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda, -1)) {
WARN("error reading TracksInfo !\n");
return MCICDA_GetError(wmcda);
}
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL)) {
WARN("error reading TOC !\n");
return MCICDA_GetError(wmcda);
}
if (dwFlags & MCI_TRACK) {
TRACE("MCI_TRACK #%lu LENGTH=??? !\n", lpParms->dwTrack);
if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
if (lpParms->dwTrack < toc.FirstTrack || lpParms->dwTrack > toc.LastTrack)
return MCIERR_OUTOFRANGE;
lpParms->dwReturn = wmcda->wcda.lpdwTrackLen[lpParms->dwTrack - 1];
idx = lpParms->dwTrack - toc.FirstTrack;
lpParms->dwReturn = FRAME_OF_TOC(toc, lpParms->dwTrack + 1) -
FRAME_OF_TOC(toc, lpParms->dwTrack);
/* Windows returns one frame less than the total track length for the
last track on the CD. See CDDB HOWTO. Verified on Win95OSR2. */
if (lpParms->dwTrack == wmcda->wcda.nTracks)
if (lpParms->dwTrack == toc.LastTrack)
lpParms->dwReturn--;
} else {
/* Sum of the lengths of all of the tracks. Inherits the
'off by one frame' behavior from the length of the last track.
See above comment. */
lpParms->dwReturn = wmcda->wcda.dwLastFrame - wmcda->wcda.dwFirstFrame - 1;
lpParms->dwReturn = FRAME_OF_TOC(toc, toc.LastTrack + 1) -
FRAME_OF_TOC(toc, toc.FirstTrack) - 1;
}
lpParms->dwReturn = MCICDA_CalcTime(wmcda,
(wmcda->dwTimeFormat == MCI_FORMAT_TMSF)
......@@ -468,51 +558,70 @@ static DWORD MCICDA_Status(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParm
TRACE("LENGTH=%lu !\n", lpParms->dwReturn);
break;
case MCI_STATUS_MODE:
CDROM_Audio_GetCDStatus(&wmcda->wcda, -1);
lpParms->dwReturn = MCICDA_Mode(wmcda->wcda.cdaMode);
if (!lpParms->dwReturn) lpParms->dwReturn = wmcda->mciMode;
lpParms->dwReturn = MCICDA_GetStatus(wmcda);
TRACE("MCI_STATUS_MODE=%08lX !\n", lpParms->dwReturn);
lpParms->dwReturn = MAKEMCIRESOURCE(lpParms->dwReturn, lpParms->dwReturn);
ret = MCI_RESOURCE_RETURNED;
break;
case MCI_STATUS_MEDIA_PRESENT:
CDROM_Audio_GetCDStatus(&wmcda->wcda, -1);
lpParms->dwReturn = (wmcda->wcda.nTracks == 0 ||
wmcda->wcda.cdaMode == WINE_CDA_OPEN) ?
lpParms->dwReturn = (MCICDA_GetStatus(wmcda) == MCI_MODE_OPEN) ?
MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
TRACE("MCI_STATUS_MEDIA_PRESENT =%c!\n", LOWORD(lpParms->dwReturn) ? 'Y' : 'N');
ret = MCI_RESOURCE_RETURNED;
break;
case MCI_STATUS_NUMBER_OF_TRACKS:
lpParms->dwReturn = CDROM_Audio_GetNumberOfTracks(&wmcda->wcda, -1);
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL)) {
WARN("error reading TOC !\n");
return MCICDA_GetError(wmcda);
}
lpParms->dwReturn = toc.LastTrack - toc.FirstTrack + 1;
TRACE("MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms->dwReturn);
if (lpParms->dwReturn == (WORD)-1)
return MCICDA_GetError(wmcda);
break;
case MCI_STATUS_POSITION:
if (!CDROM_Audio_GetCDStatus(&wmcda->wcda, -1))
return MCICDA_GetError(wmcda);
if(wmcda->wcda.cdaMode == WINE_CDA_OPEN)
return MCIERR_HARDWARE;
lpParms->dwReturn = wmcda->wcda.dwCurFrame;
if (dwFlags & MCI_STATUS_START) {
lpParms->dwReturn = wmcda->wcda.dwFirstFrame;
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL)) {
WARN("error reading TOC !\n");
return MCICDA_GetError(wmcda);
}
lpParms->dwReturn = FRAME_OF_TOC(toc, toc.FirstTrack);
TRACE("get MCI_STATUS_START !\n");
}
if (dwFlags & MCI_TRACK) {
if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
} else if (dwFlags & MCI_TRACK) {
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL)) {
WARN("error reading TOC !\n");
return MCICDA_GetError(wmcda);
}
if (lpParms->dwTrack < toc.FirstTrack || lpParms->dwTrack > toc.LastTrack)
return MCIERR_OUTOFRANGE;
lpParms->dwReturn = wmcda->wcda.lpdwTrackPos[lpParms->dwTrack - 1];
lpParms->dwReturn = FRAME_OF_TOC(toc, lpParms->dwTrack);
TRACE("get MCI_TRACK #%lu !\n", lpParms->dwTrack);
}
} else {
fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt),
&data, sizeof(data), &br, NULL)) {
return MCICDA_GetError(wmcda);
}
lpParms->dwReturn = FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress);
}
lpParms->dwReturn = MCICDA_CalcTime(wmcda, wmcda->dwTimeFormat, lpParms->dwReturn, &ret);
TRACE("MCI_STATUS_POSITION=%08lX !\n", lpParms->dwReturn);
break;
case MCI_STATUS_READY:
TRACE("MCI_STATUS_READY !\n");
lpParms->dwReturn = (wmcda->wcda.cdaMode == WINE_CDA_DONTKNOW ||
wmcda->wcda.cdaMode == WINE_CDA_NOTREADY) ?
MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
switch (MCICDA_GetStatus(wmcda))
{
case MCI_MODE_NOT_READY:
case MCI_MODE_OPEN:
lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
break;
default:
lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
break;
}
TRACE("MCI_STATUS_READY=%u!\n", LOWORD(lpParms->dwReturn));
ret = MCI_RESOURCE_RETURNED;
break;
......@@ -526,15 +635,16 @@ static DWORD MCICDA_Status(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParm
if (!(dwFlags & MCI_TRACK))
ret = MCIERR_MISSING_PARAMETER;
else {
if(!CDROM_Audio_GetTracksInfo(&wmcda->wcda, -1)) {
WARN("Error reading tracks info\n");
return MCICDA_GetError(wmcda);
}
if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL)) {
WARN("error reading TOC !\n");
return MCICDA_GetError(wmcda);
}
if (lpParms->dwTrack < toc.FirstTrack || lpParms->dwTrack > toc.LastTrack)
ret = MCIERR_OUTOFRANGE;
else
lpParms->dwReturn = (wmcda->wcda.lpbTrackFlags[lpParms->dwTrack - 1] &
CDROM_DATA_TRACK) ? MCI_CDA_TRACK_OTHER : MCI_CDA_TRACK_AUDIO;
lpParms->dwReturn = (toc.TrackData[lpParms->dwTrack - toc.FirstTrack].Control & 0x04) ?
MCI_CDA_TRACK_OTHER : MCI_CDA_TRACK_AUDIO;
}
TRACE("MCI_CDA_STATUS_TYPE_TRACK[%ld]=%08lx\n", lpParms->dwTrack, lpParms->dwReturn);
break;
......@@ -553,11 +663,14 @@ static DWORD MCICDA_Status(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParm
*/
static DWORD MCICDA_Play(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
{
int start, end;
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
DWORD ret = 0;
int dev = -1;
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
DWORD ret = 0, start, end;
CDROM_TOC toc;
DWORD br;
CDROM_PLAY_AUDIO_MSF play;
CDROM_SUB_Q_DATA_FORMAT fmt;
SUB_Q_CHANNEL_DATA data;
TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
if (lpParms == NULL)
......@@ -566,48 +679,45 @@ static DWORD MCICDA_Play(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
if (wmcda == NULL)
return MCIERR_INVALID_DEVICE_ID;
dev = CDROM_OpenDev(&wmcda->wcda);
if (wmcda->wcda.nTracks == 0) {
if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda, dev)) {
WARN("error reading TracksInfo !\n");
ret = MCIERR_DRIVER_INTERNAL;
goto end;
}
}
wmcda->wcda.nCurTrack = 1;
if (dwFlags & MCI_FROM) {
start = MCICDA_CalcFrame(wmcda, lpParms->dwFrom);
TRACE("MCI_FROM=%08lX -> %u \n", lpParms->dwFrom, start);
TRACE("MCI_FROM=%08lX -> %lu \n", lpParms->dwFrom, start);
} else {
if (!CDROM_Audio_GetCDStatus(&wmcda->wcda, dev))
{
ret = MCIERR_DRIVER_INTERNAL;
goto end;
}
start = wmcda->wcda.dwCurFrame;
fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt),
&data, sizeof(data), &br, NULL)) {
return MCICDA_GetError(wmcda);
}
start = FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress);
}
if (dwFlags & MCI_TO) {
end = MCICDA_CalcFrame(wmcda, lpParms->dwTo);
TRACE("MCI_TO=%08lX -> %u \n", lpParms->dwTo, end);
} else
end = wmcda->wcda.dwLastFrame;
if (CDROM_Audio_Play(&wmcda->wcda, start, end, dev) == -1)
{
ret = MCIERR_HARDWARE;
goto end;
TRACE("MCI_TO=%08lX -> %lu \n", lpParms->dwTo, end);
} else {
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL)) {
WARN("error reading TOC !\n");
return MCICDA_GetError(wmcda);
}
end = FRAME_OF_TOC(toc, toc.LastTrack + 1) - 1;
}
wmcda->mciMode = MCI_MODE_PLAY;
if (dwFlags & MCI_NOTIFY) {
TRACE("Playing from %lu to %lu\n", start, end);
play.StartingM = start / CDFRAMES_PERMIN;
play.StartingS = (start / CDFRAMES_PERSEC) % 60;
play.StartingF = start % CDFRAMES_PERSEC;
play.EndingM = end / CDFRAMES_PERMIN;
play.EndingS = (end / CDFRAMES_PERSEC) % 60;
play.EndingF = end % CDFRAMES_PERSEC;
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_PLAY_AUDIO_MSF, &play, sizeof(play),
NULL, 0, &br, NULL)) {
ret = MCIERR_HARDWARE;
} else if (dwFlags & MCI_NOTIFY) {
TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
/*
mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
*/
}
end:
if (dev != -1)
CDROM_CloseDev(dev);
return ret;
}
......@@ -617,15 +727,15 @@ end:
static DWORD MCICDA_Stop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
{
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
DWORD br;
TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
if (CDROM_Audio_Stop(&wmcda->wcda, -1) == -1)
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_STOP_AUDIO, NULL, 0, NULL, 0, &br, NULL))
return MCIERR_HARDWARE;
wmcda->mciMode = MCI_MODE_STOP;
if (lpParms && (dwFlags & MCI_NOTIFY)) {
TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
......@@ -640,14 +750,15 @@ static DWORD MCICDA_Stop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms
static DWORD MCICDA_Pause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
{
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
DWORD br;
TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
if (CDROM_Audio_Pause(&wmcda->wcda, 1, -1) == -1)
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL))
return MCIERR_HARDWARE;
wmcda->mciMode = MCI_MODE_PAUSE;
if (lpParms && (dwFlags & MCI_NOTIFY)) {
TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
......@@ -662,14 +773,15 @@ static DWORD MCICDA_Pause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParm
static DWORD MCICDA_Resume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
{
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
DWORD br;
TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
if (CDROM_Audio_Pause(&wmcda->wcda, 0, -1) == -1)
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_RESUME_AUDIO, NULL, 0, NULL, 0, &br, NULL))
return MCIERR_HARDWARE;
wmcda->mciMode = MCI_MODE_STOP;
if (lpParms && (dwFlags & MCI_NOTIFY)) {
TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
......@@ -683,23 +795,35 @@ static DWORD MCICDA_Resume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpPar
*/
static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
{
DWORD at;
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
DWORD at;
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
CDROM_SEEK_AUDIO_MSF seek;
CDROM_TOC toc;
DWORD br;
TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
wmcda->mciMode = MCI_MODE_SEEK;
switch (dwFlags & ~(MCI_NOTIFY|MCI_WAIT)) {
case MCI_SEEK_TO_START:
TRACE("Seeking to start\n");
at = wmcda->wcda.dwFirstFrame;
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL)) {
WARN("error reading TOC !\n");
return MCICDA_GetError(wmcda);
}
at = FRAME_OF_TOC(toc, toc.FirstTrack);
break;
case MCI_SEEK_TO_END:
TRACE("Seeking to end\n");
at = wmcda->wcda.dwLastFrame;
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0,
&toc, sizeof(toc), &br, NULL)) {
WARN("error reading TOC !\n");
return MCICDA_GetError(wmcda);
}
at = FRAME_OF_TOC(toc, toc.LastTrack + 1) - 1;
break;
case MCI_TO:
TRACE("Seeking to %lu\n", lpParms->dwTo);
......@@ -710,9 +834,13 @@ static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
(dwFlags & ~(MCI_NOTIFY|MCI_WAIT)));
return MCIERR_UNSUPPORTED_FUNCTION;
}
if (CDROM_Audio_Seek(&wmcda->wcda, at, -1) == -1) {
seek.M = at / CDFRAMES_PERMIN;
seek.S = (at / CDFRAMES_PERSEC) % 60;
seek.F = at % CDFRAMES_PERSEC;
if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_SEEK_AUDIO_MSF, &seek, sizeof(seek),
NULL, 0, &br, NULL))
return MCIERR_HARDWARE;
}
if (dwFlags & MCI_NOTIFY) {
TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
......@@ -724,17 +852,20 @@ static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
/**************************************************************************
* MCICDA_SetDoor [internal]
*/
static DWORD MCICDA_SetDoor(UINT wDevID, int open)
static DWORD MCICDA_SetDoor(UINT wDevID, BOOL open)
{
WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
DWORD br;
TRACE("(%04x, %s) !\n", wDevID, (open) ? "OPEN" : "CLOSE");
if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
if (CDROM_SetDoor(&wmcda->wcda, open, -1) == -1)
if (!DeviceIoControl(wmcda->handle,
(open) ? IOCTL_STORAGE_EJECT_MEDIA : IOCTL_STORAGE_LOAD_MEDIA,
NULL, 0, NULL, 0, &br, NULL))
return MCIERR_HARDWARE;
wmcda->mciMode = (open) ? MCI_MODE_OPEN : MCI_MODE_STOP;
return 0;
}
......
......@@ -4,7 +4,7 @@
*
* Cdrom - device driver emulation - Audio features.
* (c) 1998 Petr Tomasek <tomasek@etf.cuni.cz>
* (c) 1999 Eric Pouech
* (c) 1999,2002 Eric Pouech
*/
#include "config.h"
......@@ -15,7 +15,9 @@
#include "module.h"
/* #define DEBUG_INT */
#include "debugtools.h"
#include "cdrom.h"
#include "winioctl.h"
#include "ntddstor.h"
#include "ntddcdrm.h"
DEFAULT_DEBUG_CHANNEL(int);
......@@ -414,12 +416,19 @@ static void MSCDEX_Dump(char* pfx, BYTE* req, int dorealmode)
#define MSCDEX_Dump(pfx, req, drm)
#endif
#define CDFRAMES_PERSEC 75
#define CDFRAMES_PERMIN (CDFRAMES_PERSEC * 60)
#define FRAME_OF_ADDR(a) ((a)[1] * CDFRAMES_PERMIN + (a)[2] * CDFRAMES_PERSEC + (a)[3])
#define FRAME_OF_TOC(toc, idx) FRAME_OF_ADDR((toc).TrackData[idx - (toc).FirstTrack].Address)
#define CTRL_OF_TOC(toc, idx) (((toc).TrackData[idx - (toc).FirstTrack].Control << 4) | \
(toc).TrackData[idx - (toc).FirstTrack].Adr)
static void MSCDEX_StoreMSF(DWORD frame, BYTE* val)
{
val[3] = 0; /* zero */
val[2] = frame / CDFRAMES_PERMIN; /* minutes */
val[1] = (frame - CDFRAMES_PERMIN * val[2]) / CDFRAMES_PERSEC; /* seconds */
val[0] = frame - CDFRAMES_PERMIN * val[2] - CDFRAMES_PERSEC * val[1]; /* frames */
val[1] = (frame / CDFRAMES_PERSEC) % 60; /* seconds */
val[0] = frame % CDFRAMES_PERSEC; /* frames */
}
static int is_cdrom( int drive)
......@@ -434,7 +443,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
int drive, count;
char* p;
switch(LOBYTE(context->Eax)) {
switch (LOBYTE(context->Eax)) {
case 0x00: /* Installation check */
/* Count the number of contiguous CDROM drives
*/
......@@ -470,13 +479,18 @@ static void MSCDEX_Handler(CONTEXT86* context)
case 0x10: /* direct driver access */
{
static WINE_CDAUDIO wcda;
int dev = -1;
BYTE* driver_request;
BYTE* io_stru;
BYTE Error = 255; /* No Error */
int dorealmode = ISV86(context);
char devName[] = "\\\\.\\@:";
HANDLE h;
CDROM_TOC toc;
CDROM_SUB_Q_DATA_FORMAT fmt;
SUB_Q_CHANNEL_DATA data;
DWORD br;
DWORD present = TRUE;
driver_request = CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx);
if (!driver_request) {
......@@ -489,16 +503,13 @@ static void MSCDEX_Handler(CONTEXT86* context)
return;
}
/* FIXME
* - the current implementation only supports a single CD ROM
* the following tests are wrong because lots of functions don't require the
* tray to be closed with a CD inside
*/
CDROM_Open(&wcda, -1);
dev = CDROM_OpenDev(&wcda);
TRACE("CDROM device driver -> command <%d>\n", (unsigned char)driver_request[2]);
for (drive = 0; drive < 26; drive++) if (is_cdrom(drive)) break;
/* drive contains the first CD ROM */
if (CX_reg(context) != drive) {
WARN("Request made doesn't match a CD ROM drive (%d/%d)\n", CX_reg(context), drive);
if (!is_cdrom(CX_reg(context))) {
WARN("Request made doesn't match a CD ROM drive (%d)\n", CX_reg(context));
driver_request[4] |= 0x80;
driver_request[3] = 1; /* unknown unit */
return;
......@@ -508,8 +519,39 @@ static void MSCDEX_Handler(CONTEXT86* context)
/* set status to 0 */
PTR_AT(driver_request, 3, WORD) = 0;
CDROM_Audio_GetCDStatus(&wcda, dev);
devName[4] = 'A' + CX_reg(context);
h = CreateFileA(devName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if (!h) {
WARN("Couldn't open cdrom handle\n");
driver_request[4] |= 0x80;
driver_request[3] = 1; /* unknown unit */
return;
}
fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
if (!DeviceIoControl(h, IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &br, NULL) ||
!DeviceIoControl(h, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt),
&data, sizeof(data), &br, NULL)) {
if (GetLastError() == STATUS_NO_MEDIA_IN_DEVICE)
{
if (driver_request[2] != 6 && driver_request[2] != 15)
{
driver_request[4] |= 0x80;
driver_request[3] = 2; /* drive not ready */
CloseHandle(h);
return;
}
present = FALSE;
}
else
{
driver_request[4] |= 0x80;
driver_request[3] = 1; /* unknown unit */
CloseHandle(h);
return;
}
}
switch (driver_request[2]) {
case 3:
io_stru = (dorealmode) ?
......@@ -548,10 +590,12 @@ static void MSCDEX_Handler(CONTEXT86* context)
case 1: /* location of head */
switch (io_stru[1]) {
case 0:
PTR_AT(io_stru, 2, DWORD) = wcda.dwCurFrame;
PTR_AT(io_stru, 2, DWORD) =
FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress);
break;
case 1:
MSCDEX_StoreMSF(wcda.dwCurFrame, io_stru + 2);
MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress),
io_stru + 2);
break;
default:
ERR("CD-ROM driver: unsupported addressing mode !!\n");
......@@ -588,13 +632,13 @@ static void MSCDEX_Handler(CONTEXT86* context)
* 0 Door locked
* 0 see below (Door closed/opened)
*/
if (wcda.cdaMode == WINE_CDA_OPEN)
io_stru[1] |= 1;
if (!present) PTR_AT(io_stru, 1, DWORD) |= 1;
TRACE(" ----> DEVICE STATUS <0x%08lx>\n", PTR_AT(io_stru, 1, DWORD));
break;
case 8: /* Volume size */
PTR_AT(io_stru, 1, DWORD) = wcda.dwLastFrame;
PTR_AT(io_stru, 1, DWORD) = FRAME_OF_TOC(toc, toc.LastTrack + 1) -
FRAME_OF_TOC(toc, toc.FirstTrack) - 1;
TRACE(" ----> VOLUME SIZE <%ld>\n", PTR_AT(io_stru, 1, DWORD));
break;
......@@ -605,20 +649,20 @@ static void MSCDEX_Handler(CONTEXT86* context)
break;
case 10: /* audio disk info */
io_stru[1] = wcda.nFirstTrack; /* starting track of the disc */
io_stru[2] = wcda.nLastTrack; /* ending track */
MSCDEX_StoreMSF(wcda.dwLastFrame, io_stru + 3);
io_stru[1] = toc.FirstTrack; /* starting track of the disc */
io_stru[2] = toc.LastTrack; /* ending track */
MSCDEX_StoreMSF(FRAME_OF_TOC(toc, toc.LastTrack + 1) -
FRAME_OF_TOC(toc, toc.FirstTrack) - 1, io_stru + 3);
TRACE(" ----> AUDIO DISK INFO <%d-%d/%08lx>\n",
io_stru[1], io_stru[2], PTR_AT(io_stru, 3, DWORD));
break;
case 11: /* audio track info */
if (io_stru[1] >= wcda.nFirstTrack && io_stru[1] <= wcda.nLastTrack) {
int nt = io_stru[1] - wcda.nFirstTrack;
MSCDEX_StoreMSF(wcda.lpdwTrackPos[nt], io_stru + 2);
if (io_stru[1] >= toc.FirstTrack && io_stru[1] <= toc.LastTrack) {
MSCDEX_StoreMSF(FRAME_OF_TOC(toc, io_stru[1]), io_stru + 2);
/* starting point if the track */
io_stru[6] = (wcda.lpbTrackFlags[nt] & 0xF0) >> 4;
io_stru[6] = CTRL_OF_TOC(toc, io_stru[1]);
} else {
PTR_AT(io_stru, 2, DWORD) = 0;
io_stru[6] = 0;
......@@ -628,42 +672,43 @@ static void MSCDEX_Handler(CONTEXT86* context)
break;
case 12: /* get Q-Channel info */
io_stru[1] = wcda.lpbTrackFlags[wcda.nCurTrack - 1];
io_stru[2] = wcda.nCurTrack;
io_stru[1] = CTRL_OF_TOC(toc, data.CurrentPosition.TrackNumber);
io_stru[2] = data.CurrentPosition.TrackNumber;
io_stru[3] = 0; /* FIXME ?? */
/* why the heck did MS use another format for 0MSF information... sigh */
{
BYTE bTmp[4];
MSCDEX_StoreMSF(wcda.dwCurFrame - wcda.lpdwTrackPos[wcda.nCurTrack - 1], bTmp);
MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.TrackRelativeAddress), bTmp);
io_stru[ 4] = bTmp[2];
io_stru[ 5] = bTmp[1];
io_stru[ 6] = bTmp[0];
io_stru[ 7] = 0;
MSCDEX_StoreMSF(wcda.dwCurFrame, bTmp);
MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress), bTmp);
io_stru[ 8] = bTmp[2];
io_stru[ 9] = bTmp[1];
io_stru[10] = bTmp[0];
io_stru[11] = 0;
}
TRACE("Q-Channel info: Ctrl/adr=%02x TNO=%02x X=%02x rtt=%02x:%02x:%02x rtd=%02x:%02x:%02x (cf=%08lx, tp=%08lx)\n",
TRACE("Q-Channel info: Ctrl/adr=%02x TNO=%02x X=%02x rtt=%02x:%02x:%02x rtd=%02x:%02x:%02x (cf=%08x, tp=%08x)\n",
io_stru[ 1], io_stru[ 2], io_stru[ 3],
io_stru[ 4], io_stru[ 5], io_stru[ 6],
io_stru[ 8], io_stru[ 9], io_stru[10],
wcda.dwCurFrame, wcda.lpdwTrackPos[wcda.nCurTrack - 1]);
FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress),
FRAME_OF_TOC(toc, data.CurrentPosition.TrackNumber));
break;
case 15: /* Audio status info */
/* !!!! FIXME FIXME FIXME !! */
PTR_AT(io_stru, 1, WORD) = 2 | ((wcda.cdaMode == WINE_CDA_PAUSE) ? 1 : 0);
if (wcda.cdaMode == WINE_CDA_OPEN) {
PTR_AT(io_stru, 1, WORD) = 2 | ((data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_PAUSED) ? 1 : 0);
if (!present) {
PTR_AT(io_stru, 3, DWORD) = 0;
PTR_AT(io_stru, 7, DWORD) = 0;
} else {
PTR_AT(io_stru, 3, DWORD) = wcda.lpdwTrackPos[0];
PTR_AT(io_stru, 7, DWORD) = wcda.lpdwTrackPos[wcda.nTracks - 1];
PTR_AT(io_stru, 3, DWORD) = FRAME_OF_TOC(toc, toc.FirstTrack);
PTR_AT(io_stru, 7, DWORD) = FRAME_OF_TOC(toc, toc.LastTrack + 1);
}
TRACE("Audio status info: status=%04x startLoc=%ld endLoc=%ld\n",
PTR_AT(io_stru, 1, WORD), PTR_AT(io_stru, 3, DWORD), PTR_AT(io_stru, 7, DWORD));
......@@ -684,18 +729,18 @@ static void MSCDEX_Handler(CONTEXT86* context)
TRACE(" --> IOCTL OUTPUT <%d>\n", io_stru[0]);
switch (io_stru[0]) {
case 0: /* eject */
CDROM_SetDoor(&wcda, 1, dev);
DeviceIoControl(h, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &br, NULL);
TRACE(" ----> EJECT\n");
break;
case 2: /* reset drive */
CDROM_Reset(&wcda, dev);
DeviceIoControl(h, IOCTL_STORAGE_RESET_DEVICE, NULL, 0, NULL, 0, &br, NULL);
TRACE(" ----> RESET\n");
break;
case 3: /* Audio Channel Control */
FIXME(" ----> AUDIO CHANNEL CONTROL (NIY)\n");
break;
case 5: /* close tray */
CDROM_SetDoor(&wcda, 0, dev);
DeviceIoControl(h, IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &br, NULL);
TRACE(" ----> CLOSE TRAY\n");
break;
default:
......@@ -705,10 +750,57 @@ static void MSCDEX_Handler(CONTEXT86* context)
}
break;
case 128: /* read long */
{
LPVOID dst = MapSL(MAKESEGPTR(PTR_AT(driver_request, 16, WORD),
PTR_AT(driver_request, 14, WORD)));
DWORD at = PTR_AT(driver_request, 20, DWORD);
WORD num = PTR_AT(driver_request, 18, WORD);
RAW_READ_INFO rri;
switch (driver_request[13]) {
case 1: /* Red book addressing mode = 0:m:s:f */
/* FIXME : frame <=> msf conversion routines could be shared
* between mscdex and mcicda
*/
at = LOBYTE(HIWORD(at)) * CDFRAMES_PERMIN +
HIBYTE(LOWORD(at)) * CDFRAMES_PERSEC +
LOBYTE(LOWORD(at));
/* fall through */
case 0: /* HSG addressing mode */
switch (PTR_AT(driver_request, 24, BYTE))
{
case 0: /* cooked */
ReadFile(h, dst, num * 2048, &br, NULL);
break;
case 1:
/* FIXME: computation is wrong */
rri.DiskOffset.s.HighPart = 0;
rri.DiskOffset.s.LowPart = at << 11;
rri.TrackMode = YellowMode2;
rri.SectorCount = num;
DeviceIoControl(h, IOCTL_CDROM_RAW_READ, &rri, sizeof(rri),
dst, num * 2352, &br, NULL);
break;
default:
ERR("Unsupported read mode !!\n");
Error = 0x0c;
break;
}
break;
default:
ERR("Unsupported address mode !!\n");
Error = 0x0c;
break;
}
}
break;
case 131: /* seek */
{
DWORD at;
DWORD at;
CDROM_SEEK_AUDIO_MSF seek;
at = PTR_AT(driver_request, 20, DWORD);
TRACE(" --> SEEK AUDIO mode :<0x%02X>, [%ld]\n",
......@@ -724,7 +816,11 @@ static void MSCDEX_Handler(CONTEXT86* context)
LOBYTE(LOWORD(at));
/* fall through */
case 0: /* HSG addressing mode */
CDROM_Audio_Seek(&wcda, at, dev);
seek.M = at / CDFRAMES_PERMIN;
seek.S = (at / CDFRAMES_PERSEC) % 60;
seek.F = at % CDFRAMES_PERSEC;
DeviceIoControl(h, IOCTL_CDROM_SEEK_AUDIO_MSF, &seek, sizeof(seek),
NULL, 0, &br, NULL);
break;
default:
ERR("Unsupported address mode !!\n");
......@@ -736,8 +832,9 @@ static void MSCDEX_Handler(CONTEXT86* context)
case 132: /* play */
{
DWORD beg, end;
DWORD beg, end;
CDROM_PLAY_AUDIO_MSF play;
beg = end = PTR_AT(driver_request, 14, DWORD);
end += PTR_AT(driver_request, 18, DWORD);
......@@ -745,19 +842,27 @@ static void MSCDEX_Handler(CONTEXT86* context)
(BYTE)driver_request[13], beg, end);
switch (driver_request[13]) {
case 1: /* Red book addressing mode = 0:m:s:f */
case 1:
/* Red book addressing mode = 0:m:s:f */
/* FIXME : frame <=> msf conversion routines could be shared
* between mscdex and mcicda
*/
beg = LOBYTE(HIWORD(beg)) * CDFRAMES_PERMIN +
beg = LOBYTE(LOWORD(beg)) * CDFRAMES_PERMIN +
HIBYTE(LOWORD(beg)) * CDFRAMES_PERSEC +
LOBYTE(LOWORD(beg));
end = LOBYTE(HIWORD(end)) * CDFRAMES_PERMIN +
LOBYTE(HIWORD(beg));
end = LOBYTE(LOWORD(end)) * CDFRAMES_PERMIN +
HIBYTE(LOWORD(end)) * CDFRAMES_PERSEC +
LOBYTE(LOWORD(end));
LOBYTE(HIWORD(end));
/* fall through */
case 0: /* HSG addressing mode */
CDROM_Audio_Play(&wcda, beg, end, dev);
play.StartingM = beg / CDFRAMES_PERMIN;
play.StartingS = (beg / CDFRAMES_PERSEC) % 60;
play.StartingF = beg % CDFRAMES_PERSEC;
play.EndingM = end / CDFRAMES_PERMIN;
play.EndingS = (end / CDFRAMES_PERSEC) % 60;
play.EndingF = end % CDFRAMES_PERSEC;
DeviceIoControl(h, IOCTL_CDROM_PLAY_AUDIO_MSF, &play, sizeof(play),
NULL, 0, &br, NULL);
break;
default:
ERR("Unsupported address mode !!\n");
......@@ -768,18 +873,18 @@ static void MSCDEX_Handler(CONTEXT86* context)
break;
case 133:
if (wcda.cdaMode == WINE_CDA_PLAY) {
CDROM_Audio_Pause(&wcda, 1, dev);
if (data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) {
DeviceIoControl(h, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL);
TRACE(" --> STOP AUDIO (Paused)\n");
} else {
CDROM_Audio_Stop(&wcda, dev);
DeviceIoControl(h, IOCTL_CDROM_STOP_AUDIO, NULL, 0, NULL, 0, &br, NULL);
TRACE(" --> STOP AUDIO (Stopped)\n");
}
break;
case 136:
TRACE(" --> RESUME AUDIO\n");
CDROM_Audio_Pause(&wcda, 0, dev);
DeviceIoControl(h, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL);
break;
default:
......@@ -792,14 +897,14 @@ static void MSCDEX_Handler(CONTEXT86* context)
driver_request[4] |= 0x80;
driver_request[3] = Error;
}
CDROM_CloseDev(dev);
CDROM_Close(&wcda);
CloseHandle(h);
/* setting status bits
* 3 == playing && done
* 1 == done
*/
driver_request[4] |= (wcda.cdaMode == WINE_CDA_PLAY) ? 3 : 1;
driver_request[4] |=
(data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) ? 3 : 1;
MSCDEX_Dump("End", driver_request, dorealmode);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment