diff --git a/src/dos/cdrom_image.cpp b/src/dos/cdrom_image.cpp index 2a31d224..bd4cb411 100644 --- a/src/dos/cdrom_image.cpp +++ b/src/dos/cdrom_image.cpp @@ -416,8 +416,9 @@ bool CDROM_Interface_Image::CanReadPVD(TrackFile *file, int sectorSize, bool mod if (sectorSize == RAW_SECTOR_SIZE && !mode2) seek += 16; if (mode2) seek += 24; file->read(pvd, seek, COOKED_SECTOR_SIZE); - // pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version - return (pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1); + // pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version (+8 for High Sierra) + return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || + (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); } #if defined(WIN32) diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp index b0f1d187..ca406d71 100644 --- a/src/dos/dos_mscdex.cpp +++ b/src/dos/dos_mscdex.cpp @@ -117,7 +117,7 @@ public: bool GetAbstractName (Bit16u drive, PhysPt data); bool GetDocumentationName(Bit16u drive, PhysPt data); bool GetDirectoryEntry (Bit16u drive, bool copyFlag, PhysPt pathname, PhysPt buffer, Bit16u& error); - bool ReadVTOC (Bit16u drive, Bit16u volume, PhysPt data, Bit16u& error); + bool ReadVTOC (Bit16u drive, Bit16u volume, PhysPt data, Bit16u& offset, Bit16u& error); bool ReadSectors (Bit16u drive, Bit32u sector, Bit16u num, PhysPt data); bool ReadSectors (Bit8u subUnit, bool raw, Bit32u sector, Bit16u num, PhysPt data); bool ReadSectorsMSF (Bit8u subUnit, bool raw, Bit32u sector, Bit16u num, PhysPt data); @@ -577,7 +577,7 @@ Bit32u CMscdex::GetVolumeSize(Bit8u subUnit) { return 0; } -bool CMscdex::ReadVTOC(Bit16u drive, Bit16u volume, PhysPt data, Bit16u& error) { +bool CMscdex::ReadVTOC(Bit16u drive, Bit16u volume, PhysPt data, Bit16u& offset, Bit16u& error) { Bit8u subunit = GetSubUnit(drive); /* if (subunit>=numDrives) { error=MSCDEX_ERROR_UNKNOWN_DRIVE; @@ -589,11 +589,16 @@ bool CMscdex::ReadVTOC(Bit16u drive, Bit16u volume, PhysPt data, Bit16u& error) } char id[5]; MEM_BlockRead(data + 1, id, 5); - if (strncmp("CD001",id, 5)!=0) { - error = MSCDEX_ERROR_BAD_FORMAT; - return false; + if (strncmp("CD001", id, 5)==0) offset = 0; + else { + MEM_BlockRead(data + 9, id, 5); + if (strncmp("CDROM", id, 5)==0) offset = 8; + else { + error = MSCDEX_ERROR_BAD_FORMAT; + return false; + } } - Bit8u type = mem_readb(data); + Bit8u type = mem_readb(data + offset); error = (type == 1) ? 1 : (type == 0xFF) ? 0xFF : 0; return true; } @@ -602,12 +607,12 @@ bool CMscdex::GetVolumeName(Bit8u subUnit, char* data) { if (subUnit>=numDrives) return false; Bit16u drive = dinfo[subUnit].drive; - Bit16u error; + Bit16u offset = 0, error; bool success = false; PhysPt ptoc = GetTempBuffer(); - success = ReadVTOC(drive,0x00,ptoc,error); + success = ReadVTOC(drive,0x00,ptoc,offset,error); if (success) { - MEM_StrCopy(ptoc+40,data,31); + MEM_StrCopy(ptoc+offset+40,data,31); data[31] = 0; rtrim(data); }; @@ -616,51 +621,51 @@ bool CMscdex::GetVolumeName(Bit8u subUnit, char* data) { } bool CMscdex::GetCopyrightName(Bit16u drive, PhysPt data) { - Bit16u error; + Bit16u offset = 0, error; bool success = false; PhysPt ptoc = GetTempBuffer(); - success = ReadVTOC(drive,0x00,ptoc,error); + success = ReadVTOC(drive,0x00,ptoc,offset,error); if (success) { Bitu len; for (len=0;len<37;len++) { - Bit8u c=mem_readb(ptoc+702+len); + Bit8u c=mem_readb(ptoc+offset+702+len); if (c==0 || c==0x20) break; } - MEM_BlockCopy(data,ptoc+702,len); + MEM_BlockCopy(data,ptoc+offset+702,len); mem_writeb(data+len,0); }; return success; } bool CMscdex::GetAbstractName(Bit16u drive, PhysPt data) { - Bit16u error; + Bit16u offset = 0, error; bool success = false; PhysPt ptoc = GetTempBuffer(); - success = ReadVTOC(drive,0x00,ptoc,error); + success = ReadVTOC(drive,0x00,ptoc,offset,error); if (success) { Bitu len; for (len=0;len<37;len++) { - Bit8u c=mem_readb(ptoc+739+len); + Bit8u c=mem_readb(ptoc+offset+739+len); if (c==0 || c==0x20) break; } - MEM_BlockCopy(data,ptoc+739,len); + MEM_BlockCopy(data,ptoc+offset+739,len); mem_writeb(data+len,0); }; return success; } bool CMscdex::GetDocumentationName(Bit16u drive, PhysPt data) { - Bit16u error; + Bit16u offset = 0, error; bool success = false; PhysPt ptoc = GetTempBuffer(); - success = ReadVTOC(drive,0x00,ptoc,error); + success = ReadVTOC(drive,0x00,ptoc,offset,error); if (success) { Bitu len; for (len=0;len<37;len++) { - Bit8u c=mem_readb(ptoc+776+len); + Bit8u c=mem_readb(ptoc+offset+776+len); if (c==0 || c==0x20) break; } - MEM_BlockCopy(data,ptoc+776,len); + MEM_BlockCopy(data,ptoc+offset+776,len); mem_writeb(data+len,0); }; return success; @@ -718,13 +723,17 @@ bool CMscdex::GetDirectoryEntry(Bit16u drive, bool copyFlag, PhysPt pathname, Ph // read vtoc PhysPt defBuffer = GetDefaultBuffer(); if (!ReadSectors(GetSubUnit(drive),false,16,1,defBuffer)) return false; - // TODO: has to be iso 9960 MEM_StrCopy(defBuffer+1,volumeID,5); volumeID[5] = 0; - bool iso = (strcmp("CD001",volumeID)==0); - if (!iso) E_Exit("MSCDEX: GetDirEntry: Not an ISO 9960 CD."); + Bit16u offset; + if (strcmp("CD001",volumeID)==0) offset = 156; + else { + MEM_StrCopy(defBuffer+9,volumeID,5); + if (strcmp("CDROM",volumeID)==0) offset = 180; + else E_Exit("MSCDEX: GetDirEntry: Not an ISO 9660 or High Sierra CD."); + } // get directory position - Bitu dirEntrySector = mem_readd(defBuffer+156+2); - Bits dirSize = mem_readd(defBuffer+156+10); + Bitu dirEntrySector = mem_readd(defBuffer+offset+2); + Bits dirSize = mem_readd(defBuffer+offset+10); Bitu index; while (dirSize>0) { index = 0; @@ -790,7 +799,7 @@ bool CMscdex::GetDirectoryEntry(Bit16u drive, bool copyFlag, PhysPt pathname, Ph // Direct copy MEM_BlockCopy(buffer,defBuffer+index,entryLength); } - error = iso ? 1:0; + error = 1; return true; } // change directory @@ -1203,8 +1212,8 @@ static bool MSCDEX_Handler(void) { }; return true; case 0x1505: { // read vtoc - Bit16u error = 0; - if (mscdex->ReadVTOC(reg_cx,reg_dx,data,error)) { + Bit16u offset = 0, error = 0; + if (mscdex->ReadVTOC(reg_cx,reg_dx,data,offset,error)) { // reg_ax = error; // return code CALLBACK_SCF(false); } else { diff --git a/src/dos/drive_iso.cpp b/src/dos/drive_iso.cpp index 8e4d96d0..6be44bd8 100644 --- a/src/dos/drive_iso.cpp +++ b/src/dos/drive_iso.cpp @@ -25,6 +25,9 @@ #include "support.h" #include "drives.h" +#define FLAGS1 ((iso) ? de.fileFlags : de.timeZone) +#define FLAGS2 ((iso) ? de->fileFlags : de->timeZone) + using namespace std; class isoFile : public DOS_File { @@ -198,7 +201,7 @@ bool isoDrive::FileOpen(DOS_File **file, char *name, Bit32u flags) { } isoDirEntry de; - bool success = lookup(&de, name) && !IS_DIR(de.fileFlags); + bool success = lookup(&de, name) && !IS_DIR(FLAGS1); if (success) { FileStat_Block file_stat; @@ -234,7 +237,7 @@ bool isoDrive::MakeDir(char* /*dir*/) { bool isoDrive::TestDir(char *dir) { isoDirEntry de; - return (lookup(&de, dir) && IS_DIR(de.fileFlags)); + return (lookup(&de, dir) && IS_DIR(FLAGS1)); } bool isoDrive::FindFirst(char *dir, DOS_DTA &dta, bool fcb_findfirst) { @@ -279,11 +282,11 @@ bool isoDrive::FindNext(DOS_DTA &dta) { isoDirEntry de; while (GetNextDirEntry(dirIterator, &de)) { Bit8u findAttr = 0; - if (IS_DIR(de.fileFlags)) findAttr |= DOS_ATTR_DIRECTORY; + if (IS_DIR(FLAGS1)) findAttr |= DOS_ATTR_DIRECTORY; else findAttr |= DOS_ATTR_ARCHIVE; - if (IS_HIDDEN(de.fileFlags)) findAttr |= DOS_ATTR_HIDDEN; + if (IS_HIDDEN(FLAGS1)) findAttr |= DOS_ATTR_HIDDEN; - if (!IS_ASSOC(de.fileFlags) && !(isRoot && de.ident[0]=='.') && WildFileCmp((char*)de.ident, pattern) + if (!IS_ASSOC(FLAGS1) && !(isRoot && de.ident[0]=='.') && WildFileCmp((char*)de.ident, pattern) && !(~attr & findAttr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM))) { /* file is okay, setup everything to be copied in DTA Block */ @@ -318,8 +321,8 @@ bool isoDrive::GetFileAttr(char *name, Bit16u *attr) { bool success = lookup(&de, name); if (success) { *attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY; - if (IS_HIDDEN(de.fileFlags)) *attr |= DOS_ATTR_HIDDEN; - if (IS_DIR(de.fileFlags)) *attr |= DOS_ATTR_DIRECTORY; + if (IS_HIDDEN(FLAGS1)) *attr |= DOS_ATTR_HIDDEN; + if (IS_DIR(FLAGS1)) *attr |= DOS_ATTR_DIRECTORY; } return success; } @@ -334,7 +337,7 @@ bool isoDrive::AllocationInfo(Bit16u *bytes_sector, Bit8u *sectors_cluster, Bit1 bool isoDrive::FileExists(const char *name) { isoDirEntry de; - return (lookup(&de, name) && !IS_DIR(de.fileFlags)); + return (lookup(&de, name) && !IS_DIR(FLAGS1)); } bool isoDrive::FileStat(const char *name, FileStat_Block *const stat_block) { @@ -346,7 +349,7 @@ bool isoDrive::FileStat(const char *name, FileStat_Block *const stat_block) { stat_block->time = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec); stat_block->size = DATA_LENGTH(de); stat_block->attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY; - if (IS_DIR(de.fileFlags)) stat_block->attr |= DOS_ATTR_DIRECTORY; + if (IS_DIR(FLAGS1)) stat_block->attr |= DOS_ATTR_DIRECTORY; } return success; @@ -470,7 +473,7 @@ int isoDrive :: readDirEntry(isoDirEntry *de, Bit8u *data) { // modify file identifier for use with dosbox if ((de->length < 33 + de->fileIdentLength)) return -1; - if (IS_DIR(de->fileFlags)) { + if (IS_DIR(FLAGS2)) { if (de->fileIdentLength == 1 && de->ident[0] == 0) strcpy((char*)de->ident, "."); else if (de->fileIdentLength == 1 && de->ident[0] == 1) strcpy((char*)de->ident, ".."); else { @@ -499,11 +502,14 @@ int isoDrive :: readDirEntry(isoDirEntry *de, Bit8u *data) { } bool isoDrive :: loadImage() { - isoPVD pvd; + Bit8u pvd[COOKED_SECTOR_SIZE]; dataCD = false; - readSector((Bit8u*)(&pvd), ISO_FIRST_VD); - if (pvd.type != 1 || strncmp((char*)pvd.standardIdent, "CD001", 5) || pvd.version != 1) return false; - if (readDirEntry(&this->rootEntry, pvd.rootEntry)>0) { + readSector(pvd, ISO_FIRST_VD); + if (pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) iso = true; + else if (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1) iso = false; + else return false; + Bit16u offset = iso ? 156 : 180; + if (readDirEntry(&this->rootEntry, &pvd[offset])>0) { dataCD = true; return true; } @@ -524,7 +530,7 @@ bool isoDrive :: lookup(isoDirEntry *de, const char *path) { bool found = false; // current entry must be a directory, abort otherwise - if (IS_DIR(de->fileFlags)) { + if (IS_DIR(FLAGS2)) { // remove the trailing dot if present size_t nameLength = strlen(name); @@ -535,7 +541,7 @@ bool isoDrive :: lookup(isoDirEntry *de, const char *path) { // look for the current path element int dirIterator = GetDirIterator(de); while (!found && GetNextDirEntry(dirIterator, de)) { - if (!IS_ASSOC(de->fileFlags) && (0 == strncasecmp((char*) de->ident, name, ISO_MAX_FILENAME_LENGTH))) { + if (!IS_ASSOC(FLAGS2) && (0 == strncasecmp((char*) de->ident, name, ISO_MAX_FILENAME_LENGTH))) { found = true; } } diff --git a/src/dos/drives.h b/src/dos/drives.h index 0138163b..9d22da8c 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -363,6 +363,7 @@ private: Bit8u data[ISO_FRAMESIZE]; } sectorHashEntries[ISO_MAX_HASH_TABLE_SIZE]; + bool iso; bool dataCD; isoDirEntry rootEntry; Bit8u mediaid;