1
0
Fork 0

Add support for High Sierra format cdrom images.

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3886
This commit is contained in:
ripsaw8080 2015-01-08 17:23:15 +00:00
parent 56c3a4be9c
commit 933174fb3e
4 changed files with 64 additions and 47 deletions

View file

@ -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)

View file

@ -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 {

View file

@ -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;
}
}

View file

@ -363,6 +363,7 @@ private:
Bit8u data[ISO_FRAMESIZE];
} sectorHashEntries[ISO_MAX_HASH_TABLE_SIZE];
bool iso;
bool dataCD;
isoDirEntry rootEntry;
Bit8u mediaid;