DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/dos/cdrom.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  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 along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 // ******************************************************
00021 // SDL CDROM 
00022 // ******************************************************
00023 
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <unistd.h>
00027 
00028 #include "dosbox.h"
00029 #include "SDL.h"
00030 #include "support.h"
00031 #include "cdrom.h"
00032 
00033 CDROM_Interface_SDL::CDROM_Interface_SDL(void) {
00034 }
00035 
00036 CDROM_Interface_SDL::~CDROM_Interface_SDL(void) {
00037         CDROM_Interface_SDL::StopAudio();
00038 #if !defined(C_SDL2)
00039         SDL_CDClose(cd);
00040         cd              = 0;
00041 #endif
00042 }
00043 
00044 bool CDROM_Interface_SDL::SetDevice(char* path, int forceCD) { 
00045     (void)forceCD;//UNUSED
00046         char buffer[512];
00047         strcpy(buffer,path);
00048         upcase(buffer);
00049 
00050 #if !defined(C_SDL2)
00051         int num = SDL_CDNumDrives();
00052         if ((forceCD>=0) && (forceCD<num)) {
00053                 driveID = forceCD;
00054                 cd = SDL_CDOpen(driveID);
00055                 SDL_CDStatus(cd);
00056                 return true;
00057         }
00058         
00059         const char* cdname = 0;
00060         for (int i=0; i<num; i++) {
00061                 cdname = SDL_CDName(i);
00062                 if (strcmp(buffer,cdname)==0) {
00063                         cd = SDL_CDOpen(i);
00064                         SDL_CDStatus(cd);
00065                         driveID = i;
00066                         return true;
00067                 }
00068         }
00069 #endif
00070 
00071         return false; 
00072 }
00073 
00074 bool CDROM_Interface_SDL::ReadSectorsHost(void *buffer, bool raw, unsigned long sector, unsigned long num)
00075 {
00076     (void)sector;//UNUSED
00077     (void)buffer;//UNUSED
00078     (void)raw;//UNUSED
00079     (void)num;//UNUSED
00080         return false;/*TODO*/
00081 }
00082 
00083 bool CDROM_Interface_SDL::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut) {
00084     (void)leadOut;//POSSIBLY UNUSED
00085     (void)stTrack;//POSSIBLY UNUSED
00086     (void)end;//POSSIBLY UNUSED
00087 #if !defined(C_SDL2)
00088         if (CD_INDRIVE(SDL_CDStatus(cd))) {
00089                 stTrack         = 1;
00090                 end                     = cd->numtracks;
00091                 FRAMES_TO_MSF(cd->track[cd->numtracks].offset,&leadOut.min,&leadOut.sec,&leadOut.fr);
00092         }
00093         return CD_INDRIVE(SDL_CDStatus(cd));
00094 #else
00095     return false;
00096 #endif
00097 }
00098 
00099 bool CDROM_Interface_SDL::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) {
00100     (void)track;//POSSIBLY UNUSED
00101     (void)start;//POSSIBLY UNUSED
00102     (void)attr;//POSSIBLY UNUSED
00103 #if !defined(C_SDL2)
00104         if (CD_INDRIVE(SDL_CDStatus(cd))) {
00105                 FRAMES_TO_MSF(cd->track[track-1].offset,&start.min,&start.sec,&start.fr);
00106                 attr    = cd->track[track-1].type<<4;//sdl uses 0 for audio and 4 for data. instead of 0x00 and 0x40
00107         }
00108         return CD_INDRIVE(SDL_CDStatus(cd));    
00109 #else
00110     return false;
00111 #endif
00112 }
00113 
00114 bool CDROM_Interface_SDL::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) {
00115     (void)absPos;//POSSIBLY UNUSED
00116     (void)relPos;//POSSIBLY UNUSED
00117     (void)index;//POSSIBLY UNUSED
00118     (void)track;//POSSIBLY UNUSED
00119     (void)attr;//POSSIBLY UNUSED
00120 #if !defined(C_SDL2)
00121         if (CD_INDRIVE(SDL_CDStatus(cd))) {
00122                 track   = cd->cur_track;
00123                 index   = cd->cur_track;
00124                 attr    = cd->track[track].type<<4;
00125                 FRAMES_TO_MSF((unsigned int)cd->cur_frame,&relPos.min,&relPos.sec,&relPos.fr);
00126                 FRAMES_TO_MSF((unsigned int)cd->cur_frame+cd->track[track].offset,&absPos.min,&absPos.sec,&absPos.fr);
00127         }
00128         return CD_INDRIVE(SDL_CDStatus(cd));            
00129 #else
00130     return false;
00131 #endif
00132 }
00133 
00134 bool CDROM_Interface_SDL::GetAudioStatus(bool& playing, bool& pause){
00135     (void)playing;//POSSIBLY UNUSED
00136     (void)pause;//POSSIBLY UNUSED
00137 #if !defined(C_SDL2)
00138         if (CD_INDRIVE(SDL_CDStatus(cd))) {
00139                 playing = (cd->status==CD_PLAYING);
00140                 pause   = (cd->status==CD_PAUSED);
00141         }
00142         return CD_INDRIVE(SDL_CDStatus(cd));
00143 #else
00144     return false;
00145 #endif
00146 }
00147         
00148 bool CDROM_Interface_SDL::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) {
00149     (void)mediaPresent;//POSSIBLY UNUSED
00150     (void)mediaChanged;//POSSIBLY UNUSED
00151     (void)trayOpen;//POSSIBLY UNUSED
00152 #if !defined(C_SDL2)
00153         SDL_CDStatus(cd);
00154         mediaPresent = (cd->status!=CD_TRAYEMPTY) && (cd->status!=CD_ERROR);
00155         mediaChanged = (oldLeadOut!=cd->track[cd->numtracks].offset);
00156         trayOpen         = !mediaPresent;
00157         oldLeadOut       = cd->track[cd->numtracks].offset;
00158         if (mediaChanged) SDL_CDStatus(cd);
00159         return true;
00160 #else
00161     return false;
00162 #endif
00163 }
00164 
00165 bool CDROM_Interface_SDL::PlayAudioSector(unsigned long start,unsigned long len) { 
00166     (void)start;//POSSIBLY UNUSED
00167     (void)len;//POSSIBLY UNUSED
00168 #if !defined(C_SDL2)
00169         // Has to be there, otherwise wrong cd status report (dunno why, sdl bug ?)
00170         SDL_CDClose(cd);
00171         cd = SDL_CDOpen(driveID);
00172         bool success = (SDL_CDPlay(cd,int(start+150u),int(len))==0);
00173         return success;
00174 #else
00175     return false;
00176 #endif
00177 }
00178 
00179 bool CDROM_Interface_SDL::PauseAudio(bool resume) { 
00180     (void)resume;//POSSIBLY UNUSED
00181 #if !defined(C_SDL2)
00182         bool success;
00183         if (resume) success = (SDL_CDResume(cd)==0);
00184         else            success = (SDL_CDPause (cd)==0);
00185         return success;
00186 #else
00187     return false;
00188 #endif
00189 }
00190 
00191 bool CDROM_Interface_SDL::StopAudio(void) {
00192 #if !defined(C_SDL2)
00193         // Has to be there, otherwise wrong cd status report (dunno why, sdl bug ?)
00194         SDL_CDClose(cd);
00195         cd = SDL_CDOpen(driveID);
00196         bool success = (SDL_CDStop(cd)==0);
00197         return success;
00198 #else
00199     return false;
00200 #endif
00201 }
00202 
00203 bool CDROM_Interface_SDL::LoadUnloadMedia(bool unload) {
00204     (void)unload;//UNUSED
00205 #if !defined(C_SDL2)
00206         bool success = (SDL_CDEject(cd)==0);
00207         return success;
00208 #else
00209     return false;
00210 #endif
00211 }
00212 
00213 int CDROM_GetMountType(const char* path, int forceCD) {
00214     (void)forceCD;
00215 // 0 - physical CDROM
00216 // 1 - Iso file
00217 // 2 - subdirectory
00218         // 1. Smells like a real cdrom 
00219         // if ((strlen(path)<=3) && (path[2]=='\\') && (strchr(path,'\\')==strrchr(path,'\\')) &&       (GetDriveType(path)==DRIVE_CDROM)) return 0;
00220 
00221         char buffer[512];
00222         strcpy(buffer,path);
00223 #if defined (WIN32) || defined(OS2)
00224         upcase(buffer);
00225 #endif
00226 
00227 #if !defined(C_SDL2)
00228         const char* cdName;
00229         int num = SDL_CDNumDrives();
00230         // If cd drive is forced then check if its in range and return 0
00231         if ((forceCD>=0) && (forceCD<num)) {
00232                 LOG(LOG_ALL,LOG_ERROR)("CDROM: Using drive %d",forceCD);
00233                 return 0;
00234         }
00235 
00236         // compare names
00237         for (int i=0; i<num; i++) {
00238                 cdName = SDL_CDName(i);
00239                 if (strcmp(buffer,cdName)==0) return 0;
00240         }
00241 #endif
00242         
00243         // Detect ISO
00244         struct stat file_stat;
00245         if ((stat(path, &file_stat) == 0) && (file_stat.st_mode & S_IFREG)) return 1; 
00246         return 2;
00247 }
00248 
00249 // ******************************************************
00250 // Fake CDROM
00251 // ******************************************************
00252 
00253 bool CDROM_Interface_Fake :: GetAudioTracks(int& stTrack, int& end, TMSF& leadOut) {
00254         stTrack = end = 1;
00255         leadOut.min     = 60;
00256         leadOut.sec = leadOut.fr = 0;
00257         return true;
00258 }
00259 
00260 bool CDROM_Interface_Fake :: GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) {
00261         if (track>1) return false;
00262         start.min = start.fr = 0;
00263         start.sec = 2;
00264         attr      = 0x60; // data / permitted
00265         return true;
00266 }
00267 
00268 bool CDROM_Interface_Fake :: GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos){
00269         attr    = 0;
00270         track   = index = 1;
00271         relPos.min = relPos.fr = 0; relPos.sec = 2;
00272         absPos.min = absPos.fr = 0; absPos.sec = 2;
00273         return true;
00274 }
00275 
00276 bool CDROM_Interface_Fake :: GetAudioStatus(bool& playing, bool& pause) {
00277         playing = pause = false;
00278         return true;
00279 }
00280 
00281 bool CDROM_Interface_Fake :: GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) {
00282         mediaPresent = true;
00283         mediaChanged = false;
00284         trayOpen     = false;
00285         return true;
00286 }
00287 
00288 bool CDROM_Interface_Fake::ReadSectorsHost(void *buffer, bool raw, unsigned long sector, unsigned long num)
00289 {
00290     (void)buffer;//UNUSED
00291     (void)sector;//UNUSED
00292     (void)raw;//UNUSED
00293     (void)num;//UNUSED
00294         return false;/*TODO*/
00295 }
00296 
00297