DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/dos/drives.cpp
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 #include "dosbox.h"
00021 #include "dos_system.h"
00022 #include "drives.h"
00023 #include "setup.h"
00024 #include "mapper.h"
00025 #include "support.h"
00026 #include "control.h"
00027 
00028 bool WildFileCmp(const char * file, const char * wild) 
00029 {
00030         char file_name[9];
00031         char file_ext[4];
00032         char wild_name[9];
00033         char wild_ext[4];
00034         const char * find_ext;
00035         Bitu r;
00036 
00037         strcpy(file_name,"        ");
00038         strcpy(file_ext,"   ");
00039         strcpy(wild_name,"        ");
00040         strcpy(wild_ext,"   ");
00041 
00042         find_ext=strrchr(file,'.');
00043         if (find_ext) {
00044                 Bitu size=(Bitu)(find_ext-file);
00045                 if (size>8) size=8;
00046                 memcpy(file_name,file,size);
00047                 find_ext++;
00048                 memcpy(file_ext,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext)); 
00049         } else {
00050                 memcpy(file_name,file,(strlen(file) > 8) ? 8 : strlen(file));
00051         }
00052         upcase(file_name);upcase(file_ext);
00053         find_ext=strrchr(wild,'.');
00054         if (find_ext) {
00055                 Bitu size=(Bitu)(find_ext-wild);
00056                 if (size>8) size=8;
00057                 memcpy(wild_name,wild,size);
00058                 find_ext++;
00059                 memcpy(wild_ext,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext));
00060         } else {
00061                 memcpy(wild_name,wild,(strlen(wild) > 8) ? 8 : strlen(wild));
00062         }
00063         upcase(wild_name);upcase(wild_ext);
00064         /* Names are right do some checking */
00065         r=0;
00066         while (r<8) {
00067                 if (wild_name[r]=='*') goto checkext;
00068                 if (wild_name[r]!='?' && wild_name[r]!=file_name[r]) return false;
00069                 r++;
00070         }
00071 checkext:
00072     r=0;
00073         while (r<3) {
00074                 if (wild_ext[r]=='*') return true;
00075                 if (wild_ext[r]!='?' && wild_ext[r]!=file_ext[r]) return false;
00076                 r++;
00077         }
00078         return true;
00079 }
00080 
00081 void Set_Label(char const * const input, char * const output, bool cdrom) {
00082         Bitu togo     = 8;
00083         Bitu vnamePos = 0;
00084         Bitu labelPos = 0;
00085         bool point    = false;
00086 
00087         //spacepadding the filenamepart to include spaces after the terminating zero is more closely to the specs. (not doing this now)
00088         // HELLO\0' '' '
00089 
00090         while (togo > 0) {
00091                 if (input[vnamePos]==0) break;
00092                 if (!point && (input[vnamePos]=='.')) { togo=4; point=true; }
00093 
00094                 //another mscdex quirk. Label is not always uppercase. (Daggerfall)
00095                 output[labelPos] = (cdrom?input[vnamePos]:toupper(input[vnamePos]));
00096 
00097                 labelPos++; vnamePos++;
00098                 togo--;
00099                 if ((togo==0) && !point) {
00100                         if (input[vnamePos]=='.') vnamePos++;
00101                         output[labelPos]='.'; labelPos++; point=true; togo=3;
00102                 }
00103         };
00104         output[labelPos]=0;
00105 
00106         //Remove trailing dot. except when on cdrom and filename is exactly 8 (9 including the dot) letters. MSCDEX feature/bug (fifa96 cdrom detection)
00107         if((labelPos > 0) && (output[labelPos-1] == '.') && !(cdrom && labelPos ==9))
00108                 output[labelPos-1] = 0;
00109 }
00110 
00111 
00112 
00113 DOS_Drive::DOS_Drive() {
00114     nocachedir=false;
00115     readonly=false;
00116         curdir[0]=0;
00117         info[0]=0;
00118 }
00119 
00120 const char * DOS_Drive::GetInfo(void) {
00121         return info;
00122 }
00123 
00124 // static members variables
00125 int DriveManager::currentDrive;
00126 DriveManager::DriveInfo DriveManager::driveInfos[26];
00127 
00128 void DriveManager::AppendDisk(int drive, DOS_Drive* disk) {
00129         driveInfos[drive].disks.push_back(disk);
00130 }
00131 
00132 void DriveManager::InitializeDrive(int drive) {
00133         currentDrive = drive;
00134         DriveInfo& driveInfo = driveInfos[currentDrive];
00135         if (driveInfo.disks.size() > 0) {
00136                 driveInfo.currentDisk = 0;
00137                 DOS_Drive* disk = driveInfo.disks[driveInfo.currentDisk];
00138                 Drives[currentDrive] = disk;
00139                 disk->Activate();
00140         }
00141 }
00142 
00143 /*
00144 void DriveManager::CycleDrive(bool pressed) {
00145         if (!pressed) return;
00146                 
00147         // do one round through all drives or stop at the next drive with multiple disks
00148         int oldDrive = currentDrive;
00149         do {
00150                 currentDrive = (currentDrive + 1) % DOS_DRIVES;
00151                 int numDisks = driveInfos[currentDrive].disks.size();
00152                 if (numDisks > 1) break;
00153         } while (currentDrive != oldDrive);
00154 }
00155 
00156 void DriveManager::CycleDisk(bool pressed) {
00157         if (!pressed) return;
00158         
00159         int numDisks = driveInfos[currentDrive].disks.size();
00160         if (numDisks > 1) {
00161                 // cycle disk
00162                 int currentDisk = driveInfos[currentDrive].currentDisk;
00163                 DOS_Drive* oldDisk = driveInfos[currentDrive].disks[currentDisk];
00164                 currentDisk = (currentDisk + 1) % numDisks;             
00165                 DOS_Drive* newDisk = driveInfos[currentDrive].disks[currentDisk];
00166                 driveInfos[currentDrive].currentDisk = currentDisk;
00167                 
00168                 // copy working directory, acquire system resources and finally switch to next drive            
00169                 strcpy(newDisk->curdir, oldDisk->curdir);
00170                 newDisk->Activate();
00171                 Drives[currentDrive] = newDisk;
00172         }
00173 }
00174 */
00175 
00176 void DriveManager::CycleAllDisks(void) {
00177         for (unsigned int idrive=0; idrive<2; idrive++) { /* Cycle all DISKS meaning A: and B: */
00178                 unsigned int numDisks = (unsigned int)driveInfos[idrive].disks.size();
00179                 if (numDisks > 1) {
00180                         // cycle disk
00181                         unsigned int currentDisk = (unsigned int)driveInfos[idrive].currentDisk;
00182                         DOS_Drive* oldDisk = driveInfos[idrive].disks[(unsigned int)currentDisk];
00183                         currentDisk = ((unsigned int)currentDisk + 1u) % (unsigned int)numDisks;                
00184                         DOS_Drive* newDisk = driveInfos[idrive].disks[(unsigned int)currentDisk];
00185                         driveInfos[idrive].currentDisk = currentDisk;
00186                         
00187                         // copy working directory, acquire system resources and finally switch to next drive            
00188                         strcpy(newDisk->curdir, oldDisk->curdir);
00189                         newDisk->Activate();
00190                         Drives[idrive] = newDisk;
00191                         LOG_MSG("Drive %c: disk %d of %d now active", 'A'+idrive, currentDisk+1, numDisks);
00192                 }
00193         }
00194 }
00195 
00196 void DriveManager::CycleAllCDs(void) {
00197         for (unsigned int idrive=2; idrive<DOS_DRIVES; idrive++) { /* Cycle all CDs in C: D: ... Z: */
00198                 unsigned int numDisks = (unsigned int)driveInfos[idrive].disks.size();
00199                 if (numDisks > 1) {
00200                         // cycle disk
00201                         unsigned int currentDisk = driveInfos[idrive].currentDisk;
00202                         DOS_Drive* oldDisk = driveInfos[idrive].disks[currentDisk];
00203                         currentDisk = ((unsigned int)currentDisk + 1u) % (unsigned int)numDisks;                
00204                         DOS_Drive* newDisk = driveInfos[idrive].disks[currentDisk];
00205                         driveInfos[idrive].currentDisk = currentDisk;
00206                         
00207                         // copy working directory, acquire system resources and finally switch to next drive            
00208                         strcpy(newDisk->curdir, oldDisk->curdir);
00209                         newDisk->Activate();
00210                         Drives[idrive] = newDisk;
00211                         LOG_MSG("Drive %c: disk %d of %d now active", 'A'+idrive, currentDisk+1, numDisks);
00212                 }
00213         }
00214 }
00215 
00216 int DriveManager::UnmountDrive(int drive) {
00217         int result = 0;
00218         // unmanaged drive
00219         if (driveInfos[drive].disks.size() == 0) {
00220                 result = Drives[drive]->UnMount();
00221         } else {
00222                 // managed drive
00223                 unsigned int currentDisk = driveInfos[drive].currentDisk;
00224                 result = driveInfos[drive].disks[currentDisk]->UnMount();
00225                 // only delete on success, current disk set to NULL because of UnMount
00226                 if (result == 0) {
00227                         driveInfos[drive].disks[currentDisk] = NULL;
00228                         for (unsigned int i = 0; i < (unsigned int)driveInfos[drive].disks.size(); i++) {
00229                                 delete driveInfos[drive].disks[i];
00230                         }
00231                         driveInfos[drive].disks.clear();
00232                 }
00233         }
00234         
00235         return result;
00236 }
00237 
00238 bool drivemanager_init = false;
00239 bool int13_extensions_enable = true;
00240 
00241 void DriveManager::Init(Section* s) {
00242         Section_prop * section=static_cast<Section_prop *>(s);
00243 
00244         drivemanager_init = true;
00245 
00246         int13_extensions_enable = section->Get_bool("int 13 extensions");
00247         
00248         // setup driveInfos structure
00249         currentDrive = 0;
00250         for(int i = 0; i < DOS_DRIVES; i++) {
00251                 driveInfos[i].currentDisk = 0;
00252         }
00253         
00254 //      MAPPER_AddHandler(&CycleDisk, MK_f3, MMOD1, "cycledisk", "Cycle Disk");
00255 //      MAPPER_AddHandler(&CycleDrive, MK_f3, MMOD2, "cycledrive", "Cycle Drv");
00256 }
00257 
00258 void DRIVES_Startup(Section *s) {
00259     (void)s;//UNUSED
00260         if (!drivemanager_init) {
00261                 LOG(LOG_MISC,LOG_DEBUG)("Initializing drive system");
00262                 DriveManager::Init(control->GetSection("dos"));
00263         }
00264 }
00265 
00266 void DRIVES_Init() {
00267         LOG(LOG_MISC,LOG_DEBUG)("Initializing OOS drives");
00268 
00269         // TODO: DOS kernel exit, reset, guest booting handler
00270 }
00271 
00272 char * DOS_Drive::GetBaseDir(void) {
00273         return info + 16;
00274 }
00275