The great CD-ROM clean-up and rewrite, fixes #5134.

This commit is contained in:
OBattler
2025-01-28 16:26:28 +01:00
parent 1cb17f7a3a
commit 90e1190c92
48 changed files with 9486 additions and 9389 deletions

View File

@@ -21,10 +21,8 @@ pkg_check_modules(SNDFILE REQUIRED IMPORTED_TARGET sndfile)
add_library(cdrom OBJECT
cdrom.c
cdrom_image_backend.c
cdrom_image_viso.c
cdrom_image.c
cdrom_ioctl.c
cdrom_image_viso.c
)
target_link_libraries(86Box PkgConfig::SNDFILE)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,9 @@
#define __STDC_FORMAT_MACROS
#include <ctype.h>
#include <inttypes.h>
#ifdef IMAGE_VISO_LOG
#include <stdarg.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -29,15 +31,16 @@
#include <sys/stat.h>
#include <time.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/bswap.h>
#include <86box/cdrom_image_backend.h>
#include <86box/cdrom.h>
#include <86box/cdrom_image.h>
#include <86box/cdrom_image_viso.h>
#include <86box/log.h>
#include <86box/path.h>
#include <86box/plat.h>
#include <86box/plat_dir.h>
#include <86box/version.h>
#include <86box/timer.h>
#include <86box/nvr.h>
#ifndef S_ISDIR
@@ -136,29 +139,30 @@ static const char rr_eid[] = "RRIP_1991A"; /* identifiers used in ER field for
static const char rr_edesc[] = "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS.";
static int8_t tz_offset = 0;
#ifdef ENABLE_CDROM_IMAGE_VISO_LOG
int cdrom_image_viso_do_log = ENABLE_CDROM_IMAGE_VISO_LOG;
#ifdef IMAGE_VISO_LOG
int image_viso_do_log = IMAGE_VISO_LOG;
void
cdrom_image_viso_log(const char *fmt, ...)
image_viso_log(void *priv, const char *fmt, ...)
{
va_list ap;
if (cdrom_image_viso_do_log) {
if (image_viso_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
log_out(priv, fmt, ap);
va_end(ap);
}
}
#else
# define cdrom_image_viso_log(fmt, ...)
# define image_viso_log(priv, fmt, ...)
#endif
static size_t
viso_pread(void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp)
viso_pread(void *ptr, const uint64_t offset, const size_t size,
const size_t count, FILE *fp)
{
uint64_t cur_pos = ftello64(fp);
size_t ret = 0;
const uint64_t cur_pos = ftello64(fp);
size_t ret = 0;
if (fseeko64(fp, offset, SEEK_SET) != -1)
ret = fread(ptr, size, count, fp);
fseeko64(fp, cur_pos, SEEK_SET);
@@ -166,10 +170,11 @@ viso_pread(void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp)
}
static size_t
viso_pwrite(const void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp)
viso_pwrite(const void *ptr, const uint64_t offset, const size_t size,
const size_t count, FILE *fp)
{
uint64_t cur_pos = ftello64(fp);
size_t ret = 0;
const uint64_t cur_pos = ftello64(fp);
size_t ret = 0;
if (fseeko64(fp, offset, SEEK_SET) != -1)
ret = fwrite(ptr, size, count, fp);
fseeko64(fp, cur_pos, SEEK_SET);
@@ -691,22 +696,22 @@ viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
/* Close any existing FIFO entry's file. */
viso_entry_t *other_entry = viso->file_fifo[viso->file_fifo_pos];
if (other_entry && other_entry->file) {
cdrom_image_viso_log("VISO: Closing [%s]", other_entry->path);
image_viso_log(viso->tf.log, "Closing [%s]...\n", other_entry->path);
fclose(other_entry->file);
other_entry->file = NULL;
cdrom_image_viso_log("\n");
image_viso_log(viso->tf.log, "Done\n");
}
/* Open file. */
cdrom_image_viso_log("VISO: Opening [%s]", entry->path);
image_viso_log(viso->tf.log, "Opening [%s]...\n", entry->path);
if ((entry->file = fopen(entry->path, "rb"))) {
cdrom_image_viso_log("\n");
image_viso_log(viso->tf.log, "Done\n");
/* Add this entry to the FIFO. */
viso->file_fifo[viso->file_fifo_pos++] = entry;
viso->file_fifo_pos &= (sizeof(viso->file_fifo) / sizeof(viso->file_fifo[0])) - 1;
} else {
cdrom_image_viso_log(" => failed\n");
image_viso_log(viso->tf.log, "Failed\n");
/* Clear any existing FIFO entry. */
viso->file_fifo[viso->file_fifo_pos] = NULL;
@@ -753,12 +758,12 @@ viso_close(void *priv)
if (viso == NULL)
return;
cdrom_image_viso_log("VISO: close()\n");
image_viso_log(viso->tf.log, "close()\n");
/* De-allocate everything. */
if (tf->fp)
fclose(tf->fp);
#ifndef ENABLE_CDROM_IMAGE_VISO_LOG
#ifndef ENABLE_IMAGE_VISO_LOG
remove(nvr_path(viso->tf.fn));
#endif
@@ -777,21 +782,32 @@ viso_close(void *priv)
if (viso->entry_map)
free(viso->entry_map);
if (tf->log != NULL) {
}
free(viso);
}
track_file_t *
viso_init(const char *dirname, int *error)
viso_init(const uint8_t id, const char *dirname, int *error)
{
cdrom_image_viso_log("VISO: init()\n");
/* Initialize our data structure. */
viso_t *viso = (viso_t *) calloc(1, sizeof(viso_t));
uint8_t *data = NULL;
uint8_t *p;
*error = 1;
if (viso == NULL)
goto end;
char n[1024] = { 0 };
sprintf(n, "CD-ROM %i VISO ", id + 1);
viso->tf.log = log_open(n);
image_viso_log(viso->tf.log, "init()\n");
viso->sector_size = VISO_SECTOR_SIZE;
viso->format = VISO_FORMAT_ISO | VISO_FORMAT_JOLIET | VISO_FORMAT_RR;
viso->use_version_suffix = (viso->format & VISO_FORMAT_ISO); /* cleared later if required */
@@ -802,7 +818,7 @@ viso_init(const char *dirname, int *error)
goto end;
/* Open temporary file. */
#ifdef ENABLE_CDROM_IMAGE_VISO_LOG
#ifdef ENABLE_IMAGE_VISO_LOG
strcpy(viso->tf.fn, "viso-debug.iso");
#else
plat_tempfile(viso->tf.fn, "viso", ".tmp");
@@ -812,7 +828,7 @@ viso_init(const char *dirname, int *error)
goto end;
/* Set up directory traversal. */
cdrom_image_viso_log("VISO: Traversing directories:\n");
image_viso_log(viso->tf.log, "Traversing directories:\n");
viso_entry_t *entry;
viso_entry_t *last_entry;
viso_entry_t *dir;
@@ -839,7 +855,7 @@ viso_init(const char *dirname, int *error)
if (!S_ISDIR(dir->stats.st_mode)) /* root is not a directory */
goto end;
dir->parent = dir; /* for the root's path table and .. entries */
cdrom_image_viso_log("[%08X] %s => [root]\n", dir, dir->path);
image_viso_log(viso->tf.log, "[%08X] %s => [root]\n", dir, dir->path);
/* Traverse directories, starting with the root. */
viso_entry_t **dir_entries = NULL;
@@ -889,7 +905,8 @@ viso_init(const char *dirname, int *error)
/* Set basename. */
strcpy(entry->name_short, children_count ? ".." : ".");
cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path, entry->name_short);
image_viso_log(viso->tf.log, "[%08X] %s => %s\n", entry,
dir->path, entry->name_short);
}
/* Iterate through this directory's children again, making the entries. */
@@ -897,12 +914,16 @@ viso_init(const char *dirname, int *error)
rewinddir(dirp);
while ((readdir_entry = readdir(dirp))) {
/* Ignore . and .. pseudo-directories. */
if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || (*((uint16_t *) &readdir_entry->d_name[1]) == '.')))
if ((readdir_entry->d_name[0] == '.') &&
((readdir_entry->d_name[1] == '\0') ||
(*((uint16_t *) &readdir_entry->d_name[1]) == '.')))
continue;
/* Add and fill entry. */
entry = dir_entries[children_count++] = (viso_entry_t *) calloc(1, sizeof(viso_entry_t) + dir_path_len + strlen(readdir_entry->d_name) + 2);
if (!entry)
entry = dir_entries[children_count++] =
(viso_entry_t *) calloc(1, sizeof(viso_entry_t) +
dir_path_len + strlen(readdir_entry->d_name) + 2);
if (entry == NULL)
break;
entry->parent = dir;
strcpy(entry->path, dir->path);
@@ -972,10 +993,12 @@ have_eltorito_entry:
continue;
}
cdrom_image_viso_log("[%08X] %s => [%-12s] %s\n", entry, dir->path, entry->name_short, entry->basename);
image_viso_log(viso->tf.log, "[%08X] %s => [%-12s] %s\n", entry,
dir->path, entry->name_short, entry->basename);
}
} else {
cdrom_image_viso_log("VISO: Failed to enumerate [%s], will be empty\n", dir->path);
image_viso_log(viso->tf.log, "Failed to enumerate [%s], will be empty\n",
dir->path);
}
/* Add terminator. */
@@ -1129,13 +1152,17 @@ next_dir:
/* Write El Torito boot descriptor. This is an awkward spot for
that, but the spec requires it to be the second descriptor. */
if (!i && eltorito_entry) {
cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", eltorito_entry);
image_viso_log(viso->tf.log, "Writing El Torito boot descriptor for "
"entry [%08X]\n", eltorito_entry);
p = data;
if (!(viso->format & VISO_FORMAT_ISO))
VISO_LBE_32(p, ftello64(viso->tf.fp) / viso->sector_size); /* sector offset (HSF only) */
*p++ = 0; /* type */
memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */
/* Sector offset (HSF only). */
VISO_LBE_32(p, ftello64(viso->tf.fp) / viso->sector_size);
/* Type. */
*p++ = 0;
/* Standard ID. */
memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5);
p += 5;
*p++ = 1; /* version */
@@ -1236,7 +1263,7 @@ next_dir:
/* Write each path table. */
for (int i = 0; i <= ((max_vd << 1) | 1); i++) {
cdrom_image_viso_log("VISO: Generating path table #%d:\n", i);
image_viso_log(viso->tf.log, "Generating path table #%d:\n", i);
/* Save this path table's start offset. */
uint64_t pt_start = ftello64(viso->tf.fp);
@@ -1257,7 +1284,9 @@ next_dir:
continue;
}
cdrom_image_viso_log("[%08X] %s => %s\n", dir, dir->path, ((i & 2) || (dir == viso->root_dir)) ? dir->basename : dir->name_short);
image_viso_log(viso->tf.log, "[%08X] %s => %s\n", dir,
dir->path, ((i & 2) || (dir == viso->root_dir)) ? dir->basename :
dir->name_short);
/* Save this directory's path table index and offset. */
dir->pt_idx = pt_idx;
@@ -1325,7 +1354,7 @@ next_dir:
/* Write directory records for each type. */
int dir_type = VISO_DIR_CURRENT_ROOT;
for (int i = 0; i <= max_vd; i++) {
cdrom_image_viso_log("VISO: Generating directory record set #%d:\n", i);
image_viso_log(viso->tf.log, "Generating directory record set #%d:\n", i);
/* Go through directories. */
dir = viso->root_dir;
@@ -1368,8 +1397,10 @@ next_dir:
if ((entry == eltorito_entry) || (entry == eltorito_dir))
goto next_entry;
cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path,
((dir_type == VISO_DIR_PARENT) ? ".." : ((dir_type < VISO_DIR_PARENT) ? "." : (i ? entry->basename : entry->name_short))));
image_viso_log(viso->tf.log, "[%08X] %s => %s\n", entry, dir->path,
((dir_type == VISO_DIR_PARENT) ? ".." :
((dir_type < VISO_DIR_PARENT) ? "." :
(i ? entry->basename : entry->name_short))));
/* Fill directory record. */
viso_fill_dir_record(data, entry, viso, dir_type);
@@ -1436,7 +1467,8 @@ next_entry:
/* Allocate entry map for sector->file lookups. */
size_t orig_sector_size = viso->sector_size;
while (1) {
cdrom_image_viso_log("VISO: Allocating entry map for %zu %zu-byte sectors\n", viso->entry_map_size, viso->sector_size);
image_viso_log(viso->tf.log, "Allocating entry map for %zu %zu-byte sectors\n",
viso->entry_map_size, viso->sector_size);
viso->entry_map = (viso_entry_t **) calloc(viso->entry_map_size, sizeof(viso_entry_t *));
if (viso->entry_map) {
/* Successfully allocated. */
@@ -1477,7 +1509,7 @@ next_entry:
viso->all_sectors = viso->metadata_sectors;
/* Go through files, assigning sectors to them. */
cdrom_image_viso_log("VISO: Assigning sectors to files:\n");
image_viso_log(viso->tf.log, "Assigning sectors to files:\n");
size_t base_factor = viso->sector_size / orig_sector_size;
viso_entry_t *prev_entry = viso->root_dir;
viso_entry_t **entry_map_p = viso->entry_map;
@@ -1522,7 +1554,8 @@ next_entry:
size_t size = entry->stats.st_size / viso->sector_size;
if (entry->stats.st_size % viso->sector_size)
size++; /* round up to the next sector */
cdrom_image_viso_log("[%08X] %s => %zu + %zu sectors\n", entry, entry->path, viso->all_sectors, size);
image_viso_log(viso->tf.log, "[%08X] %s => %zu + %zu sectors\n", entry,
entry->path, viso->all_sectors, size);
/* Allocate sectors to this file. */
viso->all_sectors += size;
@@ -1541,9 +1574,10 @@ next_entry:
viso_pwrite(data, viso->vol_size_offsets[i], 8, 1, viso->tf.fp);
/* Metadata processing is finished, read it back to memory. */
cdrom_image_viso_log("VISO: Reading back %zu %zu-byte sectors of metadata\n", viso->metadata_sectors, viso->sector_size);
image_viso_log(viso->tf.log, "Reading back %zu %zu-byte sectors of metadata\n",
viso->metadata_sectors, viso->sector_size);
viso->metadata = (uint8_t *) calloc(viso->metadata_sectors, viso->sector_size);
if (!viso->metadata)
if (viso->metadata == NULL)
goto end;
fseeko64(viso->tf.fp, 0, SEEK_SET);
size_t metadata_size = viso->metadata_sectors * viso->sector_size;
@@ -1554,7 +1588,7 @@ next_entry:
/* We no longer need the temporary file; close and delete it. */
fclose(viso->tf.fp);
viso->tf.fp = NULL;
#ifndef ENABLE_CDROM_IMAGE_VISO_LOG
#ifndef ENABLE_IMAGE_VISO_LOG
remove(nvr_path(viso->tf.fn));
#endif
@@ -1565,13 +1599,15 @@ end:
/* Set the function pointers. */
viso->tf.priv = viso;
if (!*error) {
cdrom_image_viso_log("VISO: Initialized\n");
image_viso_log(viso->tf.log, "Initialized\n");
viso->tf.read = viso_read;
viso->tf.get_length = viso_get_length;
viso->tf.close = viso_close;
return &viso->tf;
} else {
cdrom_image_viso_log("VISO: Initialization failed\n");
image_viso_log(viso->tf.log, "Initialization failed\n");
if (data)
free(data);
viso_close(&viso->tf);

View File

@@ -1,267 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* CD-ROM passthrough support.
*
*
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2023 TheCollector1995.
* Copyright 2023 Miran Grca.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/config.h>
#include <86box/path.h>
#include <86box/plat.h>
#include <86box/scsi_device.h>
#include <86box/cdrom.h>
#include <86box/plat_cdrom.h>
#ifdef ENABLE_CDROM_IOCTL_LOG
int cdrom_ioctl_do_log = ENABLE_CDROM_IOCTL_LOG;
void
cdrom_ioctl_log(const char *fmt, ...)
{
va_list ap;
if (cdrom_ioctl_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define cdrom_ioctl_log(fmt, ...)
#endif
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
of the audio while audio still plays. With an absolute conversion, the counter is fine. */
#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f)
static void
ioctl_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti)
{
TMSF tmsf;
plat_cdrom_get_audio_track_info(dev->local, end, track, &ti->number, &tmsf, &ti->attr);
ti->m = tmsf.min;
ti->s = tmsf.sec;
ti->f = tmsf.fr;
}
static void
ioctl_get_raw_track_info(cdrom_t *dev, int *num, raw_track_info_t *rti)
{
plat_cdrom_get_raw_track_info(dev->local, num, rti);
}
static void
ioctl_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc)
{
TMSF rel_pos;
TMSF abs_pos;
if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED)) {
const uint32_t trk = plat_cdrom_get_track_start(dev->local, lba, &subc->attr, &subc->track);
FRAMES_TO_MSF(lba + 150, &abs_pos.min, &abs_pos.sec, &abs_pos.fr);
/* Absolute position should be adjusted by 150, not the relative ones. */
FRAMES_TO_MSF(lba - trk, &rel_pos.min, &rel_pos.sec, &rel_pos.fr);
subc->index = 1;
} else
plat_cdrom_get_audio_sub(dev->local, lba, &subc->attr, &subc->track, &subc->index,
&rel_pos, &abs_pos);
subc->abs_m = abs_pos.min;
subc->abs_s = abs_pos.sec;
subc->abs_f = abs_pos.fr;
subc->rel_m = rel_pos.min;
subc->rel_s = rel_pos.sec;
subc->rel_f = rel_pos.fr;
cdrom_ioctl_log("ioctl_get_subchannel(): %02X, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n",
subc->attr, subc->track, subc->index, subc->abs_m, subc->abs_s, subc->abs_f,
subc->rel_m, subc->rel_s, subc->rel_f);
}
static int
ioctl_get_capacity(cdrom_t *dev)
{
int ret;
ret = plat_cdrom_get_last_block(dev->local);
cdrom_ioctl_log("GetCapacity=%x.\n", ret);
return ret;
}
static int
ioctl_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf)
{
int m;
int s;
int f;
if (dev->cd_status == CD_STATUS_DATA_ONLY)
return 0;
if (ismsf) {
m = (pos >> 16) & 0xff;
s = (pos >> 8) & 0xff;
f = pos & 0xff;
pos = MSFtoLBA(m, s, f) - 150;
}
/* GetTrack requires LBA. */
return plat_cdrom_is_track_audio(dev->local, pos);
}
static int
ioctl_is_track_pre(cdrom_t *dev, uint32_t lba)
{
return plat_cdrom_is_track_pre(dev->local, lba);
}
static int
ioctl_sector_size(cdrom_t *dev, uint32_t lba)
{
cdrom_ioctl_log("LBA=%x.\n", lba);
return plat_cdrom_get_sector_size(dev->local, lba);
}
static int
ioctl_read_sector(cdrom_t *dev, uint8_t *b, uint32_t lba)
{
cdrom_ioctl_log("cdrom_ioctl_read_sector(): Raw.\n");
return plat_cdrom_read_sector(dev->local, b, lba);
}
static int
ioctl_track_type(cdrom_t *dev, uint32_t lba)
{
int ret = CD_TRACK_UNK_DATA;
if (ioctl_is_track_audio(dev, lba, 0))
ret = CD_TRACK_AUDIO;
cdrom_ioctl_log("cdrom_ioctl_track_type(): %i\n", ret);
return ret;
}
static int
ioctl_ext_medium_changed(cdrom_t *dev)
{
int ret;
if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED))
ret = 0;
else
ret = plat_cdrom_ext_medium_changed(dev->local);
if (ret == 1) {
dev->cd_status = CD_STATUS_STOPPED;
dev->cdrom_capacity = ioctl_get_capacity(dev);
} else if (ret == -1)
dev->cd_status = CD_STATUS_EMPTY;
return ret;
}
static void
ioctl_exit(cdrom_t *dev)
{
cdrom_ioctl_log("CDROM: ioctl_exit(%s)\n", dev->image_path);
dev->cd_status = CD_STATUS_EMPTY;
plat_cdrom_close(dev->local);
dev->local = NULL;
dev->ops = NULL;
}
static const cdrom_ops_t cdrom_ioctl_ops = {
ioctl_get_track_info,
ioctl_get_raw_track_info,
ioctl_get_subchannel,
ioctl_is_track_pre,
ioctl_sector_size,
ioctl_read_sector,
ioctl_track_type,
ioctl_ext_medium_changed,
ioctl_exit
};
static int
cdrom_ioctl_open_abort(cdrom_t *dev)
{
cdrom_ioctl_close(dev);
dev->ops = NULL;
dev->image_path[0] = 0;
return 1;
}
int
cdrom_ioctl_open(cdrom_t *dev, const char *drv)
{
const char *actual_drv = &(drv[8]);
int local_size = plat_cdrom_get_local_size();
/* Make sure to not STRCPY if the two are pointing
at the same place. */
if (drv != dev->image_path)
strcpy(dev->image_path, drv);
/* Open the image. */
if (strstr(drv, "ioctl://") != drv)
return cdrom_ioctl_open_abort(dev);
cdrom_ioctl_log("actual_drv = %s\n", actual_drv);
if (dev->local == NULL)
dev->local = calloc(1, local_size);
int i = plat_cdrom_set_drive(dev->local, actual_drv);
if (!i)
return cdrom_ioctl_open_abort(dev);
/* All good, reset state. */
dev->cd_status = CD_STATUS_STOPPED;
dev->seek_pos = 0;
dev->cd_buflen = 0;
dev->cdrom_capacity = ioctl_get_capacity(dev);
cdrom_ioctl_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n",
dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity) << 11ULL);
/* Attach this handler to the drive. */
dev->ops = &cdrom_ioctl_ops;
return 0;
}
void
cdrom_ioctl_close(cdrom_t *dev)
{
cdrom_ioctl_log("CDROM: ioctl_close(%s)\n", dev->image_path);
if (dev && dev->ops && dev->ops->exit)
dev->ops->exit(dev);
}

View File

@@ -118,14 +118,6 @@ typedef struct mcd_t {
int newstat;
} mcd_t;
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
of the audio while audio still plays. With an absolute conversion, the counter is fine. */
#ifdef MSFtoLBA
#undef MSFtoLBA
#endif
#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f)
#define CD_BCD(x) (((x) % 10) | (((x) / 10) << 4))
#define CD_DCB(x) ((((x) &0xf0) >> 4) * 10 + ((x) &0x0f))