Skip to content
Snippets Groups Projects
Commit f65c7d54 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard
Browse files

Now using the NT CD interface.

parent 5cc6105b
No related branches found
No related tags found
No related merge requests found
......@@ -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);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment