VISO: Overhaul format selection system

This commit is contained in:
RichardG867
2022-11-21 17:07:33 -03:00
parent 711eaf5bdd
commit bdddfdb4b8

View File

@@ -89,9 +89,9 @@ enum {
}; };
enum { enum {
VISO_FORMAT_HSF = 0, /* High Sierra */ VISO_FORMAT_ISO = 1, /* ISO 9660 (High Sierra if not set) */
VISO_FORMAT_ISO, /* ISO 9660 */ VISO_FORMAT_JOLIET = 2, /* Joliet extensions (Microsoft) */
VISO_FORMAT_ISO_LFN /* ISO 9660 with Joliet and Rock Ridge */ VISO_FORMAT_RR = 4 /* Rock Ridge extensions (*nix) */
}; };
typedef struct _viso_entry_ { typedef struct _viso_entry_ {
@@ -392,7 +392,7 @@ viso_fill_fn_joliet(uint8_t *data, const viso_entry_t *entry, size_t max_len) /*
len = viso_convert_utf8(utf8dec, entry->basename, len + 1); len = viso_convert_utf8(utf8dec, entry->basename, len + 1);
/* Trim decoded filename to max_len if needed. */ /* Trim decoded filename to max_len if needed. */
max_len /= 2; max_len >>= 1;
if (len > max_len) { if (len > max_len) {
viso_write_wstring((uint16_t *) data, utf8dec, max_len, VISO_CHARSET_FN); viso_write_wstring((uint16_t *) data, utf8dec, max_len, VISO_CHARSET_FN);
@@ -463,7 +463,7 @@ viso_fill_time(uint8_t *data, time_t time, int format, int longform)
*p++ = time_s->tm_min; /* minute */ *p++ = time_s->tm_min; /* minute */
*p++ = time_s->tm_sec; /* second */ *p++ = time_s->tm_sec; /* second */
} }
if (format >= VISO_FORMAT_ISO) if (format & VISO_FORMAT_ISO)
*p++ = tz_offset; /* timezone (ISO only) */ *p++ = tz_offset; /* timezone (ISO only) */
return p - data; return p - data;
@@ -485,7 +485,7 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, viso_t *viso, int type)
p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* time */ p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* time */
*p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */ *p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */
VISO_SKIP(p, 2 + (viso->format <= VISO_FORMAT_HSF)); /* file unit size (reserved on HSF), interleave gap size (HSF/ISO) and skip factor (HSF only) */ VISO_SKIP(p, 2 + !(viso->format & VISO_FORMAT_ISO)); /* file unit size (reserved on HSF), interleave gap size (HSF/ISO) and skip factor (HSF only) */
VISO_LBE_16(p, 1); /* volume sequence number */ VISO_LBE_16(p, 1); /* volume sequence number */
switch (type) { switch (type) {
@@ -496,7 +496,7 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, viso_t *viso, int type)
*p++ = (type == VISO_DIR_PARENT) ? 1 : 0; /* magic value corresponding to . or .. */ *p++ = (type == VISO_DIR_PARENT) ? 1 : 0; /* magic value corresponding to . or .. */
/* Fill Rock Ridge Extension Record for the root directory's . entry. */ /* Fill Rock Ridge Extension Record for the root directory's . entry. */
if ((type == VISO_DIR_CURRENT_ROOT) && (viso->format >= VISO_FORMAT_ISO_LFN)) { if ((type == VISO_DIR_CURRENT_ROOT) && (viso->format & VISO_FORMAT_RR)) {
*p++ = 'E'; *p++ = 'E';
*p++ = 'R'; *p++ = 'R';
*p++ = 8 + (sizeof(rr_eid) - 1) + (sizeof(rr_edesc) - 1); /* length */ *p++ = 8 + (sizeof(rr_eid) - 1) + (sizeof(rr_edesc) - 1); /* length */
@@ -532,7 +532,7 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, viso_t *viso, int type)
*p++ = 0; *p++ = 0;
/* Fill Rock Ridge data. */ /* Fill Rock Ridge data. */
if (viso->format >= VISO_FORMAT_ISO_LFN) { if (viso->format & VISO_FORMAT_RR) {
*p++ = 'R'; /* RR = present Rock Ridge entries (only documented by RRIP revision 1.09!) */ *p++ = 'R'; /* RR = present Rock Ridge entries (only documented by RRIP revision 1.09!) */
*p++ = 'R'; *p++ = 'R';
*p++ = 5; /* length */ *p++ = 5; /* length */
@@ -765,8 +765,8 @@ viso_init(const char *dirname, int *error)
if (viso == NULL) if (viso == NULL)
goto end; goto end;
viso->sector_size = VISO_SECTOR_SIZE; viso->sector_size = VISO_SECTOR_SIZE;
viso->format = VISO_FORMAT_ISO_LFN; viso->format = VISO_FORMAT_ISO | VISO_FORMAT_JOLIET | VISO_FORMAT_RR;
viso->use_version_suffix = (viso->format >= VISO_FORMAT_ISO); /* cleared later if required */ viso->use_version_suffix = (viso->format & VISO_FORMAT_ISO); /* cleared later if required */
/* Prepare temporary data buffers. */ /* Prepare temporary data buffers. */
data = calloc(2, viso->sector_size); data = calloc(2, viso->sector_size);
@@ -977,7 +977,7 @@ next_dir:
the timezone offset for descriptors and file times to use. */ the timezone offset for descriptors and file times to use. */
tzset(); tzset();
time_t now = time(NULL); time_t now = time(NULL);
if (viso->format >= VISO_FORMAT_ISO) /* timezones are ISO only */ if (viso->format & VISO_FORMAT_ISO) /* timezones are ISO only */
tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4); tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4);
/* Get root directory basename for the volume ID. */ /* Get root directory basename for the volume ID. */
@@ -985,14 +985,18 @@ next_dir:
if (!basename || (basename[0] == '\0')) if (!basename || (basename[0] == '\0'))
basename = EMU_NAME; basename = EMU_NAME;
/* Determine whether or not we're working with 2 volume descriptors
(as well as 2 directory trees and 4 path tables) for Joliet. */
int max_vd = (viso->format & VISO_FORMAT_JOLIET) ? 1 : 0;
/* Write volume descriptors. */ /* Write volume descriptors. */
for (int i = 0; i <= (viso->format >= VISO_FORMAT_ISO_LFN); i++) { for (int i = 0; i <= max_vd; i++) {
/* Fill volume descriptor. */ /* Fill volume descriptor. */
p = data; p = data;
if (viso->format <= VISO_FORMAT_HSF) if (!(viso->format & VISO_FORMAT_ISO))
VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */ VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */
*p++ = 1 + i; /* type */ *p++ = 1 + i; /* type */
memcpy(p, (viso->format <= VISO_FORMAT_HSF) ? "CDROM" : "CD001", 5); /* standard ID */ memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */
p += 5; p += 5;
*p++ = 1; /* version */ *p++ = 1; /* version */
*p++ = 0; /* unused */ *p++ = 0; /* unused */
@@ -1031,11 +1035,12 @@ next_dir:
/* Path table metadata is filled in later. */ /* Path table metadata is filled in later. */
viso->pt_meta_offsets[i] = ftello64(viso->tf.file) + (p - data); viso->pt_meta_offsets[i] = ftello64(viso->tf.file) + (p - data);
VISO_SKIP(p, 24 + (16 * (viso->format <= VISO_FORMAT_HSF))); /* PT size, LE PT offset, optional LE PT offset (three on HSF), BE PT offset, optional BE PT offset (three on HSF) */ VISO_SKIP(p, 24 + (16 * !(viso->format & VISO_FORMAT_ISO))); /* PT size, LE PT offset, optional LE PT offset (three on HSF), BE PT offset, optional BE PT offset (three on HSF) */
viso->root_dir->dr_offsets[i] = ftello64(viso->tf.file) + (p - data); viso->root_dir->dr_offsets[i] = ftello64(viso->tf.file) + (p - data);
p += viso_fill_dir_record(p, viso->root_dir, viso, VISO_DIR_CURRENT); /* root directory */ p += viso_fill_dir_record(p, viso->root_dir, viso, VISO_DIR_CURRENT); /* root directory */
int copyright_abstract_len = (viso->format & VISO_FORMAT_ISO) ? 37 : 32;
if (i) { if (i) {
viso_write_wstring((uint16_t *) p, L"", 64, VISO_CHARSET_D); /* volume set ID */ viso_write_wstring((uint16_t *) p, L"", 64, VISO_CHARSET_D); /* volume set ID */
p += 128; p += 128;
@@ -1045,11 +1050,11 @@ next_dir:
p += 128; p += 128;
viso_write_wstring((uint16_t *) p, EMU_NAME_W L" " EMU_VERSION_W L" VIRTUAL ISO", 64, VISO_CHARSET_A); /* application ID */ viso_write_wstring((uint16_t *) p, EMU_NAME_W L" " EMU_VERSION_W L" VIRTUAL ISO", 64, VISO_CHARSET_A); /* application ID */
p += 128; p += 128;
viso_write_wstring((uint16_t *) p, L"", (viso->format <= VISO_FORMAT_HSF) ? 16 : 18, VISO_CHARSET_D); /* copyright file ID */ viso_write_wstring((uint16_t *) p, L"", copyright_abstract_len >> 1, VISO_CHARSET_D); /* copyright file ID */
p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37; p += copyright_abstract_len;
viso_write_wstring((uint16_t *) p, L"", (viso->format <= VISO_FORMAT_HSF) ? 16 : 18, VISO_CHARSET_D); /* abstract file ID */ viso_write_wstring((uint16_t *) p, L"", copyright_abstract_len >> 1, VISO_CHARSET_D); /* abstract file ID */
p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37; p += copyright_abstract_len;
if (viso->format >= VISO_FORMAT_ISO) { if (viso->format & VISO_FORMAT_ISO) {
viso_write_wstring((uint16_t *) p, L"", 18, VISO_CHARSET_D); /* bibliography file ID (ISO only) */ viso_write_wstring((uint16_t *) p, L"", 18, VISO_CHARSET_D); /* bibliography file ID (ISO only) */
p += 37; p += 37;
} }
@@ -1062,11 +1067,11 @@ next_dir:
p += 128; p += 128;
viso_write_string(p, EMU_NAME " " EMU_VERSION " VIRTUAL ISO", 128, VISO_CHARSET_A); /* application ID */ viso_write_string(p, EMU_NAME " " EMU_VERSION " VIRTUAL ISO", 128, VISO_CHARSET_A); /* application ID */
p += 128; p += 128;
viso_write_string(p, "", (viso->format <= VISO_FORMAT_HSF) ? 32 : 37, VISO_CHARSET_D); /* copyright file ID */ viso_write_string(p, "", copyright_abstract_len, VISO_CHARSET_D); /* copyright file ID */
p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37; p += copyright_abstract_len;
viso_write_string(p, "", (viso->format <= VISO_FORMAT_HSF) ? 32 : 37, VISO_CHARSET_D); /* abstract file ID */ viso_write_string(p, "", copyright_abstract_len, VISO_CHARSET_D); /* abstract file ID */
p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37; p += copyright_abstract_len;
if (viso->format >= VISO_FORMAT_ISO) { if (viso->format & VISO_FORMAT_ISO) {
viso_write_string(p, "", 37, VISO_CHARSET_D); /* bibliography file ID (ISO only) */ viso_write_string(p, "", 37, VISO_CHARSET_D); /* bibliography file ID (ISO only) */
p += 37; p += 37;
} }
@@ -1092,10 +1097,10 @@ next_dir:
cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", eltorito_entry); cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", eltorito_entry);
p = data; p = data;
if (viso->format <= VISO_FORMAT_HSF) if (!(viso->format & VISO_FORMAT_ISO))
VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */ VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */
*p++ = 0; /* type */ *p++ = 0; /* type */
memcpy(p, (viso->format <= VISO_FORMAT_HSF) ? "CDROM" : "CD001", 5); /* standard ID */ memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */
p += 5; p += 5;
*p++ = 1; /* version */ *p++ = 1; /* version */
@@ -1116,10 +1121,10 @@ next_dir:
/* Fill terminator. */ /* Fill terminator. */
p = data; p = data;
if (viso->format <= VISO_FORMAT_HSF) if (!(viso->format & VISO_FORMAT_ISO))
VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */ VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */
*p++ = 0xff; /* type */ *p++ = 0xff; /* type */
memcpy(p, (viso->format <= VISO_FORMAT_HSF) ? "CDROM" : "CD001", 5); /* standard ID */ memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */
p += 5; p += 5;
*p++ = 1; /* version */ *p++ = 1; /* version */
@@ -1195,7 +1200,7 @@ next_dir:
} }
/* Write each path table. */ /* Write each path table. */
for (int i = 0; i <= ((viso->format >= VISO_FORMAT_ISO_LFN) ? 3 : 1); i++) { for (int i = 0; i <= ((max_vd << 1) | 1); i++) {
cdrom_image_viso_log("VISO: Generating path table #%d:\n", i); cdrom_image_viso_log("VISO: Generating path table #%d:\n", i);
/* Save this path table's start offset. */ /* Save this path table's start offset. */
@@ -1225,7 +1230,7 @@ next_dir:
/* Fill path table entry. */ /* Fill path table entry. */
p = data; p = data;
if (viso->format <= VISO_FORMAT_HSF) { if (!(viso->format & VISO_FORMAT_ISO)) {
*((uint32_t *) p) = 0; /* extent location (filled in later) */ *((uint32_t *) p) = 0; /* extent location (filled in later) */
p += 4; p += 4;
*p++ = 0; /* extended attribute length */ *p++ = 0; /* extended attribute length */
@@ -1241,16 +1246,17 @@ next_dir:
*((uint16_t *) p) = (i & 1) ? cpu_to_be16(dir->parent->pt_idx) : cpu_to_le16(dir->parent->pt_idx); /* parent directory number */ *((uint16_t *) p) = (i & 1) ? cpu_to_be16(dir->parent->pt_idx) : cpu_to_le16(dir->parent->pt_idx); /* parent directory number */
p += 2; p += 2;
if (dir == viso->root_dir) { /* directory ID and length */ pt_temp = 5 * !(viso->format & VISO_FORMAT_ISO); /* directory ID length at offset 0 for ISO, 5 for HSF */
data[5 * (viso->format <= VISO_FORMAT_HSF)] = 1; if (dir == viso->root_dir) { /* directory ID length then ID for root... */
*p = 0x00; data[pt_temp] = 1;
} else if (i & 2) { *p = 0x00;
data[5 * (viso->format <= VISO_FORMAT_HSF)] = viso_fill_fn_joliet(p, dir, 255); } else if (i & 2) { /* ...or Joliet... */
} else { data[pt_temp] = viso_fill_fn_joliet(p, dir, 255);
data[5 * (viso->format <= VISO_FORMAT_HSF)] = strlen(dir->name_short); } else { /* ...or short name */
memcpy(p, dir->name_short, data[5 * (viso->format <= VISO_FORMAT_HSF)]); data[pt_temp] = strlen(dir->name_short);
memcpy(p, dir->name_short, data[pt_temp]);
} }
p += data[5 * (viso->format <= VISO_FORMAT_HSF)]; p += data[pt_temp];
if ((p - data) & 1) /* padding for odd directory ID lengths */ if ((p - data) & 1) /* padding for odd directory ID lengths */
*p++ = 0x00; *p++ = 0x00;
@@ -1283,7 +1289,7 @@ next_dir:
/* Write directory records for each type. */ /* Write directory records for each type. */
int dir_type = VISO_DIR_CURRENT_ROOT; int dir_type = VISO_DIR_CURRENT_ROOT;
for (int i = 0; i <= (viso->format >= VISO_FORMAT_ISO_LFN); i++) { for (int i = 0; i <= max_vd; i++) {
cdrom_image_viso_log("VISO: Generating directory record set #%d:\n", i); cdrom_image_viso_log("VISO: Generating directory record set #%d:\n", i);
/* Go through directories. */ /* Go through directories. */
@@ -1316,7 +1322,7 @@ next_dir:
viso_pwrite(data, dir->pt_offsets[i << 1], 4, 1, viso->tf.file); /* little endian */ viso_pwrite(data, dir->pt_offsets[i << 1], 4, 1, viso->tf.file); /* little endian */
viso_pwrite(data + 4, dir->pt_offsets[(i << 1) | 1], 4, 1, viso->tf.file); /* big endian */ viso_pwrite(data + 4, dir->pt_offsets[(i << 1) | 1], 4, 1, viso->tf.file); /* big endian */
if (i == (viso->format >= VISO_FORMAT_ISO_LFN)) /* overwrite pt_offsets in the union if we no longer need them */ if (i == max_vd) /* overwrite pt_offsets in the union if we no longer need them */
dir->file = NULL; dir->file = NULL;
/* Go through entries in this directory. */ /* Go through entries in this directory. */
@@ -1470,7 +1476,7 @@ next_entry:
} else { } else {
p = data; p = data;
VISO_LBE_32(p, viso->all_sectors * base_factor); VISO_LBE_32(p, viso->all_sectors * base_factor);
for (int i = 0; i <= (viso->format >= VISO_FORMAT_ISO_LFN); i++) for (int i = 0; i <= max_vd; i++)
viso_pwrite(data, entry->dr_offsets[i] + 2, 8, 1, viso->tf.file); viso_pwrite(data, entry->dr_offsets[i] + 2, 8, 1, viso->tf.file);
} }