From f65c7d546ddbd07ad7c50bf2227d89e9034b415e Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sun, 13 Jan 2002 01:46:12 +0000 Subject: [PATCH] Now using the NT CD interface. --- dlls/winmm/mcicda/Makefile.in | 1 - dlls/winmm/mcicda/mcicda.c | 471 ++++++++++++++++++++++------------ msdos/int2f.c | 227 +++++++++++----- 3 files changed, 467 insertions(+), 232 deletions(-) diff --git a/dlls/winmm/mcicda/Makefile.in b/dlls/winmm/mcicda/Makefile.in index 14780b84545..9b1cb25b164 100644 --- a/dlls/winmm/mcicda/Makefile.in +++ b/dlls/winmm/mcicda/Makefile.in @@ -3,7 +3,6 @@ TOPOBJDIR = ../../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = mcicda.drv -IMPORTS = ntdll LDDLLFLAGS = @LDDLLFLAGS@ SYMBOLFILE = $(MODULE).tmp.o diff --git a/dlls/winmm/mcicda/mcicda.c b/dlls/winmm/mcicda/mcicda.c index 9dd940151c3..fba5ded9009 100644 --- a/dlls/winmm/mcicda/mcicda.c +++ b/dlls/winmm/mcicda/mcicda.c @@ -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; } diff --git a/msdos/int2f.c b/msdos/int2f.c index ed6fffbdd8e..0a44ac36c39 100644 --- a/msdos/int2f.c +++ b/msdos/int2f.c @@ -4,7 +4,7 @@ * * Cdrom - device driver emulation - Audio features. * (c) 1998 Petr Tomasek - * (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); }