Now using the NT CD interface.
This commit is contained in:
parent
5cc6105b39
commit
f65c7d546d
|
@ -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;
|
||||
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:
|
||||
FIXME("Unknown mode %04x\n", wcdaMode);
|
||||
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);
|
||||
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));
|
||||
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);
|
||||
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);
|
||||
|
||||
/* 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]
|
||||
*/
|
||||
|
@ -374,22 +461,15 @@ static DWORD MCICDA_Info(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpParms)
|
|||
ret = MCIERR_NO_IDENTITY;
|
||||
} else if (dwFlags & MCI_INFO_MEDIA_IDENTITY) {
|
||||
DWORD res = 0;
|
||||
int dev = CDROM_OpenDev(&wmcda->wcda);
|
||||
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 {
|
||||
|
@ -416,7 +496,12 @@ 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 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");
|
||||
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;
|
||||
TRACE("get MCI_STATUS_START !\n");
|
||||
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) {
|
||||
if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
|
||||
lpParms->dwReturn = FRAME_OF_TOC(toc, toc.FirstTrack);
|
||||
TRACE("get MCI_STATUS_START !\n");
|
||||
} 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");
|
||||
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 > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
|
||||
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,10 +663,13 @@ 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;
|
||||
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);
|
||||
|
||||
|
@ -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;
|
||||
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 = wmcda->wcda.dwCurFrame;
|
||||
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);
|
||||
}
|
||||
wmcda->mciMode = MCI_MODE_PLAY;
|
||||
if (dwFlags & MCI_NOTIFY) {
|
||||
end = FRAME_OF_TOC(toc, toc.LastTrack + 1) - 1;
|
||||
}
|
||||
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),
|
||||
|
@ -685,21 +797,33 @@ static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
213
msdos/int2f.c
213
msdos/int2f.c
|
@ -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,12 +479,17 @@ 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);
|
||||
|
||||
|
@ -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,7 +519,38 @@ 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:
|
||||
|
@ -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,9 +750,56 @@ 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;
|
||||
CDROM_SEEK_AUDIO_MSF seek;
|
||||
|
||||
at = PTR_AT(driver_request, 20, DWORD);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -737,6 +833,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
|
|||
case 132: /* play */
|
||||
{
|
||||
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:
|
||||
|
@ -793,13 +898,13 @@ static void MSCDEX_Handler(CONTEXT86* context)
|
|||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue