/* * Copyright (C) 2002-2007 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* $Id: cdrom_ioctl_win32.cpp,v 1.14 2007/01/08 19:45:39 qbix79 Exp $ */ #if defined (WIN32) // ***************************************************************** // Windows IOCTL functions (not suitable for 95/98/Me) // ***************************************************************** #include #include #if defined (_MSC_VER) #include // Ioctl stuff #include // Ioctl stuff #else #include "ddk/ntddcdrm.h" // Ioctl stuff #endif #include "cdrom.h" CDROM_Interface_Ioctl::CDROM_Interface_Ioctl() { pathname[0] = 0; hIOCTL = INVALID_HANDLE_VALUE; memset(&oldLeadOut,0,sizeof(oldLeadOut)); }; CDROM_Interface_Ioctl::~CDROM_Interface_Ioctl() { StopAudio(); Close(); }; bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc) { // FIXME : To Do return true; } bool CDROM_Interface_Ioctl::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut) { // Open(); CDROM_TOC toc; DWORD byteCount; BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &byteCount,NULL); // Close(); if (!bStat) return false; stTrack = toc.FirstTrack; endTrack = toc.LastTrack; leadOut.min = toc.TrackData[endTrack].Address[1]; leadOut.sec = toc.TrackData[endTrack].Address[2]; leadOut.fr = toc.TrackData[endTrack].Address[3]; return true; }; bool CDROM_Interface_Ioctl::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) { // Open(); CDROM_TOC toc; DWORD byteCount; BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &byteCount,NULL); // Close(); if (!bStat) return false; attr = (toc.TrackData[track-1].Control << 4) & 0xEF; start.min = toc.TrackData[track-1].Address[1]; start.sec = toc.TrackData[track-1].Address[2]; start.fr = toc.TrackData[track-1].Address[3]; return true; }; bool CDROM_Interface_Ioctl::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) { // Open(); CDROM_SUB_Q_DATA_FORMAT insub; SUB_Q_CHANNEL_DATA sub; DWORD byteCount; insub.Format = IOCTL_CDROM_CURRENT_POSITION; BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), &sub, sizeof(sub), &byteCount,NULL); // Close(); if (!bStat) return false; attr = (sub.CurrentPosition.Control << 4) & 0xEF; track = sub.CurrentPosition.TrackNumber; index = sub.CurrentPosition.IndexNumber; relPos.min = sub.CurrentPosition.TrackRelativeAddress[1]; relPos.sec = sub.CurrentPosition.TrackRelativeAddress[2]; relPos.fr = sub.CurrentPosition.TrackRelativeAddress[3]; absPos.min = sub.CurrentPosition.AbsoluteAddress[1]; absPos.sec = sub.CurrentPosition.AbsoluteAddress[2]; absPos.fr = sub.CurrentPosition.AbsoluteAddress[3]; return true; }; bool CDROM_Interface_Ioctl::GetAudioStatus(bool& playing, bool& pause) { // Open(); CDROM_SUB_Q_DATA_FORMAT insub; SUB_Q_CHANNEL_DATA sub; DWORD byteCount; insub.Format = IOCTL_CDROM_CURRENT_POSITION; BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), &sub, sizeof(sub), &byteCount,NULL); // Close(); if (!bStat) return false; playing = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS); pause = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_PAUSED); return true; }; bool CDROM_Interface_Ioctl::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) { // Seems not possible to get this values using ioctl... int track1,track2; TMSF leadOut; // If we can read, there's a media mediaPresent = GetAudioTracks(track1, track2, leadOut), trayOpen = !mediaPresent; mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr); if (mediaChanged) { // Open new media Close(); Open(); }; // Save old values oldLeadOut.min = leadOut.min; oldLeadOut.sec = leadOut.sec; oldLeadOut.fr = leadOut.fr; // always success return true; }; bool CDROM_Interface_Ioctl::PlayAudioSector (unsigned long start,unsigned long len) { // Open(); CDROM_PLAY_AUDIO_MSF audio; DWORD byteCount; // Start unsigned long addr = start + 150; audio.StartingF = (UCHAR)(addr%75); addr/=75; audio.StartingS = (UCHAR)(addr%60); audio.StartingM = (UCHAR)(addr/60); // End addr = start + len + 150; audio.EndingF = (UCHAR)(addr%75); addr/=75; audio.EndingS = (UCHAR)(addr%60); audio.EndingM = (UCHAR)(addr/60); BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PLAY_AUDIO_MSF, &audio, sizeof(audio), NULL, 0, &byteCount,NULL); // Close(); return bStat>0; }; bool CDROM_Interface_Ioctl::PauseAudio(bool resume) { // Open(); BOOL bStat; DWORD byteCount; if (resume) bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RESUME_AUDIO, NULL, 0, NULL, 0, &byteCount,NULL); else bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &byteCount,NULL); // Close(); return bStat>0; }; bool CDROM_Interface_Ioctl::StopAudio(void) { // Open(); BOOL bStat; DWORD byteCount; bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_STOP_AUDIO, NULL, 0, NULL, 0, &byteCount,NULL); // Close(); return bStat>0; }; bool CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload) { // Open(); BOOL bStat; DWORD byteCount; if (unload) bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &byteCount,NULL); else bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &byteCount,NULL); // Close(); return bStat>0; }; bool CDROM_Interface_Ioctl::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { BOOL bStat; DWORD byteCount = 0; // Open(); Bitu buflen = raw ? num*RAW_SECTOR_SIZE : num*COOKED_SECTOR_SIZE; Bit8u* bufdata = new Bit8u[buflen]; if (!raw) { // Cooked int success = 0; DWORD newPos = SetFilePointer(hIOCTL, sector*COOKED_SECTOR_SIZE, 0, FILE_BEGIN); if (newPos != 0xFFFFFFFF) success = ReadFile(hIOCTL, bufdata, buflen, &byteCount, NULL); bStat = (success!=0); } else { // Raw RAW_READ_INFO in; in.DiskOffset.LowPart = sector; in.DiskOffset.HighPart = 0; in.SectorCount = num; in.TrackMode = CDDA; bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RAW_READ, &in, sizeof(in), bufdata, buflen, &byteCount,NULL); } // Close(); MEM_BlockWrite(buffer,bufdata,buflen); delete[] bufdata; return (byteCount==buflen) && (bStat>0); } bool CDROM_Interface_Ioctl::SetDevice(char* path, int forceCD) { if (GetDriveType(path)==DRIVE_CDROM) { char letter [3] = { 0, ':', 0 }; letter[0] = path[0]; strcpy(pathname,"\\\\.\\"); strcat(pathname,letter); if (Open()) { // Close(); return true; }; } return false; } bool CDROM_Interface_Ioctl::Open(void) { hIOCTL = CreateFile(pathname, // drive to open GENERIC_READ, // read access FILE_SHARE_READ | // share mode FILE_SHARE_WRITE, NULL, // default security attributes OPEN_EXISTING, // disposition 0, // file attributes NULL); // do not copy file attributes return (hIOCTL!=INVALID_HANDLE_VALUE); }; void CDROM_Interface_Ioctl::Close(void) { CloseHandle(hIOCTL); }; #endif