DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/dos/cdrom.h
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #ifndef __CDROM_INTERFACE__
00021 #define __CDROM_INTERFACE__
00022 
00023 #define MAX_ASPI_CDROM  5
00024 
00025 #include <string.h>
00026 #include <string>
00027 #include <iostream>
00028 #include <vector>
00029 #include <fstream>
00030 #include <sstream>
00031 #include "dosbox.h"
00032 #include "mem.h"
00033 #include "mixer.h"
00034 #include "SDL.h"
00035 #include "SDL_thread.h"
00036 
00037 #if defined(C_SDL2) /* SDL 1.x defines this, SDL 2.x does not */
00038 
00042 #define CD_FPS  75
00043 #define FRAMES_TO_MSF(f, M,S,F) {                                       \
00044         int value = f;                                                  \
00045         *(F) = value%CD_FPS;                                            \
00046         value /= CD_FPS;                                                \
00047         *(S) = value%60;                                                \
00048         value /= 60;                                                    \
00049         *(M) = value;                                                   \
00050 }
00051 #define MSF_TO_FRAMES(M, S, F)  ((M)*60*CD_FPS+(S)*CD_FPS+(F))
00052 #endif /* C_SDL2 */
00053 
00054 #define RAW_SECTOR_SIZE         2352
00055 #define COOKED_SECTOR_SIZE      2048
00056 
00057 enum { CDROM_USE_SDL, CDROM_USE_ASPI, CDROM_USE_IOCTL_DIO, CDROM_USE_IOCTL_DX, CDROM_USE_IOCTL_MCI };
00058 
00062 typedef struct SMSF {
00064     unsigned char   min;
00066     unsigned char   sec;
00068     unsigned char   fr;
00069 } TMSF;
00070 
00072 typedef struct SCtrl {
00074     Bit8u           out[4];
00076     Bit8u           vol[4];
00077 } TCtrl;
00078 
00079 extern int CDROM_GetMountType(char* path, int force);
00080 
00084 class CDROM_Interface
00085 {
00086 public:
00087 //      CDROM_Interface                                         (void);
00088         virtual ~CDROM_Interface                        (void) {};
00089 
00091         virtual bool    SetDevice                       (char* path, int forceCD) = 0;
00092 
00094         virtual bool    GetUPC                          (unsigned char& attr, char* upc) = 0;
00095 
00097         virtual bool    GetAudioTracks          (int& stTrack, int& end, TMSF& leadOut) = 0;
00098 
00100         virtual bool    GetAudioTrackInfo       (int track, TMSF& start, unsigned char& attr) = 0;
00101 
00103         virtual bool    GetAudioSub                     (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) = 0;
00104 
00106         virtual bool    GetAudioStatus          (bool& playing, bool& pause) = 0;
00107 
00109         virtual bool    GetMediaTrayStatus      (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) = 0;
00110 
00112         virtual bool    PlayAudioSector         (unsigned long start,unsigned long len) = 0;
00113 
00115         virtual bool    PauseAudio                      (bool resume) = 0;
00116 
00118         virtual bool    StopAudio                       (void) = 0;
00119 
00121         virtual void    ChannelControl          (TCtrl ctrl) = 0;
00122 
00124         virtual bool    ReadSectors                     (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0;
00125 
00127         virtual bool    ReadSectorsHost                 (void* buffer, bool raw, unsigned long sector, unsigned long num) = 0;
00128 
00130         virtual bool    LoadUnloadMedia         (bool unload) = 0;
00131 
00133         virtual void    InitNewMedia            (void) {};
00134 };      
00135 
00139 class CDROM_Interface_SDL : public CDROM_Interface
00140 {
00141 public:
00142         CDROM_Interface_SDL                     (void);
00143         virtual ~CDROM_Interface_SDL(void);
00144 
00145     /* base C++ class overrides, no documentation needed */
00146         virtual bool    SetDevice                       (char* path, int forceCD);
00147         virtual bool    GetUPC                          (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; };
00148         virtual bool    GetAudioTracks          (int& stTrack, int& end, TMSF& leadOut);
00149         virtual bool    GetAudioTrackInfo       (int track, TMSF& start, unsigned char& attr);
00150         virtual bool    GetAudioSub                     (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
00151         virtual bool    GetAudioStatus          (bool& playing, bool& pause);
00152         virtual bool    GetMediaTrayStatus      (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
00153         virtual bool    PlayAudioSector         (unsigned long start,unsigned long len);
00154         virtual bool    PauseAudio                      (bool resume);
00155         virtual bool    StopAudio                       (void);
00156         virtual void    ChannelControl          (TCtrl ctrl) { (void)ctrl; return; };
00157         virtual bool    ReadSectors                     (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return false; };
00158         /* This is needed for IDE hack, who's buffer does not exist in DOS physical memory */
00159         virtual bool    ReadSectorsHost                 (void* buffer, bool raw, unsigned long sector, unsigned long num);
00160         virtual bool    LoadUnloadMedia         (bool unload);
00161 
00162 private:
00164         bool    Open                            (void);
00165 
00167         void    Close                           (void);
00168 
00169 #if !defined(C_SDL2)
00170 
00171         SDL_CD* cd;
00172 #endif
00173         int             driveID;
00174         Uint32  oldLeadOut;
00175 };
00176 
00180 class CDROM_Interface_Fake : public CDROM_Interface
00181 {
00182 public:
00183         bool    SetDevice                       (char* /*path*/, int /*forceCD*/) { return true; };
00184         bool    GetUPC                          (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; };
00185         bool    GetAudioTracks          (int& stTrack, int& end, TMSF& leadOut);
00186         bool    GetAudioTrackInfo       (int track, TMSF& start, unsigned char& attr);
00187         bool    GetAudioSub                     (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
00188         bool    GetAudioStatus          (bool& playing, bool& pause);
00189         bool    GetMediaTrayStatus      (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
00190         bool    PlayAudioSector         (unsigned long /*start*/,unsigned long /*len*/) { return true; };
00191         bool    PauseAudio                      (bool /*resume*/) { return true; };
00192         bool    StopAudio                       (void) { return true; };
00193         void    ChannelControl          (TCtrl ctrl) { (void)ctrl; return; };
00194         bool    ReadSectors                     (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return true; };
00195         /* This is needed for IDE hack, who's buffer does not exist in DOS physical memory */
00196         bool    ReadSectorsHost                 (void* buffer, bool raw, unsigned long sector, unsigned long num);
00197 
00198         bool    LoadUnloadMedia         (bool /*unload*/) { return true; };
00199 };      
00200 
00204 class CDROM_Interface_Image : public CDROM_Interface
00205 {
00206 private:
00208         class TrackFile {
00209         public:
00210                 virtual bool read(Bit8u *buffer, int seek, int count) = 0;
00211                 virtual int getLength() = 0;
00212                 virtual ~TrackFile() { };
00213         };
00214 
00216         class BinaryFile : public TrackFile {
00217         public:
00218                 BinaryFile(const char *filename, bool &error);
00219                 ~BinaryFile();
00220                 bool read(Bit8u *buffer, int seek, int count);
00221                 int getLength();
00222         private:
00223                 BinaryFile();
00224                 std::ifstream *file;
00225         };
00226 
00228         struct Track {
00229                 int number;
00230                 int attr;
00231                 int start;
00232                 int length;
00233                 int skip;
00234                 int sectorSize;
00235                 bool mode2;
00236                 TrackFile *file;
00237         };
00238         
00239 public:
00241         CDROM_Interface_Image           (Bit8u subUnit);
00242         virtual ~CDROM_Interface_Image  (void);
00243 
00244         void    InitNewMedia            (void);
00245         bool    SetDevice               (char* path, int forceCD);
00246         bool    GetUPC                  (unsigned char& attr, char* upc);
00247         bool    GetAudioTracks          (int& stTrack, int& end, TMSF& leadOut);
00248         bool    GetAudioTrackInfo       (int track, TMSF& start, unsigned char& attr);
00249         bool    GetAudioSub             (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
00250         bool    GetAudioStatus          (bool& playing, bool& pause);
00251         bool    GetMediaTrayStatus      (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
00252         bool    PlayAudioSector         (unsigned long start,unsigned long len);
00253         bool    PauseAudio              (bool resume);
00254         bool    StopAudio               (void);
00255         void    ChannelControl          (TCtrl ctrl);
00256         bool    ReadSectors             (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
00257         /* This is needed for IDE hack, who's buffer does not exist in DOS physical memory */
00258         bool    ReadSectorsHost                 (void* buffer, bool raw, unsigned long sector, unsigned long num);
00259         bool    LoadUnloadMedia         (bool unload);
00260 
00262         bool    ReadSector              (Bit8u *buffer, bool raw, unsigned long sector);
00263 
00265         bool    HasDataTrack            (void);
00266 
00272 static bool images_init;
00276 static  CDROM_Interface_Image* images[26];
00277 
00278 private:
00279         // player
00280 static  void    CDAudioCallBack(Bitu len);
00281         int     GetTrack(int sector);
00282 
00287 static  struct imagePlayer {
00288                 CDROM_Interface_Image *cd;
00289                 MixerChannel   *channel;
00290                 SDL_mutex       *mutex;
00291                 Bit8u   buffer[8192];
00292                 int     bufLen;
00293                 int     currFrame;      
00294                 int     targetFrame;
00295                 bool    isPlaying;
00296                 bool    isPaused;
00297                 bool    ctrlUsed;
00298                 TCtrl   ctrlData;
00299         } player;
00300         
00301         void    ClearTracks();
00302         bool    LoadIsoFile(char *filename);
00303         bool    CanReadPVD(TrackFile *file, int sectorSize, bool mode2);
00304         // cue sheet processing
00305         bool    LoadCueSheet(char *cuefile);
00306         bool    GetRealFileName(std::string& filename, std::string& pathname);
00307         bool    GetCueKeyword(std::string &keyword, std::istream &in);
00308         bool    GetCueFrame(int &frames, std::istream &in);
00309         bool    GetCueString(std::string &str, std::istream &in);
00310         bool    AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap);
00311 
00312 static  int     refCount;
00313         std::vector<Track>      tracks;
00314 typedef std::vector<Track>::iterator    track_it;
00315         std::string     mcn;
00316         Bit8u   subUnit;
00317 };
00318 
00319 #if defined (WIN32)     /* Win 32 */
00320 
00321 #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
00322 
00323 #include <windows.h>
00324 #include "wnaspi32.h"                   // Aspi stuff 
00325 
00326 class CDROM_Interface_Aspi : public CDROM_Interface
00327 {
00328 public:
00329         CDROM_Interface_Aspi            (void);
00330         virtual ~CDROM_Interface_Aspi(void);
00331 
00332         bool    SetDevice                       (char* path, int forceCD);
00333 
00334         bool    GetUPC                          (unsigned char& attr, char* upc);
00335 
00336         bool    GetAudioTracks          (int& stTrack, int& end, TMSF& leadOut);
00337         bool    GetAudioTrackInfo       (int track, TMSF& start, unsigned char& attr);
00338         bool    GetAudioSub                     (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
00339         bool    GetAudioStatus          (bool& playing, bool& pause);
00340         bool    GetMediaTrayStatus      (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
00341 
00342         bool    PlayAudioSector         (unsigned long start,unsigned long len);
00343         bool    PauseAudio                      (bool resume);
00344         bool    StopAudio                       (void);
00345         void    ChannelControl          (TCtrl ctrl) { (void)ctrl; return; };
00346         
00347         bool    ReadSectors                     (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
00348         /* This is needed for IDE hack, who's buffer does not exist in DOS physical memory */
00349         bool    ReadSectorsHost                 (void* buffer, bool raw, unsigned long sector, unsigned long num);
00350         
00351         bool    LoadUnloadMedia         (bool unload);
00352         
00353 private:
00354         DWORD   GetTOC                          (LPTOC toc);
00355         HANDLE  OpenIOCTLFile           (char cLetter, BOOL bAsync);
00356         void    GetIOCTLAdapter         (HANDLE hF,int * iDA,int * iDT,int * iDL);
00357         bool    ScanRegistryFindKey     (HKEY& hKeyBase);
00358         bool    ScanRegistry            (HKEY& hKeyBase);
00359         BYTE    GetHostAdapter          (char* hardwareID);
00360         bool    GetVendor                       (BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, char* szBuffer);
00361                 
00362         // ASPI stuff
00363         BYTE    haId;
00364         BYTE    target;
00365         BYTE    lun;
00366         char    letter;
00367 
00368         // Windows stuff
00369         HINSTANCE       hASPI;
00370         HANDLE          hEvent;                                                                                 // global event
00371         DWORD           (*pGetASPI32SupportInfo)        (void);             // ptrs to aspi funcs
00372         DWORD           (*pSendASPI32Command)           (LPSRB);
00373         TMSF            oldLeadOut;
00374 };
00375 
00376 class CDROM_Interface_Ioctl : public CDROM_Interface
00377 {
00378 public:
00379         enum cdioctl_cdatype { CDIOCTL_CDA_DIO, CDIOCTL_CDA_MCI, CDIOCTL_CDA_DX };
00380         cdioctl_cdatype cdioctl_cda_selected;
00381 
00382         CDROM_Interface_Ioctl           (cdioctl_cdatype ioctl_cda);
00383         virtual ~CDROM_Interface_Ioctl(void);
00384 
00385         bool    SetDevice                       (char* path, int forceCD);
00386 
00387         bool    GetUPC                          (unsigned char& attr, char* upc);
00388 
00389         bool    GetAudioTracks          (int& stTrack, int& end, TMSF& leadOut);
00390         bool    GetAudioTrackInfo       (int track, TMSF& start, unsigned char& attr);
00391         bool    GetAudioSub                     (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
00392         bool    GetAudioStatus          (bool& playing, bool& pause);
00393         bool    GetMediaTrayStatus      (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
00394 
00395         bool    PlayAudioSector         (unsigned long start,unsigned long len);
00396         bool    PauseAudio                      (bool resume);
00397         bool    StopAudio                       (void);
00398         void    ChannelControl          (TCtrl ctrl);
00399         
00400         bool    ReadSector                      (Bit8u *buffer, bool raw, unsigned long sector);
00401         bool    ReadSectors                     (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
00402         /* This is needed for IDE hack, who's buffer does not exist in DOS physical memory */
00403         bool    ReadSectorsHost                 (void* buffer, bool raw, unsigned long sector, unsigned long num);
00404         
00405         bool    LoadUnloadMedia         (bool unload);
00406 
00407         void    InitNewMedia            (void) { Close(); Open(); };
00408 private:
00409 
00410         bool    Open                            (void);
00411         void    Close                           (void);
00412 
00413         char    pathname[32];
00414         HANDLE  hIOCTL;
00415         TMSF    oldLeadOut;
00416 
00417 
00418         /* track start/length data */
00419         bool    track_start_valid;
00420         int             track_start_first,track_start_last;
00421         int             track_start[128];
00422 
00423         bool    GetAudioTracksAll       (void);
00424 
00425 
00426         /* mci audio cd interface */
00427         bool    use_mciplay;
00428         int             mci_devid;
00429 
00430         bool    mci_CDioctl                             (UINT msg, DWORD flags, void *arg);
00431         bool    mci_CDOpen                              (char drive);
00432         bool    mci_CDClose                             (void);
00433         bool    mci_CDPlay                              (int start, int length);
00434         bool    mci_CDPause                             (void);
00435         bool    mci_CDResume                    (void);
00436         bool    mci_CDStop                              (void);
00437         int             mci_CDStatus                    (void);
00438         bool    mci_CDPosition                  (int *position);
00439 
00440 
00441         /* digital audio extraction cd interface */
00442         static void dx_CDAudioCallBack(Bitu len);
00443 
00444         bool    use_dxplay;
00445         static  struct dxPlayer {
00446                 CDROM_Interface_Ioctl *cd;
00447                 MixerChannel    *channel;
00448                 SDL_mutex               *mutex;
00449                 Bit8u   buffer[8192];
00450                 int     bufLen;
00451                 int     currFrame;      
00452                 int     targetFrame;
00453                 bool    isPlaying;
00454                 bool    isPaused;
00455                 bool    ctrlUsed;
00456                 TCtrl   ctrlData;
00457         } player;
00458 
00459 };
00460 
00461 #endif /* WIN 32 */
00462 
00463 #if defined (LINUX) || defined(OS2)
00464 
00465 class CDROM_Interface_Ioctl : public CDROM_Interface_SDL
00466 {
00467 public:
00468         CDROM_Interface_Ioctl           (void);
00469 
00470         bool    SetDevice               (char* path, int forceCD);
00471         bool    GetUPC                  (unsigned char& attr, char* upc);
00472         bool    ReadSectors             (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
00473         /* This is needed for IDE hack, who's buffer does not exist in DOS physical memory */
00474         bool    ReadSectorsHost                 (void* buffer, bool raw, unsigned long sector, unsigned long num);
00475 
00476 private:
00477         char    device_name[512];
00478 };
00479 
00480 #endif /* LINUX */
00481 
00482 #endif /* __CDROM_INTERFACE__ */