DOSBox-X
|
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 #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 wild_match(char *haystack, char *needle) { 00029 size_t max, i; 00030 for (; *needle != '\0'; ++needle) { 00031 switch (*needle) { 00032 case '?': 00033 if (*haystack == '\0') 00034 return false; 00035 ++haystack; 00036 break; 00037 case '*': 00038 if (needle[1] == '\0') 00039 return true; 00040 max = strlen(haystack); 00041 for (i = 0; i < max; i++) 00042 if (wild_match(haystack + i, needle + 1)) 00043 return true; 00044 return false; 00045 default: 00046 if (toupper(*haystack) != *needle) 00047 return false; 00048 ++haystack; 00049 } 00050 } 00051 return *haystack == '\0'; 00052 } 00053 00054 bool WildFileCmp(const char * file, const char * wild) 00055 { 00056 char file_name[9]; 00057 char file_ext[4]; 00058 char wild_name[10]; 00059 char wild_ext[5]; 00060 const char * find_ext; 00061 Bitu r; 00062 00063 for (r=0;r<9;r++) { 00064 file_name[r]=0; 00065 wild_name[r]=0; 00066 } 00067 wild_name[9]=0; 00068 for (r=0;r<4;r++) { 00069 file_ext[r]=0; 00070 wild_ext[r]=0; 00071 } 00072 wild_ext[4]=0; 00073 00074 find_ext=strrchr(file,'.'); 00075 if (find_ext) { 00076 Bitu size=(Bitu)(find_ext-file); 00077 if (size>8) size=8; 00078 memcpy(file_name,file,size); 00079 find_ext++; 00080 memcpy(file_ext,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext)); 00081 } else { 00082 memcpy(file_name,file,(strlen(file) > 8) ? 8 : strlen(file)); 00083 } 00084 upcase(file_name);upcase(file_ext); 00085 find_ext=strrchr(wild,'.'); 00086 if (find_ext) { 00087 Bitu size=(Bitu)(find_ext-wild); 00088 if (size>9) size=9; 00089 memcpy(wild_name,wild,size); 00090 find_ext++; 00091 memcpy(wild_ext,find_ext,(strlen(find_ext)>4) ? 4 : strlen(find_ext)); 00092 } else { 00093 memcpy(wild_name,wild,(strlen(wild) > 9) ? 9 : strlen(wild)); 00094 } 00095 upcase(wild_name);upcase(wild_ext); 00096 /* Names are right do some checking */ 00097 if (uselfn&&strchr(wild_name, '*')) { 00098 if (strchr(wild,'.')) { 00099 if (!wild_match(file_name, wild_name)) return false; 00100 goto checkext; 00101 } else 00102 return wild_match((char *)file, wild_name); 00103 } else { 00104 r=0; 00105 while (r<8) { 00106 if (wild_name[r]=='*') goto checkext; 00107 if (wild_name[r]!='?' && wild_name[r]!=file_name[r]) return false; 00108 r++; 00109 } 00110 if (wild_name[r]&&wild_name[r]!='*') return false; 00111 } 00112 checkext: 00113 if (uselfn&&strchr(wild_ext, '*')) 00114 return wild_match(file_ext, wild_ext); 00115 else { 00116 r=0; 00117 while (r<3) { 00118 if (wild_ext[r]=='*') return true; 00119 if (wild_ext[r]!='?' && wild_ext[r]!=file_ext[r]) return false; 00120 r++; 00121 } 00122 if (wild_ext[r]&&wild_ext[r]!='*') return false; 00123 return true; 00124 } 00125 } 00126 00127 bool LWildFileCmp(const char * file, const char * wild) 00128 { 00129 if (!uselfn||*file == 0) return false; 00130 char file_name[256]; 00131 char file_ext[256]; 00132 char wild_name[256]; 00133 char wild_ext[256]; 00134 const char * find_ext; 00135 Bitu r; 00136 00137 for (r=0;r<256;r++) { 00138 file_name[r]=0; 00139 wild_name[r]=0; 00140 } 00141 for (r=0;r<256;r++) { 00142 file_ext[r]=0; 00143 wild_ext[r]=0; 00144 } 00145 00146 Bitu size,elen; 00147 find_ext=strrchr(file,'.'); 00148 if (find_ext) { 00149 size=(Bitu)(find_ext-file); 00150 if (size>255) size=255; 00151 memcpy(file_name,file,size); 00152 find_ext++; 00153 elen=strlen(find_ext); 00154 memcpy(file_ext,find_ext,(strlen(find_ext)>255) ? 255 : strlen(find_ext)); 00155 } else { 00156 size=strlen(file); 00157 elen=0; 00158 memcpy(file_name,file,(strlen(file) > 255) ? 255 : strlen(file)); 00159 } 00160 upcase(file_name);upcase(file_ext); 00161 char nwild[LFN_NAMELENGTH+2]; 00162 strcpy(nwild,wild); 00163 if (strrchr(nwild,'*')&&strrchr(nwild,'.')==NULL) strcat(nwild,".*"); 00164 find_ext=strrchr(nwild,'.'); 00165 if (find_ext) { 00166 Bitu size=(Bitu)(find_ext-nwild); 00167 if (size>255) size=255; 00168 memcpy(wild_name,nwild,size); 00169 find_ext++; 00170 memcpy(wild_ext,find_ext,(strlen(find_ext)>255) ? 255 : strlen(find_ext)); 00171 } else { 00172 memcpy(wild_name,nwild,(strlen(nwild) > 255) ? 255 : strlen(nwild)); 00173 } 00174 upcase(wild_name);upcase(wild_ext); 00175 /* Names are right do some checking */ 00176 if (strchr(wild_name, '*')) { 00177 if (strchr(wild,'.')) { 00178 if (!wild_match(file_name, wild_name)) return false; 00179 goto checkext; 00180 } else 00181 return wild_match((char *)file, wild_name); 00182 } else { 00183 r=0; 00184 while (r<size) { 00185 if (wild_name[r]=='*') goto checkext; 00186 if (wild_name[r]!='?' && wild_name[r]!=file_name[r]) return false; 00187 r++; 00188 } 00189 if (wild_name[r]&&wild_name[r]!='*') return false; 00190 } 00191 checkext: 00192 if (strchr(wild_ext, '*')) 00193 return wild_match(file_ext, wild_ext); 00194 else { 00195 r=0; 00196 while (r<elen) { 00197 if (wild_ext[r]=='*') return true; 00198 if (wild_ext[r]!='?' && wild_ext[r]!=file_ext[r]) return false; 00199 r++; 00200 } 00201 if (wild_ext[r]&&wild_ext[r]!='*') return false; 00202 return true; 00203 } 00204 } 00205 00206 void Set_Label(char const * const input, char * const output, bool cdrom) { 00207 /* I don't know what MSCDEX.EXE does but don't put dots in the 11-char volume label for non-CD-ROM drives */ 00208 if (!cdrom) { 00209 Bitu togo = 11; 00210 Bitu vnamePos = 0; 00211 Bitu labelPos = 0; 00212 00213 while (togo > 0) { 00214 if (input[vnamePos]==0) break; 00215 //Another mscdex quirk. Label is not always uppercase. (Daggerfall) 00216 output[labelPos] = toupper(input[vnamePos]); 00217 labelPos++; 00218 vnamePos++; 00219 togo--; 00220 } 00221 output[labelPos] = 0; 00222 return; 00223 } 00224 00225 Bitu togo = 8; 00226 Bitu vnamePos = 0; 00227 Bitu labelPos = 0; 00228 bool point = false; 00229 00230 //spacepadding the filenamepart to include spaces after the terminating zero is more closely to the specs. (not doing this now) 00231 // HELLO\0' '' ' 00232 00233 while (togo > 0) { 00234 if (input[vnamePos]==0) break; 00235 if (!point && (input[vnamePos]=='.')) { togo=4; point=true; } 00236 00237 output[labelPos] = input[vnamePos]; 00238 00239 labelPos++; vnamePos++; 00240 togo--; 00241 if ((togo==0) && !point) { 00242 if (input[vnamePos]=='.') vnamePos++; 00243 output[labelPos]='.'; labelPos++; point=true; togo=3; 00244 } 00245 } 00246 output[labelPos]=0; 00247 00248 //Remove trailing dot. except when on cdrom and filename is exactly 8 (9 including the dot) letters. MSCDEX feature/bug (fifa96 cdrom detection) 00249 if((labelPos > 0) && (output[labelPos-1] == '.') && !(cdrom && labelPos ==9)) 00250 output[labelPos-1] = 0; 00251 } 00252 00253 00254 00255 DOS_Drive::DOS_Drive() { 00256 nocachedir=false; 00257 readonly=false; 00258 curdir[0]=0; 00259 info[0]=0; 00260 } 00261 00262 const char * DOS_Drive::GetInfo(void) { 00263 return info; 00264 } 00265 00266 // static members variables 00267 int DriveManager::currentDrive; 00268 DriveManager::DriveInfo DriveManager::driveInfos[26]; 00269 00270 void DriveManager::AppendDisk(int drive, DOS_Drive* disk) { 00271 driveInfos[drive].disks.push_back(disk); 00272 } 00273 00274 void DriveManager::InitializeDrive(int drive) { 00275 currentDrive = drive; 00276 DriveInfo& driveInfo = driveInfos[currentDrive]; 00277 if (driveInfo.disks.size() > 0) { 00278 driveInfo.currentDisk = 0; 00279 DOS_Drive* disk = driveInfo.disks[driveInfo.currentDisk]; 00280 Drives[currentDrive] = disk; 00281 if (driveInfo.disks.size() > 1) disk->Activate(); 00282 disk->UpdateDPB(currentDrive); 00283 } 00284 } 00285 00286 /* 00287 void DriveManager::CycleDrive(bool pressed) { 00288 if (!pressed) return; 00289 00290 // do one round through all drives or stop at the next drive with multiple disks 00291 int oldDrive = currentDrive; 00292 do { 00293 currentDrive = (currentDrive + 1) % DOS_DRIVES; 00294 int numDisks = driveInfos[currentDrive].disks.size(); 00295 if (numDisks > 1) break; 00296 } while (currentDrive != oldDrive); 00297 } 00298 00299 void DriveManager::CycleDisk(bool pressed) { 00300 if (!pressed) return; 00301 00302 int numDisks = driveInfos[currentDrive].disks.size(); 00303 if (numDisks > 1) { 00304 // cycle disk 00305 int currentDisk = driveInfos[currentDrive].currentDisk; 00306 DOS_Drive* oldDisk = driveInfos[currentDrive].disks[currentDisk]; 00307 currentDisk = (currentDisk + 1) % numDisks; 00308 DOS_Drive* newDisk = driveInfos[currentDrive].disks[currentDisk]; 00309 driveInfos[currentDrive].currentDisk = currentDisk; 00310 00311 // copy working directory, acquire system resources and finally switch to next drive 00312 strcpy(newDisk->curdir, oldDisk->curdir); 00313 newDisk->Activate(); 00314 Drives[currentDrive] = newDisk; 00315 } 00316 } 00317 */ 00318 00319 void DriveManager::CycleDisks(int drive, bool notify) { 00320 unsigned int numDisks = (unsigned int)driveInfos[drive].disks.size(); 00321 if (numDisks > 1) { 00322 // cycle disk 00323 unsigned int currentDisk = (unsigned int)driveInfos[drive].currentDisk; 00324 const DOS_Drive* oldDisk = driveInfos[drive].disks[(unsigned int)currentDisk]; 00325 currentDisk = ((unsigned int)currentDisk + 1u) % (unsigned int)numDisks; 00326 DOS_Drive* newDisk = driveInfos[drive].disks[currentDisk]; 00327 driveInfos[drive].currentDisk = currentDisk; 00328 00329 // copy working directory, acquire system resources and finally switch to next drive 00330 strcpy(newDisk->curdir, oldDisk->curdir); 00331 newDisk->Activate(); 00332 newDisk->UpdateDPB(currentDrive); 00333 Drives[drive] = newDisk; 00334 if (notify) LOG_MSG("Drive %c: disk %d of %d now active", 'A'+drive, currentDisk+1, numDisks); 00335 } 00336 } 00337 00338 void DriveManager::CycleAllDisks(void) { 00339 for (int idrive=0; idrive<2; idrive++) CycleDisks(idrive, true); /* Cycle all DISKS meaning A: and B: */ 00340 } 00341 00342 void DriveManager::CycleAllCDs(void) { 00343 for (unsigned int idrive=2; idrive<DOS_DRIVES; idrive++) { /* Cycle all CDs in C: D: ... Z: */ 00344 unsigned int numDisks = (unsigned int)driveInfos[idrive].disks.size(); 00345 if (numDisks > 1) { 00346 // cycle disk 00347 unsigned int currentDisk = driveInfos[idrive].currentDisk; 00348 const DOS_Drive* oldDisk = driveInfos[idrive].disks[currentDisk]; 00349 currentDisk = ((unsigned int)currentDisk + 1u) % (unsigned int)numDisks; 00350 DOS_Drive* newDisk = driveInfos[idrive].disks[currentDisk]; 00351 driveInfos[idrive].currentDisk = currentDisk; 00352 00353 // copy working directory, acquire system resources and finally switch to next drive 00354 strcpy(newDisk->curdir, oldDisk->curdir); 00355 newDisk->Activate(); 00356 newDisk->UpdateDPB(currentDrive); 00357 Drives[idrive] = newDisk; 00358 LOG_MSG("Drive %c: disk %d of %d now active", 'A'+idrive, currentDisk+1, numDisks); 00359 } 00360 } 00361 } 00362 00363 int DriveManager::UnmountDrive(int drive) { 00364 int result = 0; 00365 // unmanaged drive 00366 if (driveInfos[drive].disks.size() == 0) { 00367 result = (int)Drives[drive]->UnMount(); 00368 } else { 00369 // managed drive 00370 unsigned int currentDisk = driveInfos[drive].currentDisk; 00371 result = (int)driveInfos[drive].disks[currentDisk]->UnMount(); 00372 // only delete on success, current disk set to NULL because of UnMount 00373 if (result == 0) { 00374 driveInfos[drive].disks[currentDisk] = NULL; 00375 for (unsigned int i = 0; i < (unsigned int)driveInfos[drive].disks.size(); i++) { 00376 delete driveInfos[drive].disks[i]; 00377 } 00378 driveInfos[drive].disks.clear(); 00379 } 00380 } 00381 00382 return result; 00383 } 00384 00385 bool drivemanager_init = false; 00386 bool int13_extensions_enable = true; 00387 00388 void DriveManager::Init(Section* s) { 00389 const Section_prop* section = static_cast<Section_prop*>(s); 00390 00391 drivemanager_init = true; 00392 00393 int13_extensions_enable = section->Get_bool("int 13 extensions"); 00394 00395 // setup driveInfos structure 00396 currentDrive = 0; 00397 for(int i = 0; i < DOS_DRIVES; i++) { 00398 driveInfos[i].currentDisk = 0; 00399 } 00400 00401 // MAPPER_AddHandler(&CycleDisk, MK_f3, MMOD1, "cycledisk", "Cycle Disk"); 00402 // MAPPER_AddHandler(&CycleDrive, MK_f3, MMOD2, "cycledrive", "Cycle Drv"); 00403 } 00404 00405 void DRIVES_Startup(Section *s) { 00406 (void)s;//UNUSED 00407 if (!drivemanager_init) { 00408 LOG(LOG_MISC,LOG_DEBUG)("Initializing drive system"); 00409 DriveManager::Init(control->GetSection("dos")); 00410 } 00411 } 00412 00413 void DRIVES_Init() { 00414 LOG(LOG_MISC,LOG_DEBUG)("Initializing OOS drives"); 00415 00416 // TODO: DOS kernel exit, reset, guest booting handler 00417 } 00418 00419 char * DOS_Drive::GetBaseDir(void) { 00420 return info + 16; 00421 } 00422 00423 // save state support 00424 void DOS_Drive::SaveState( std::ostream& stream ) 00425 { 00426 // - pure data 00427 WRITE_POD( &curdir, curdir ); 00428 WRITE_POD( &info, info ); 00429 } 00430 00431 void DOS_Drive::LoadState( std::istream& stream ) 00432 { 00433 // - pure data 00434 READ_POD( &curdir, curdir ); 00435 READ_POD( &info, info ); 00436 } 00437 00438 void DriveManager::SaveState( std::ostream& stream ) 00439 { 00440 // - pure data 00441 WRITE_POD( ¤tDrive, currentDrive ); 00442 } 00443 00444 void DriveManager::LoadState( std::istream& stream ) 00445 { 00446 // - pure data 00447 READ_POD( ¤tDrive, currentDrive ); 00448 } 00449 00450 void POD_Save_DOS_DriveManager( std::ostream& stream ) 00451 { 00452 DriveManager::SaveState(stream); 00453 } 00454 00455 void POD_Load_DOS_DriveManager( std::istream& stream ) 00456 { 00457 DriveManager::LoadState(stream); 00458 }