From bdddfdb4b8babbbc2f4eeaa4863320ba6a3a73e6 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 21 Nov 2022 17:07:33 -0300 Subject: [PATCH] VISO: Overhaul format selection system --- src/cdrom/cdrom_image_viso.c | 104 ++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/src/cdrom/cdrom_image_viso.c b/src/cdrom/cdrom_image_viso.c index f7d96dbc7..66572c5a3 100644 --- a/src/cdrom/cdrom_image_viso.c +++ b/src/cdrom/cdrom_image_viso.c @@ -89,9 +89,9 @@ enum { }; enum { - VISO_FORMAT_HSF = 0, /* High Sierra */ - VISO_FORMAT_ISO, /* ISO 9660 */ - VISO_FORMAT_ISO_LFN /* ISO 9660 with Joliet and Rock Ridge */ + VISO_FORMAT_ISO = 1, /* ISO 9660 (High Sierra if not set) */ + VISO_FORMAT_JOLIET = 2, /* Joliet extensions (Microsoft) */ + VISO_FORMAT_RR = 4 /* Rock Ridge extensions (*nix) */ }; 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); /* Trim decoded filename to max_len if needed. */ - max_len /= 2; + max_len >>= 1; if (len > max_len) { 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_sec; /* second */ } - if (format >= VISO_FORMAT_ISO) + if (format & VISO_FORMAT_ISO) *p++ = tz_offset; /* timezone (ISO only) */ 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++ = 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 */ 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 .. */ /* 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++ = 'R'; *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; /* 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'; *p++ = 5; /* length */ @@ -765,8 +765,8 @@ viso_init(const char *dirname, int *error) if (viso == NULL) goto end; viso->sector_size = VISO_SECTOR_SIZE; - viso->format = VISO_FORMAT_ISO_LFN; - viso->use_version_suffix = (viso->format >= VISO_FORMAT_ISO); /* cleared later if required */ + viso->format = VISO_FORMAT_ISO | VISO_FORMAT_JOLIET | VISO_FORMAT_RR; + viso->use_version_suffix = (viso->format & VISO_FORMAT_ISO); /* cleared later if required */ /* Prepare temporary data buffers. */ data = calloc(2, viso->sector_size); @@ -977,7 +977,7 @@ next_dir: the timezone offset for descriptors and file times to use. */ tzset(); 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); /* Get root directory basename for the volume ID. */ @@ -985,14 +985,18 @@ next_dir: if (!basename || (basename[0] == '\0')) 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. */ - for (int i = 0; i <= (viso->format >= VISO_FORMAT_ISO_LFN); i++) { + for (int i = 0; i <= max_vd; i++) { /* Fill volume descriptor. */ p = data; - if (viso->format <= VISO_FORMAT_HSF) - VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */ - *p++ = 1 + i; /* type */ - memcpy(p, (viso->format <= VISO_FORMAT_HSF) ? "CDROM" : "CD001", 5); /* standard ID */ + if (!(viso->format & VISO_FORMAT_ISO)) + VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */ + *p++ = 1 + i; /* type */ + memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */ p += 5; *p++ = 1; /* version */ *p++ = 0; /* unused */ @@ -1031,11 +1035,12 @@ next_dir: /* Path table metadata is filled in later. */ 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); 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) { viso_write_wstring((uint16_t *) p, L"", 64, VISO_CHARSET_D); /* volume set ID */ p += 128; @@ -1045,11 +1050,11 @@ next_dir: p += 128; viso_write_wstring((uint16_t *) p, EMU_NAME_W L" " EMU_VERSION_W L" VIRTUAL ISO", 64, VISO_CHARSET_A); /* application ID */ p += 128; - viso_write_wstring((uint16_t *) p, L"", (viso->format <= VISO_FORMAT_HSF) ? 16 : 18, VISO_CHARSET_D); /* copyright file ID */ - p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37; - viso_write_wstring((uint16_t *) p, L"", (viso->format <= VISO_FORMAT_HSF) ? 16 : 18, VISO_CHARSET_D); /* abstract file ID */ - p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37; - if (viso->format >= VISO_FORMAT_ISO) { + viso_write_wstring((uint16_t *) p, L"", copyright_abstract_len >> 1, VISO_CHARSET_D); /* copyright file ID */ + p += copyright_abstract_len; + viso_write_wstring((uint16_t *) p, L"", copyright_abstract_len >> 1, VISO_CHARSET_D); /* abstract file ID */ + p += copyright_abstract_len; + if (viso->format & VISO_FORMAT_ISO) { viso_write_wstring((uint16_t *) p, L"", 18, VISO_CHARSET_D); /* bibliography file ID (ISO only) */ p += 37; } @@ -1062,11 +1067,11 @@ next_dir: p += 128; viso_write_string(p, EMU_NAME " " EMU_VERSION " VIRTUAL ISO", 128, VISO_CHARSET_A); /* application ID */ p += 128; - viso_write_string(p, "", (viso->format <= VISO_FORMAT_HSF) ? 32 : 37, VISO_CHARSET_D); /* copyright file ID */ - p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37; - viso_write_string(p, "", (viso->format <= VISO_FORMAT_HSF) ? 32 : 37, VISO_CHARSET_D); /* abstract file ID */ - p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37; - if (viso->format >= VISO_FORMAT_ISO) { + viso_write_string(p, "", copyright_abstract_len, VISO_CHARSET_D); /* copyright file ID */ + p += copyright_abstract_len; + viso_write_string(p, "", copyright_abstract_len, VISO_CHARSET_D); /* abstract file ID */ + p += copyright_abstract_len; + if (viso->format & VISO_FORMAT_ISO) { viso_write_string(p, "", 37, VISO_CHARSET_D); /* bibliography file ID (ISO only) */ p += 37; } @@ -1092,10 +1097,10 @@ next_dir: cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", eltorito_entry); p = data; - if (viso->format <= VISO_FORMAT_HSF) - VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */ - *p++ = 0; /* type */ - memcpy(p, (viso->format <= VISO_FORMAT_HSF) ? "CDROM" : "CD001", 5); /* standard ID */ + if (!(viso->format & VISO_FORMAT_ISO)) + VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */ + *p++ = 0; /* type */ + memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */ p += 5; *p++ = 1; /* version */ @@ -1116,10 +1121,10 @@ next_dir: /* Fill terminator. */ p = data; - if (viso->format <= VISO_FORMAT_HSF) - VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */ - *p++ = 0xff; /* type */ - memcpy(p, (viso->format <= VISO_FORMAT_HSF) ? "CDROM" : "CD001", 5); /* standard ID */ + if (!(viso->format & VISO_FORMAT_ISO)) + VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */ + *p++ = 0xff; /* type */ + memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */ p += 5; *p++ = 1; /* version */ @@ -1195,7 +1200,7 @@ next_dir: } /* 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); /* Save this path table's start offset. */ @@ -1225,7 +1230,7 @@ next_dir: /* Fill path table entry. */ p = data; - if (viso->format <= VISO_FORMAT_HSF) { + if (!(viso->format & VISO_FORMAT_ISO)) { *((uint32_t *) p) = 0; /* extent location (filled in later) */ p += 4; *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 */ p += 2; - if (dir == viso->root_dir) { /* directory ID and length */ - data[5 * (viso->format <= VISO_FORMAT_HSF)] = 1; - *p = 0x00; - } else if (i & 2) { - data[5 * (viso->format <= VISO_FORMAT_HSF)] = viso_fill_fn_joliet(p, dir, 255); - } else { - data[5 * (viso->format <= VISO_FORMAT_HSF)] = strlen(dir->name_short); - memcpy(p, dir->name_short, data[5 * (viso->format <= VISO_FORMAT_HSF)]); + pt_temp = 5 * !(viso->format & VISO_FORMAT_ISO); /* directory ID length at offset 0 for ISO, 5 for HSF */ + if (dir == viso->root_dir) { /* directory ID length then ID for root... */ + data[pt_temp] = 1; + *p = 0x00; + } else if (i & 2) { /* ...or Joliet... */ + data[pt_temp] = viso_fill_fn_joliet(p, dir, 255); + } else { /* ...or short name */ + 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 */ *p++ = 0x00; @@ -1283,7 +1289,7 @@ next_dir: /* Write directory records for each type. */ 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); /* 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 + 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; /* Go through entries in this directory. */ @@ -1470,7 +1476,7 @@ next_entry: } else { p = data; 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); }