Files
86Box/src/include/86box/cdrom.h
2025-08-01 21:28:23 +02:00

487 lines
24 KiB
C

/*
* 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.
*
* Generic CD-ROM drive core header.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2019 Miran Grca.
*/
#ifndef EMU_CDROM_H
#define EMU_CDROM_H
#ifndef EMU_VERSION_H
#include <86box/version.h>
#endif
#define CDROM_NUM 8
#define CD_STATUS_EMPTY 0
#define CD_STATUS_DATA_ONLY 1
#define CD_STATUS_DVD 2
#define CD_STATUS_PAUSED 4
#define CD_STATUS_PLAYING 5
#define CD_STATUS_STOPPED 6
#define CD_STATUS_PLAYING_COMPLETED 7
#define CD_STATUS_HOLD 8
#define CD_STATUS_DVD_REJECTED 16
#define CD_STATUS_HAS_AUDIO 0xc
#define CD_STATUS_MASK 0x1f
/* Medium changed flag. */
#define CD_STATUS_TRANSITION 0x40
#define CD_STATUS_MEDIUM_CHANGED 0x80
#define CD_TRACK_UNK_DATA 0x04
#define CD_TRACK_NORMAL 0x00
#define CD_TRACK_AUDIO 0x08
#define CD_TRACK_CDI 0x10
#define CD_TRACK_XA 0x20
#define CD_TRACK_MODE_MASK 0x30
#define CD_TRACK_MODE2 0x04
#define CD_TRACK_MODE2_MASK 0x07
#define CD_TOC_NORMAL 0
#define CD_TOC_SESSION 1
#define CD_TOC_RAW 2
#define CD_IMAGE_HISTORY 10
#define CDROM_IMAGE 200
/* This is so that if/when this is changed to something else,
changing this one define will be enough. */
#define CDROM_EMPTY !dev->host_drive
#define DVD_LAYER_0_SECTORS 0x00210558ULL
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
#define CD_BUF_SIZE (16 * RAW_SECTOR_SIZE)
#define DATA_TRACK 0x14
#define AUDIO_TRACK 0x10
#define CD_FPS 75
#define _LUT_SIZE 0x100
#define FRAMES_TO_MSF(f, M, S, F) \
{ \
uint64_t value = f; \
*(F) = (value % CD_FPS) & 0xff; \
value /= CD_FPS; \
*(S) = (value % 60) & 0xff; \
value /= 60; \
*(M) = value & 0xff; \
}
#define MSF_TO_FRAMES(M, S, F) ((M) *60 * CD_FPS + (S) *CD_FPS + (F))
typedef struct SMSF {
uint16_t min;
uint8_t sec;
uint8_t fr;
} TMSF;
#ifdef __cplusplus
extern "C" {
#endif
enum {
CDROM_BUS_DISABLED = 0,
CDROM_BUS_PHILIPS = 1,
CDROM_BUS_SONY = 2,
CDROM_BUS_HITACHI = 3,
CDROM_BUS_MKE = 4,
CDROM_BUS_MITSUMI = 5,
CDROM_BUS_LPT = 6,
CDROM_BUS_ATAPI = 8,
CDROM_BUS_SCSI = 9,
CDROM_BUS_USB = 10
};
#define BUS_TYPE_MKE CDROM_BUS_MKE
#define BUS_TYPE_IDE CDROM_BUS_ATAPI
#define BUS_TYPE_SCSI CDROM_BUS_SCSI
#define BUS_TYPE_BOTH -2
#define BUS_TYPE_NONE -1
#define CDV EMU_VERSION_EX
static const struct cdrom_drive_types_s {
const char *vendor;
const char *model;
const char *revision;
const char *internal_name;
const int bus_type;
/* SCSI standard for SCSI (or both) devices, early for IDE. */
const int scsi_std;
const int speed;
const int inquiry_len;
const int caddy;
const int is_dvd;
const int transfer_max[4];
} cdrom_drive_types[] = {
{ EMU_NAME, "86B_CD", CDV, "86cd", BUS_TYPE_BOTH, 2, -1, 36, 0, 0, { 4, 2, 2, 5 } },
/* SCSI-1 / early ATAPI generic - second on purpose so the later variant is the default. */
{ EMU_NAME, "86B_CD", "1.00", "86cd100", BUS_TYPE_BOTH, 1, -1, 36, 1, 0, { 0, -1, -1, -1 } },
/* No difference from 86BOX CD-ROM, other than name - but enough people have requested such a name to warrant it. */
{ EMU_NAME, "86B_DVD", "5.00", "86dvd", BUS_TYPE_BOTH, 2, -1, 36, 0, 1, { 4, 2, 2, 5 } },
{ "ASUS", "CD-S500/A", "1.41", "asus_500", BUS_TYPE_IDE, 0, 50, 36, 0, 0, { 4, 2, 2, 2 } },
{ "ASUS", "CD-S520/A4", "1.32", "asus_520", BUS_TYPE_IDE, 0, 52, 36, 0, 0, { 4, 2, 2, 2 } },
{ "AZT", "CDA46802I", "1.15", "azt_cda", BUS_TYPE_IDE, 0, 4, 36, 0, 0, { 3, 0, 0, 0 } },
{ "BTC", "CD-ROM BCD36XH", "U1.0", "btc_36xh", BUS_TYPE_IDE, 0, 36, 36, 0, 0, { 4, 2, 2, -1 } },
{ "GOLDSTAR", "CRD-8160B", "3.14", "goldstar", BUS_TYPE_IDE, 0, 16, 36, 0, 0, { 4, 2, 2, -1 } },
/* TODO: Find an IDENTIFY and/or INQUIRY dump. */
{ "GOLDSTAR", "GCD-R560B", "1.00", "goldstar", BUS_TYPE_IDE, 0, 6, 36, 0, 0, { 4, 2, 2, -1 } },
{ "HITACHI", "CDR-8130", "0020", "hitachi_r8130", BUS_TYPE_IDE, 0, 16, 36, 0, 0, { 4, 2, 2, -1 } },
{ "HITACHI", "GD-7500", "A1 ", "hitachi_7500", BUS_TYPE_IDE, 0, 40, 36, 0, 0, { 4, 2, 2, 2 } }, /* DVD. */
{ "HL-DT-ST", "CD-ROM GCR-8526B", "1.01", "hldtst_8526b", BUS_TYPE_IDE, 0, 52, 36, 0, 0, { 4, 2, 2, 2 } },
{ "HL-DT-ST", "DVDRAM GSA-4160", "A302", "hldtst_4160", BUS_TYPE_IDE, 0, 40, 36, 0, 0, { 4, 2, 2, 2 } },
{ "KENWOOD", "CD-ROM UCR-421", "208E", "kenwood_421", BUS_TYPE_IDE, 0, 72, 36, 0, 0, { 4, 2, 2, 4 } },
/*
This is a laptop/notebook drive, as is also evident from the name:
CRN = Notebook, CRD = Desktop.
*/
{ "LG", "CD-ROM CRN-8245B", "1.30", "lg_8245b", BUS_TYPE_IDE, 0, 24, 36, 0, 0, { 4, 2, 2, -1 } },
{ "LG", "CD-ROM CRD-8322B", "1.06", "lg_8322b", BUS_TYPE_IDE, 0, 32, 36, 0, 0, { 4, 2, 2, -1 } },
/* Nothing on Google, deduced 48x from the name. */
{ "LITE-ON", "LTN48125S", "1S07", "liteon_48125s", BUS_TYPE_IDE, 0, 48, 36, 0, 0, { 4, 2, 2, 2 } },
/* Confirmed to be 52x, was the basis for deducing the other one's speed. */
{ "LITE-ON", "LTN526D", "YSR5", "liteon_526d", BUS_TYPE_IDE, 0, 52, 36, 0, 0, { 4, 2, 2, 2 } },
{ "MATSHITA", "CD-ROM CR-583", "1.07", "matshita_583", BUS_TYPE_IDE, 0, 8, 36, 0, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CD-ROM CR-585", "Z18P", "matshita_585", BUS_TYPE_IDE, 0, 24, 36, 0, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CD-ROM CR-587", "7S13", "matshita_587", BUS_TYPE_IDE, 0, 24, 36, 0, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CD-ROM CR-588", "LS15", "matshita_588", BUS_TYPE_IDE, 0, 32, 36, 0, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CR-571", "1.0e", "matshita_571", BUS_TYPE_IDE, 0, 2, 36, 0, 0, { 0, -1, -1, -1 } },
{ "MATSHITA", "CR-572", "1.0j", "matshita_572", BUS_TYPE_IDE, 0, 4, 36, 0, 0, { 0, -1, -1, -1 } },
{ "MITSUMI", "CRMC-FX4820T", "D02A", "mitsumi_4820t", BUS_TYPE_IDE, 0, 48, 36, 0, 0, { 4, 2, 2, 2 } },
/* TODO: Find an IDENTIFY and/or INQUIRY dump. */
{ "MITSUMI", "CRMC-FX810T4", "????", "mitsumi_810t4", BUS_TYPE_IDE, 0, 8, 36, 0, 0, { 4, 2, 2, -1 } },
{ "NEC", "CD-ROM DRIVE:260", "1.00", "nec_260_early", BUS_TYPE_IDE, 1, 2, 36, 1, 0, { 0, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:260", "1.01", "nec_260", BUS_TYPE_IDE, 1, 4, 36, 1, 0, { 0, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:273", "4.20", "nec_273", BUS_TYPE_IDE, 0, 4, 36, 0, 0, { 0, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:280", "1.05", "nec_280_early", BUS_TYPE_IDE, 0, 6, 36, 1, 0, { 4, 2, 2, -1 } },
{ "NEC", "CD-ROM DRIVE:280", "3.08", "nec_280", BUS_TYPE_IDE, 0, 8, 36, 1, 0, { 4, 2, 2, -1 } },
{ "NEC", "CDR-1300A", "1.05", "nec_1300a", BUS_TYPE_IDE, 0, 6, 36, 0, 0, { 4, 2, 2, -1 } },
{ "NEC", "CDR-1900A", "1.00", "nec_1900a", BUS_TYPE_IDE, 0, 32, 36, 0, 0, { 4, 2, 2, -1 } },
{ "PHILIPS", "CD-ROM PCA403CD", "U31P", "philips_403", BUS_TYPE_IDE, 0, 40, 36, 0, 0, { 4, 2, 2, -1 } },
{ "SONY", "CD-ROM CDU76", "1.0i", "sony_76", BUS_TYPE_IDE, 0, 4, 36, 0, 0, { 2, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU311", "3.0h", "sony_311", BUS_TYPE_IDE, 0, 8, 36, 0, 0, { 3, 2, 1, -1 } },
{ "SONY", "CD-ROM CDU5225", "NYS4", "sony_5225", BUS_TYPE_IDE, 0, 52, 36, 0, 0, { 4, 2, 2, 4 } },
{ "TEAC", "CD-516E", "1.0G", "teac_516e", BUS_TYPE_IDE, 0, 16, 36, 0, 0, { 3, 2, 2, -1 } },
{ "TEAC", "CD-524EA", "3.0D", "teac_524ea", BUS_TYPE_IDE, 0, 24, 36, 0, 0, { 3, 2, 2, -1 } },
{ "TEAC", "CD-532E", "2.0A", "teac_532e", BUS_TYPE_IDE, 0, 32, 36, 0, 0, { 3, 2, 2, -1 } },
{ "TOSHIBA", "CD-ROM XM-5302TA", "0305", "toshiba_5302ta", BUS_TYPE_IDE, 0, 4, 96, 0, 0, { 0, -1, -1, -1 } },
{ "TOSHIBA", "CD-ROM XM-5702B", "TA70", "toshiba_5702b", BUS_TYPE_IDE, 0, 12, 96, 0, 0, { 3, 2, 1, -1 } },
{ "TOSHIBA", "CD-ROM XM-6202B", "1512", "toshiba_6202b", BUS_TYPE_IDE, 0, 32, 96, 0, 0, { 4, 2, 2, -1 } },
{ "TOSHIBA", "CD-ROM XM-6402B", "1008", "toshiba_6402b", BUS_TYPE_IDE, 0, 32, 96, 0, 0, { 4, 2, 2, 2 } },
{ "TOSHIBA", "CD-ROM XM-6702B", "1007", "toshiba_6720b", BUS_TYPE_IDE, 0, 48, 96, 0, 0, { 4, 2, 2, 2 } },
{ "TOSHIBA", "DVD-ROM SD-M1802", "1051", "toshiba_m1802", BUS_TYPE_IDE, 0, 48, 96, 0, 1, { 4, 2, 2, 2 } },
{ "CHINON", "CD-ROM CDS-431", "H42 ", "chinon_431", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "CHINON", "CD-ROM CDX-435", "M62 ", "chinon_435", BUS_TYPE_SCSI, 1, 2, 36, 1, 0, { -1, -1, -1, -1 } },
{ "DEC", "RRD45 (C) DEC", "0436", "dec_45", BUS_TYPE_SCSI, 1, 4, 36, 0, 0, { -1, -1, -1, -1 } },
{ "MATSHITA", "CD-ROM CR-501", "1.0b", "matshita_501", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:25", "1.0a", "nec_25", BUS_TYPE_SCSI, 1, 2, 36, 0, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:38", "1.00", "nec_38", BUS_TYPE_SCSI, 2, 1, 36, 0, 0, { -1, -1, -1, -1 } },
/* The speed of the following two is guesswork based on the CDR-74. */
{ "NEC", "CD-ROM DRIVE:75", "1.03", "nec_75", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:77", "1.06", "nec_77", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:211", "1.00", "nec_211", BUS_TYPE_SCSI, 2, 3, 36, 0, 0, { -1, -1, -1, -1 } },
/* The speed of the following two is guesswork based on the CDR-400. */
{ "NEC", "CD-ROM DRIVE:464", "1.05", "nec_464", BUS_TYPE_SCSI, 2, 3, 36, 0, 0, { -1, -1, -1, -1 } },
/* The speed of the following two is guesswork based on the name. */
{ "ShinaKen", "CD-ROM DM-3x1S", "1.04", "shinaken_3x1s", BUS_TYPE_SCSI, 1, 3, 36, 0, 0, { -1, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU-541", "1.0i", "sony_541", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU-561", "1.8k", "sony_561", BUS_TYPE_SCSI, 2, 2, 36, 1, 0, { -1, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU-76S", "1.00", "sony_76s", BUS_TYPE_SCSI, 2, 4, 36, 0, 0, { -1, -1, -1, -1 } },
{ "PHILIPS", "CDD2600", "1.07", "philips_2600", BUS_TYPE_SCSI, 2, 6, 36, 0, 0, { -1, -1, -1, -1 } },
/* NOTE: The real thing is a CD changer drive! */
{ "PIONEER", "CD-ROM DRM-604X", "2403", "pioneer_604x", BUS_TYPE_SCSI, 2, 4, 47, 0, 0, { -1, -1, -1, -1 } },
{ "PLEXTOR", "CD-ROM PX-32TS", "1.03", "plextor_32ts", BUS_TYPE_SCSI, 2, 32, 36, 0, 0, { -1, -1, -1, -1 } },
/* The speed of the following two is guesswork based on the R55S. */
{ "TEAC", "CD 50", "1.00", "teac_50", BUS_TYPE_SCSI, 2, 4, 36, 1, 0, { -1, -1, -1, -1 } },
{ "TEAC", "CD-ROM R55S", "1.0R", "teac_55s", BUS_TYPE_SCSI, 2, 4, 36, 0, 0, { -1, -1, -1, -1 } },
/* Texel is Plextor according to Plextor's own EU website. */
{ "TEXEL", "CD-ROM DM-3024", "1.00", "texel_3024", BUS_TYPE_SCSI, 2, 2, 36, 1, 0, { -1, -1, -1, -1 } },
/*
Unusual 2.23x according to Google, I'm rounding it upwards to 3x.
Assumed caddy based on the DM-3024.
*/
{ "TEXEL", "CD-ROM DM-3028", "1.06", "texel_3028", BUS_TYPE_SCSI, 2, 3, 36, 1, 0, { -1, -1, -1, -1 } }, /* Caddy. */
/*
The characteristics are a complete guesswork because I can't find
this one on Google.
Also, INQUIRY length is always 96 on these Toshiba drives.
*/
{ "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "toshiba_xm", BUS_TYPE_SCSI, 2, 2, 96, 0, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "TOSHIBA", "CD-ROM XM-3201B", "3232", "toshiba_3201b", BUS_TYPE_SCSI, 1, 1, 96, 1, 0, { -1, -1, -1, -1 } }, /* Caddy. */
{ "TOSHIBA", "CD-ROM XM-3301TA", "0272", "toshiba_3301ta", BUS_TYPE_SCSI, 2, 2, 96, 0, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "TOSHIBA", "CD-ROM XM-5701TA", "3136", "toshiba_5701a", BUS_TYPE_SCSI, 2, 12, 96, 0, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "TOSHIBA", "DVD-ROM SD-M1401", "1008", "toshiba_m1401", BUS_TYPE_SCSI, 2, 40, 96, 0, 1, { -1, -1, -1, -1 } }, /* Tray. */
{ "MATSHITA", "CR-562", "0.75", "cr562", BUS_TYPE_MKE , 0, 2, 0, 0, 0, { -1, -1, -1, -1 } },
{ "MATSHITA", "CR-562", "0.80", "cr562_080", BUS_TYPE_MKE , 0, 2, 0, 0, 0, { -1, -1, -1, -1 } },
{ "MATSHITA", "CR-563", "0.75", "cr563", BUS_TYPE_MKE , 0, 2, 0, 0, 0, { -1, -1, -1, -1 } },
{ "MATSHITA", "CR-563", "0.80", "cr563_080", BUS_TYPE_MKE , 0, 2, 0, 0, 0, { -1, -1, -1, -1 } },
{ "", "", "", "", BUS_TYPE_NONE, 0, -1, 0, 0, 0, { -1, -1, -1, -1 } }
};
/* To shut up the GCC compilers. */
struct cdrom;
typedef struct subchannel_t {
uint8_t attr;
uint8_t track;
uint8_t index;
uint8_t abs_m;
uint8_t abs_s;
uint8_t abs_f;
uint8_t rel_m;
uint8_t rel_s;
uint8_t rel_f;
} subchannel_t;
typedef struct track_info_t {
int number;
uint8_t attr;
uint8_t m;
uint8_t s;
uint8_t f;
} track_info_t;
typedef struct raw_track_info_t {
uint8_t session;
uint8_t adr_ctl;
uint8_t tno;
uint8_t point;
uint8_t m;
uint8_t s;
uint8_t f;
uint8_t zero;
uint8_t pm;
uint8_t ps;
uint8_t pf;
} raw_track_info_t;
/* Define the various CD-ROM drive operations (ops). */
typedef struct cdrom_ops_t {
int (*get_track_info)(const void *local, const uint32_t track,
const int end, track_info_t *ti);
void (*get_raw_track_info)(const void *local, int *num,
uint8_t *rti);
int (*is_track_pre)(const void *local, const uint32_t sector);
int (*read_sector)(const void *local, uint8_t *buffer,
const uint32_t sector);
uint8_t (*get_track_type)(const void *local, const uint32_t sector);
uint32_t (*get_last_block)(const void *local);
int (*read_dvd_structure)(const void *local, const uint8_t layer,
const uint8_t format, uint8_t *buffer,
uint32_t *info);
int (*is_dvd)(const void *local);
int (*has_audio)(const void *local);
int (*is_empty)(const void *local);
void (*close)(void *local);
void (*load)(const void *local);
} cdrom_ops_t;
typedef struct cdrom {
uint8_t id;
union {
uint8_t res;
uint8_t res0; /* Reserved for other ID's. */
uint8_t mke_channel;
uint8_t ide_channel;
uint8_t scsi_device_id;
};
uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */
uint8_t bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
uint8_t cd_status; /* Struct variable reserved for
media status. */
uint8_t speed;
uint8_t cur_speed;
void *priv;
char image_path[1024];
char prev_image_path[1280];
uint32_t sound_on;
uint32_t cdrom_capacity;
uint32_t seek_pos;
uint32_t seek_diff;
uint32_t cd_end;
uint32_t type;
uint32_t sector_size;
uint32_t inv_field;
int32_t cached_sector;
int32_t cd_buflen;
int32_t sony_msf;
int32_t real_speed;
int32_t is_early;
int32_t is_nec;
int32_t is_bcd;
int32_t cdrom_sector_size;
const cdrom_ops_t *ops;
char *image_history[CD_IMAGE_HISTORY];
void *local;
void *log;
void (*insert)(void *priv);
void (*close)(void *priv);
uint32_t (*get_volume)(void *p, int channel);
uint32_t (*get_channel)(void *p, int channel);
int16_t cd_buffer[CD_BUF_SIZE];
uint8_t subch_buffer[96];
/* Needs some extra breathing space in case of overflows. */
uint8_t raw_buffer[2][4096];
uint8_t extra_buffer[296];
int32_t is_chinon;
int32_t is_pioneer;
int32_t is_plextor;
int32_t is_sony;
int32_t is_toshiba;
int32_t c2_first;
int32_t cur_buf;
/* Only used on Windows hosts for disc change notifications. */
uint8_t host_letter;
uint8_t mode2;
uint8_t _F_LUT[_LUT_SIZE];
uint8_t _B_LUT[_LUT_SIZE];
uint8_t p_parity[172];
uint8_t q_parity[104];
} cdrom_t;
extern cdrom_t cdrom[CDROM_NUM];
#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f)
static __inline int
bin2bcd(int x)
{
return (x % 10) | ((x / 10) << 4);
}
static __inline int
bcd2bin(int x)
{
return (x >> 4) * 10 + (x & 0x0f);
}
extern char *cdrom_get_vendor(const int type);
extern void cdrom_get_model(const int type, char *name, const int id);
extern char *cdrom_get_revision(const int type);
extern int cdrom_get_scsi_std(const int type);
extern int cdrom_is_early(const int type);
extern int cdrom_is_dvd(const int type);
extern int cdrom_is_generic(const int type);
extern int cdrom_is_caddy(const int type);
extern int cdrom_get_speed(const int type);
extern int cdrom_get_inquiry_len(const int type);
extern int cdrom_has_dma(const int type);
extern int cdrom_get_transfer_max(const int type, const int mode);
extern int cdrom_get_type_count(void);
extern void cdrom_generate_name_mke(const int type, char *name);
extern void cdrom_get_identify_model(const int type, char *name, const int id);
extern void cdrom_get_name(const int type, char *name);
extern char *cdrom_get_internal_name(const int type);
extern int cdrom_get_from_internal_name(const char *s);
/* TODO: Configuration migration, remove when no longer needed. */
extern int cdrom_get_from_name(const char *s);
extern void cdrom_set_type(const int model, const int type);
extern int cdrom_get_type(const int model);
extern int cdrom_lba_to_msf_accurate(const int lba);
extern void cdrom_interleave_subch(uint8_t *d, const uint8_t *s);
extern double cdrom_seek_time(const cdrom_t *dev);
extern void cdrom_stop(cdrom_t *dev);
extern void cdrom_seek(cdrom_t *dev, const uint32_t pos, const uint8_t vendor_type);
extern int cdrom_is_pre(const cdrom_t *dev, const uint32_t lba);
extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, const int len);
extern uint8_t cdrom_audio_play(cdrom_t *dev, const uint32_t pos, const uint32_t len, const int ismsf);
extern uint8_t cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos,
const int type, const uint8_t playbit);
extern uint8_t cdrom_audio_track_search_pioneer(cdrom_t *dev, const uint32_t pos, const uint8_t playbit);
extern uint8_t cdrom_audio_play_pioneer(cdrom_t *dev, const uint32_t pos);
extern uint8_t cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type);
extern uint8_t cdrom_audio_scan(cdrom_t *dev, const uint32_t pos);
extern void cdrom_audio_pause_resume(cdrom_t *dev, const uint8_t resume);
extern uint8_t cdrom_get_current_status(const cdrom_t *dev);
extern void cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, const int msf);
extern void cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, const int msf);
extern uint8_t cdrom_get_audio_status_pioneer(cdrom_t *dev, uint8_t *b);
extern uint8_t cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, const int msf);
extern void cdrom_get_current_subcodeq(cdrom_t *dev, uint8_t *b);
extern uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b);
extern int cdrom_read_toc(const cdrom_t *dev, uint8_t *b, const int type,
const uint8_t start_track, const int msf, const int max_len);
extern int cdrom_read_toc_sony(const cdrom_t *dev, uint8_t *b, const uint8_t start_track,
const int msf, const int max_len);
#ifdef USE_CDROM_MITSUMI
extern void cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf);
extern void cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode);
extern uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len);
#endif
extern uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b,
const uint8_t track, const int type);
extern int cdrom_is_track_audio(cdrom_t *dev, const int sector, const int ismsf,
int cdrom_sector_type, const uint8_t vendor_type);
extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf,
int cdrom_sector_type, const int cdrom_sector_flags,
int *len, const uint8_t vendor_type);
extern int cdrom_read_dvd_structure(const cdrom_t *dev, const uint8_t layer, const uint8_t format,
uint8_t *buffer, uint32_t *info);
extern void cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer);
extern int cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer);
extern uint8_t cdrom_get_current_mode(cdrom_t *dev);
extern void cdrom_set_empty(cdrom_t *dev);
extern void cdrom_update_status(cdrom_t *dev);
extern int cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert);
extern void cdrom_global_init(void);
extern void cdrom_hard_reset(void);
extern void cdrom_close(void);
extern void cdrom_insert(const uint8_t id);
extern void cdrom_exit(const uint8_t id);
extern int cdrom_is_empty(const uint8_t id);
extern void cdrom_eject(const uint8_t id);
extern void cdrom_reload(const uint8_t id);
extern void cdrom_compute_ecc_block(cdrom_t *dev, uint8_t *parity, const uint8_t *data,
uint32_t major_count, uint32_t minor_count,
uint32_t major_mult, uint32_t minor_inc, int m2f1);
extern unsigned long cdrom_crc32(unsigned long crc, const unsigned char *buf,
size_t len);
extern int cdrom_assigned_letters;
#ifdef __cplusplus
}
#endif
#endif /*EMU_CDROM_H*/