Compare commits
11 Commits
4f0cdcad0b
...
2b3ceea4f5
| Author | SHA1 | Date | |
|---|---|---|---|
|
2b3ceea4f5
|
|||
|
6498914df9
|
|||
|
864bd03c99
|
|||
|
ea339fb2ec
|
|||
|
7efcbddc80
|
|||
|
2d20d55a65
|
|||
|
f534b35257
|
|||
|
6029b563e2
|
|||
|
cc570f2a9c
|
|||
|
49f462c3cf
|
|||
|
c33e98d7e0
|
@@ -24,6 +24,7 @@ add_library(cdrom OBJECT
|
||||
cdrom_image.c
|
||||
cdrom_image_viso.c
|
||||
cdrom_mke.c
|
||||
cdrom_image_writable.c
|
||||
)
|
||||
if(NOT WIN32)
|
||||
target_include_directories(86Box PRIVATE PkgConfig::SNDFILE)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*
|
||||
* Copyright 2018-2021 Miran Grca.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#ifdef ENABLE_CDROM_LOG
|
||||
#include <stdarg.h>
|
||||
@@ -26,6 +27,7 @@
|
||||
#include <86box/config.h>
|
||||
#include <86box/cdrom.h>
|
||||
#include <86box/cdrom_image.h>
|
||||
#include <86box/cdrom_image_writable.h>
|
||||
#include <86box/cdrom_interface.h>
|
||||
#ifdef USE_CDROM_MITSUMI
|
||||
#include <86box/cdrom_mitsumi.h>
|
||||
@@ -2147,6 +2149,65 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cdrom_read_pma(const cdrom_t *dev, uint8_t *b, const int max_len)
|
||||
{
|
||||
if (max_len < 4)
|
||||
return -1;
|
||||
|
||||
// This is exactly what a blank CD-R returns, no PMA, seems only CD-RWs have PMA?
|
||||
b[0] = 0x00; /* PMA Data Length (MSB) */
|
||||
b[1] = 0x02; /* PMA Data Length (LSB) */
|
||||
b[2] = 0x00; /* Reserved */
|
||||
b[3] = 0x00; /* Reserved */
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int
|
||||
cdrom_read_atip(const cdrom_t *dev, uint8_t *b, const int max_len)
|
||||
{
|
||||
if (max_len < 28)
|
||||
return -1;
|
||||
|
||||
b[ 0] = 0x00; /* ATIP Data Length (MSB) */
|
||||
b[ 1] = 0x1a; /* ATIP Data Length (LSB) */
|
||||
b[ 2] = 0x00; /* Reserved */
|
||||
b[ 3] = 0x00; /* Reserved */
|
||||
// Special Information 1
|
||||
b[ 4] = 0xd0; /* Indicative Target Writing Power, Reference Speed */
|
||||
b[ 5] = 0x00; /* URU */
|
||||
b[ 6] = 0x98; /* 1, Disc Type, Disc Sub-Type, A1 Valid, A2 Valid, A3 Valid*/
|
||||
b[ 7] = 0x00; /* Reserved*/
|
||||
// Special Information 2
|
||||
b[ 8] = 0x61; /* ATIP Start Time of Lead-in (Min) */
|
||||
b[ 9] = 0x1a; /* ATIP Start Time of Lead-in (Sec) */
|
||||
b[10] = 0x42; /* ATIP Start Time of Lead-in (Frame) */
|
||||
b[11] = 0x00; /* Reserved */
|
||||
// Special Information 3
|
||||
b[12] = 0x4f; /* ATIP Last Possible Start of Lead-out (Min) */
|
||||
b[13] = 0x3b; /* ATIP Last Possible Start of Lead-out (Sec) */
|
||||
b[14] = 0x47; /* ATIP Last Possible Start of Lead-out (Frame) */
|
||||
b[15] = 0x00; /* Reserved */
|
||||
// Additional Information 1
|
||||
b[16] = 0x00; /* A1 Values */
|
||||
b[17] = 0x00; /* A1 Values */
|
||||
b[18] = 0x80; /* A1 Values */
|
||||
b[19] = 0x00; /* Reserved */
|
||||
// Additional Information 2
|
||||
b[20] = 0x00; /* A2 Values */
|
||||
b[21] = 0x80; /* A2 Values */
|
||||
b[22] = 0x00; /* A2 Values */
|
||||
b[23] = 0x00; /* Reserved */
|
||||
// Additional Information 3
|
||||
b[24] = 0x00; /* A3 Values */
|
||||
b[25] = 0x80; /* A3 Values */
|
||||
b[26] = 0x80; /* A3 Values */
|
||||
b[27] = 0x00; /* Reserved */
|
||||
|
||||
return 28;
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -2740,6 +2801,45 @@ cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer)
|
||||
int ls_last = 0;
|
||||
int t_b0 = -1;
|
||||
|
||||
if (dev->blank_media == CD_BLANK_CDR) {
|
||||
memset(buffer, 0x00, 34);
|
||||
|
||||
buffer[ 0] = 0x00; /* Disc Information Length (MSB) */
|
||||
buffer[ 1] = 0x20; /* Disc Information Lenght (LSB) */
|
||||
buffer[ 2] = 0x00; /* Reserved, Erasable, State of Last Session, Disc Status */
|
||||
buffer[ 3] = 0x01; /* Number of First Track on Disc */
|
||||
buffer[ 4] = 0x01; /* Number of Sessions (LSB) */
|
||||
buffer[ 5] = 0x01; /* First track number in last session (LSB) */
|
||||
buffer[ 6] = 0x01; /* Last track number in last session (LSB) */
|
||||
buffer[ 7] = 0x00; /* DID_V, DBC_V, URU, DAC_V, Reserved, Dbit, BG format Status */
|
||||
buffer[ 8] = 0xff; /* Disc type */
|
||||
buffer[ 9] = 0x00; /* Number Of Sessions (MSB) */
|
||||
buffer[10] = 0x00; /* First Track Number in Last Session (MSB) */
|
||||
buffer[11] = 0x00; /* Last Track Number in Last Session (MSB) */
|
||||
buffer[12] = 0x00; /* Disc identification (MSB...) */
|
||||
buffer[13] = 0x00; /* ... */
|
||||
buffer[14] = 0x00; /* ... */
|
||||
buffer[15] = 0x00; /* Disc identification (...LSB) */
|
||||
buffer[16] = 0x00; /* Last session Lead-In Start Address (MSB...) */
|
||||
buffer[17] = 0x61; /* ... */
|
||||
buffer[18] = 0x1a; /* ... */
|
||||
buffer[19] = 0x42; /* Last session Lead-In Start Address (...LSB) */
|
||||
buffer[20] = 0x00; /* Last Possible Start Time for Start of Lead-out (MSB) */
|
||||
buffer[21] = 0x4f; /* ... */
|
||||
buffer[22] = 0x3b; /* ... */
|
||||
buffer[23] = 0x47; /* Last Possible Start Time for Start of Lead-out (...LSB) */
|
||||
buffer[24] = 0x00; /* Disc barcode (MSB...) */
|
||||
buffer[25] = 0x00; /* ... */
|
||||
buffer[26] = 0x00; /* ... */
|
||||
buffer[27] = 0x00; /* ... */
|
||||
buffer[28] = 0x00; /* ... */
|
||||
buffer[29] = 0x00; /* ... */
|
||||
buffer[30] = 0x00; /* ... */
|
||||
buffer[31] = 0x00; /* Disc barcode (...LSB) */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dev->ops->get_raw_track_info(dev->local, &num, rti);
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
@@ -2996,6 +3096,37 @@ cdrom_update_status(cdrom_t *dev)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cdrom_insert_blank(cdrom_t *dev, const char *fn)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
// Create new image
|
||||
dev->local = wimage_open(dev, dev->image_path);
|
||||
|
||||
// Clear cached sectors
|
||||
dev->cached_sector = -1;
|
||||
|
||||
// If new image could not be created
|
||||
if (dev->local == NULL) {
|
||||
dev->ops = NULL;
|
||||
dev->image_path[0] = 0;
|
||||
|
||||
ret = 1;
|
||||
} else {
|
||||
// All looking good, reset state
|
||||
dev->seek_pos = 0;
|
||||
dev->cd_buflen = 0;
|
||||
dev->cd_status = CD_STATUS_DATA_ONLY;
|
||||
dev->blank_media = CD_BLANK_CDR;
|
||||
dev->cdrom_capacity = 0;
|
||||
cdrom_log(dev->log, "Blank CD-R created\n");
|
||||
cdrom_insert(dev->id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert)
|
||||
{
|
||||
@@ -3092,6 +3223,7 @@ cdrom_hard_reset(void)
|
||||
dev->is_chinon = !strcmp(vendor, "CHINON");
|
||||
dev->is_pioneer = !strcmp(vendor, "PIONEER");
|
||||
dev->is_plextor = !strcmp(vendor, "PLEXTOR");
|
||||
dev->is_yamaha = !strcmp(vendor, "YAMAHA");
|
||||
dev->is_sony = (dev->bus_type == CDROM_BUS_SCSI) &&
|
||||
(!strcmp(vendor, "DEC") ||
|
||||
!strcmp(vendor, "ShinaKen") ||
|
||||
|
||||
197
src/cdrom/cdrom_image_writable.c
Normal file
197
src/cdrom/cdrom_image_writable.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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-R(W) writable image file handling module.
|
||||
*
|
||||
* Authors: Nat Portillo, <claunia@claunia.com>
|
||||
*
|
||||
* Copyright 2025 Nat Portillo.
|
||||
*/
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef ENABLE_IMAGE_LOG
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/log.h>
|
||||
#include <86box/cdrom.h>
|
||||
#include <86box/cdrom_image_writable.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#define MAX_LINE_LENGTH 512
|
||||
#define MAX_FILENAME_LENGTH 256
|
||||
#define CROSS_LEN 512
|
||||
|
||||
static char temp_keyword[1024];
|
||||
|
||||
typedef struct track_index_t {
|
||||
int64_t start;
|
||||
uint64_t length;
|
||||
uint64_t file_start;
|
||||
uint64_t file_length;
|
||||
wtrack_file_t *file;
|
||||
} track_index_t;
|
||||
|
||||
typedef struct track_t {
|
||||
uint8_t session;
|
||||
uint8_t attr;
|
||||
uint8_t tno;
|
||||
uint8_t point;
|
||||
uint8_t extra[4];
|
||||
uint8_t mode;
|
||||
uint8_t form;
|
||||
uint8_t subch_type;
|
||||
uint8_t skip;
|
||||
uint8_t max_index;
|
||||
uint32_t sector_size;
|
||||
track_index_t idx[100];
|
||||
} track_t;
|
||||
|
||||
typedef struct cd_image_t {
|
||||
cdrom_t *dev;
|
||||
void *log;
|
||||
int has_audio;
|
||||
int32_t tracks_num;
|
||||
track_t *tracks;
|
||||
} cd_image_t;
|
||||
|
||||
#ifdef ENABLE_IMAGE_LOG
|
||||
int image_do_log = ENABLE_IMAGE_LOG;
|
||||
|
||||
void
|
||||
image_log(void *priv, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (image_do_log) {
|
||||
va_start(ap, fmt);
|
||||
log_out(priv, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
static char *cit[4] = { "SPECIAL", "NONE", "ZERO", "NORMAL" };
|
||||
#else
|
||||
# define image_log(priv, fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
wimage_get_track_info(const void *local, const uint32_t track,
|
||||
const int end, track_info_t *ti)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
wimage_get_raw_track_info(const void *local, int *num, uint8_t *buffer)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
}
|
||||
|
||||
static int
|
||||
wimage_is_track_pre(const void *local, const uint32_t sector)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
wimage_read_sector(const void *local, uint8_t *buffer,
|
||||
const uint32_t sector)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
wimage_get_track_type(const void *local, const uint32_t sector)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
wimage_get_last_block(const void *local)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wimage_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t format,
|
||||
uint8_t *buffer, uint32_t *info)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
wimage_is_dvd(const void *local)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wimage_has_audio(const void *local)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
wimage_close(void *local)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
}
|
||||
|
||||
static const cdrom_ops_t image_ops = {
|
||||
wimage_get_track_info,
|
||||
wimage_get_raw_track_info,
|
||||
wimage_is_track_pre,
|
||||
wimage_read_sector,
|
||||
wimage_get_track_type,
|
||||
wimage_get_last_block,
|
||||
wimage_read_dvd_structure,
|
||||
wimage_is_dvd,
|
||||
wimage_has_audio,
|
||||
NULL,
|
||||
wimage_close,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Public functions. */
|
||||
void *
|
||||
wimage_open(cdrom_t *dev, const char *path)
|
||||
{
|
||||
cd_image_t *img = (cd_image_t *) calloc(1, sizeof(cd_image_t));
|
||||
|
||||
dev->ops = &image_ops;
|
||||
|
||||
// TODO: Not implemented
|
||||
|
||||
return img;
|
||||
}
|
||||
@@ -31,7 +31,10 @@
|
||||
#define CD_STATUS_HOLD 8
|
||||
#define CD_STATUS_DVD_REJECTED 16
|
||||
#define CD_STATUS_HAS_AUDIO 0xc
|
||||
#define CD_STATUS_MASK 0x1f
|
||||
#define CD_STATUS_MASK 0x2f
|
||||
|
||||
#define CD_BLANK_NOT 0x00
|
||||
#define CD_BLANK_CDR 0x01
|
||||
|
||||
/* Medium changed flag. */
|
||||
#define CD_STATUS_TRANSITION 0x40
|
||||
@@ -184,6 +187,7 @@ static const struct cdrom_drive_types_s {
|
||||
{ "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 } },
|
||||
{ "YAMAHA", "CRW8424E", "1.0g", "yamaha_crw8424", BUS_TYPE_IDE, 0, 24, 36, 0, 0, { 4, 2, 2, -1 } },
|
||||
{ "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 } },
|
||||
@@ -307,6 +311,7 @@ typedef struct cdrom {
|
||||
Bit 1 = DMA supportd. */
|
||||
uint8_t cd_status; /* Struct variable reserved for
|
||||
media status. */
|
||||
uint8_t blank_media;
|
||||
uint8_t speed;
|
||||
uint8_t cur_speed;
|
||||
|
||||
@@ -343,6 +348,7 @@ typedef struct cdrom {
|
||||
|
||||
void (*insert)(void *priv);
|
||||
void (*close)(void *priv);
|
||||
void (*insert_blank)(void *priv);
|
||||
uint32_t (*get_volume)(void *p, int channel);
|
||||
uint32_t (*get_channel)(void *p, int channel);
|
||||
|
||||
@@ -359,6 +365,7 @@ typedef struct cdrom {
|
||||
int32_t is_plextor;
|
||||
int32_t is_sony;
|
||||
int32_t is_toshiba;
|
||||
int32_t is_yamaha;
|
||||
|
||||
int32_t c2_first;
|
||||
int32_t cur_buf;
|
||||
@@ -441,6 +448,8 @@ 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_pma(const cdrom_t *dev, uint8_t *b, const int max_len);
|
||||
extern int cdrom_read_atip(const cdrom_t *dev, uint8_t *b, 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
|
||||
@@ -472,6 +481,7 @@ 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 int cdrom_insert_blank(cdrom_t *dev, const char *fn);
|
||||
|
||||
extern void cdrom_compute_ecc_block(cdrom_t *dev, uint8_t *parity, const uint8_t *data,
|
||||
uint32_t major_count, uint32_t minor_count,
|
||||
|
||||
34
src/include/86box/cdrom_image_writable.h
Normal file
34
src/include/86box/cdrom_image_writable.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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-R(W) writable image file handling module.
|
||||
*
|
||||
* Authors: Nat Portillo, <claunia@claunia.com>
|
||||
*
|
||||
* Copyright 2025 Nat Portillo.
|
||||
*/
|
||||
#ifndef CDROM_IMAGE_WRITABLE_H
|
||||
#define CDROM_IMAGE_WRITABLE_H
|
||||
|
||||
/* Track file struct. */
|
||||
typedef struct wtrack_file_t {
|
||||
int (*read)(void *priv, uint8_t *buffer, uint64_t seek, size_t count);
|
||||
uint64_t (*get_length)(void *priv);
|
||||
void (*close)(void *priv);
|
||||
|
||||
char fn[260];
|
||||
FILE *fp;
|
||||
void *priv;
|
||||
void *log;
|
||||
|
||||
int motorola;
|
||||
} wtrack_file_t;
|
||||
|
||||
extern void *wimage_open(cdrom_t *dev, const char *path);
|
||||
|
||||
#endif /*CDROM_IMAGE_WRITABLE_H*/
|
||||
@@ -163,21 +163,22 @@
|
||||
#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12_MATSUSHITA 0xe9 /* Matsushita Vendor Unique command */
|
||||
|
||||
/* Mode page codes for mode sense/set */
|
||||
#define GPMODE_UNIT_ATN_PAGE 0x00
|
||||
#define GPMODE_R_W_ERROR_PAGE 0x01
|
||||
#define GPMODE_DISCONNECT_PAGE 0x02 /* Disconnect/reconnect page */
|
||||
#define GPMODE_FORMAT_DEVICE_PAGE 0x03
|
||||
#define GPMODE_RIGID_DISK_PAGE 0x04 /* Rigid disk geometry page */
|
||||
#define GPMODE_FLEXIBLE_DISK_PAGE 0x05
|
||||
#define GPMODE_CACHING_PAGE 0x08
|
||||
#define GPMODE_CDROM_PAGE_SONY 0x08
|
||||
#define GPMODE_CDROM_AUDIO_PAGE_SONY 0x09
|
||||
#define GPMODE_CDROM_PAGE 0x0d
|
||||
#define GPMODE_CDROM_AUDIO_PAGE 0x0e
|
||||
#define GPMODE_CAPABILITIES_PAGE 0x2a
|
||||
#define GPMODE_IOMEGA_PAGE 0x2f
|
||||
#define GPMODE_UNK_VENDOR_PAGE 0x30
|
||||
#define GPMODE_ALL_PAGES 0x3f
|
||||
#define GPMODE_UNIT_ATN_PAGE 0x00
|
||||
#define GPMODE_R_W_ERROR_PAGE 0x01
|
||||
#define GPMODE_DISCONNECT_PAGE 0x02 /* Disconnect/reconnect page */
|
||||
#define GPMODE_FORMAT_DEVICE_PAGE 0x03
|
||||
#define GPMODE_RIGID_DISK_PAGE 0x04 /* Rigid disk geometry page */
|
||||
#define GPMODE_FLEXIBLE_DISK_PAGE 0x05
|
||||
#define GPMODE_CDROM_WRITE_PARAMETERS_PAGE 0x05
|
||||
#define GPMODE_CACHING_PAGE 0x08
|
||||
#define GPMODE_CDROM_PAGE_SONY 0x08
|
||||
#define GPMODE_CDROM_AUDIO_PAGE_SONY 0x09
|
||||
#define GPMODE_CDROM_PAGE 0x0d
|
||||
#define GPMODE_CDROM_AUDIO_PAGE 0x0e
|
||||
#define GPMODE_CAPABILITIES_PAGE 0x2a
|
||||
#define GPMODE_IOMEGA_PAGE 0x2f
|
||||
#define GPMODE_UNK_VENDOR_PAGE 0x30
|
||||
#define GPMODE_ALL_PAGES 0x3f
|
||||
|
||||
/* Mode page codes for presence */
|
||||
#define GPMODEP_UNIT_ATN_PAGE 0x0000000000000001LL
|
||||
|
||||
@@ -162,6 +162,9 @@ MediaMenu::refresh(QMenu *parentMenu)
|
||||
cdromMutePos = menu->children().count();
|
||||
menu->addAction(QIcon(":/settings/qt/icons/cdrom_mute.ico"), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true);
|
||||
menu->addSeparator();
|
||||
// Can make it only appear if the drive is a Yamaha?
|
||||
menu->addAction(tr("Add &blank disc"), [this, i]() { cdromInsertBlank(i); })->setCheckable(false);
|
||||
menu->addSeparator();
|
||||
menu->addAction(getIconWithIndicator(QIcon(":/settings/qt/icons/cdrom_image.ico"), pixmap_size, QIcon::Normal, Browse), tr("&Image..."), [this, i]() { cdromMount(i, 0, nullptr); })->setCheckable(false);
|
||||
menu->addAction(getIconWithIndicator(QIcon(":/settings/qt/icons/cdrom_folder.ico"), pixmap_size, QIcon::Normal, Browse), tr("&Folder..."), [this, i]() { cdromMount(i, 1, nullptr); })->setCheckable(false);
|
||||
menu->addSeparator();
|
||||
@@ -608,6 +611,53 @@ MediaMenu::cdromMount(int i, int dir, const QString &arg)
|
||||
cdromMount(i, filename);
|
||||
}
|
||||
|
||||
void
|
||||
MediaMenu::cdromInsertBlank(int i)
|
||||
{
|
||||
// Check if drive is empty
|
||||
if (!cdrom_is_empty(i)) {
|
||||
QMessageBox::information(parentWidget, tr("Drive not empty"), tr("The drive must be empty to add a blank disc."));
|
||||
return;
|
||||
}
|
||||
|
||||
cdrom_t *drv = &cdrom[i];
|
||||
/* (claunia) TODO: Temporarily disabled because a KDE thumbnailer makes it crash while debugging on my machine, until later
|
||||
// Ask user for cuesheet file location
|
||||
QString cueFileName = QFileDialog::getSaveFileName(
|
||||
parentWidget,
|
||||
tr("CD-R(W) cuesheet image"),
|
||||
QString(),
|
||||
tr("Cuesheet files (*.cue)")
|
||||
);
|
||||
if (cueFileName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// Ensure .cue extension
|
||||
if (!cueFileName.endsWith(".cue", Qt::CaseInsensitive)) {
|
||||
cueFileName += ".cue";
|
||||
}
|
||||
QFile cueFile(cueFileName);
|
||||
if (cueFile.exists()) {
|
||||
QMessageBox::StandardButton reply = QMessageBox::question(
|
||||
parentWidget,
|
||||
tr("Replace file"),
|
||||
tr("The file '%1' already exists. Do you want to replace it?").arg(cueFileName),
|
||||
QMessageBox::Yes | QMessageBox::No
|
||||
);
|
||||
if (reply != QMessageBox::Yes) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a blank disc
|
||||
cdrom_insert_blank(drv, cueFileName.toUtf8());
|
||||
*/
|
||||
|
||||
cdrom_insert_blank(drv, "/home/claunia/foo_86box.cue"); // (claunia) Temporary hardcoded path until the above is fixed
|
||||
|
||||
ui_sb_update_icon_state(SB_CDROM | i, 1);
|
||||
}
|
||||
|
||||
void
|
||||
MediaMenu::cdromEject(int i)
|
||||
{
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
void cdromMute(int i);
|
||||
void cdromMount(int i, int dir, const QString &arg);
|
||||
void cdromMount(int i, const QString &filename);
|
||||
void cdromInsertBlank(int i);
|
||||
void cdromEject(int i);
|
||||
void cdromReload(int index, int slot);
|
||||
void updateImageHistory(int index, int slot, ui::MediaType type);
|
||||
|
||||
@@ -131,6 +131,12 @@ static uint64_t scsi_cdrom_ms_page_flags_sony_scsi = (GPMODEP_R_W_ERROR_PAGE | G
|
||||
(1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE |
|
||||
GPMODEP_ALL_PAGES);
|
||||
|
||||
static uint64_t scsi_cdrom_ms_page_flags_yamaha = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE |
|
||||
GPMODEP_FLEXIBLE_DISK_PAGE | GPMODEP_CACHING_PAGE |
|
||||
GPMODEP_CDROM_PAGE_SONY | GPMODEP_CDROM_AUDIO_PAGE_SONY |
|
||||
GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES);
|
||||
|
||||
|
||||
static uint64_t scsi_cdrom_drive_status_page_flags = ((1ULL << 0x01ULL) | (1ULL << 0x02ULL) |
|
||||
(1ULL << 0x0fULL) | GPMODEP_ALL_PAGES);
|
||||
|
||||
@@ -241,6 +247,56 @@ static const mode_sense_pages_t scsi_cdrom_ms_pages_changeable_sony_scsi = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00 } }
|
||||
};
|
||||
|
||||
static const mode_sense_pages_t scsi_cdrom_ms_pages_default_yamaha = {
|
||||
{ [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00 },
|
||||
[0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00 },
|
||||
[0x05] = { GPMODE_CDROM_WRITE_PARAMETERS_PAGE, 0x36, 0x00, 0xc7, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x96, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
[0x08] = { GPMODE_CACHING_PAGE, 0x0a, 0x04, 0x00, 0xff, 0xff, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff },
|
||||
[0x0d] = { GPMODE_CDROM_PAGE, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x4b },
|
||||
[0x0e] = { GPMODE_CDROM_AUDIO_PAGE, 0x0e, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b,
|
||||
0x01, 0xff, 0x02, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00 },
|
||||
[0x2a] = { GPMODE_CAPABILITIES_PAGE, 0x14, 0x07, 0x07, 0x71, 0x6f, 0x29, 0x03,
|
||||
0x0b, 0x06, 0x01, 0x00, 0x10, 0x00, 0x10,
|
||||
0x8a, 0x00, 0x00, 0x05, 0x83, 0x05, 0x83 } }
|
||||
};
|
||||
|
||||
// Not true values, need to check real hardware
|
||||
static const mode_sense_pages_t scsi_cdrom_ms_pages_changeable_yamaha = {
|
||||
{
|
||||
[0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0x85, 0xff, 0x00, 0x00, 0x00, 0x00 },
|
||||
[0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00 },
|
||||
[0x05] = { GPMODE_CDROM_WRITE_PARAMETERS_PAGE, 0x36, 0x5f, 0xff, 0x0f, 0x00, 0x00, 0x3f,
|
||||
0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00 },
|
||||
[0x08] = { GPMODE_CACHING_PAGE, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00 },
|
||||
[0x0d] = { GPMODE_CDROM_PAGE, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
[0x0e] = { GPMODE_CDROM_AUDIO_PAGE, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00 },
|
||||
[0x2a] = { GPMODE_CAPABILITIES_PAGE, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static gesn_cdb_t *gesn_cdb;
|
||||
@@ -1176,6 +1232,17 @@ scsi_cdrom_insert(void *priv)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_cdrom_insert_blank(void *priv)
|
||||
{
|
||||
scsi_cdrom_t *dev = (scsi_cdrom_t *) priv;
|
||||
|
||||
if ((dev == NULL) /*|| (dev->drv == NULL)*/)
|
||||
return;
|
||||
|
||||
scsi_cdrom_log(dev->log, "Inserting blank disc\n");
|
||||
}
|
||||
|
||||
static int
|
||||
scsi_command_check_ready(const scsi_cdrom_t *dev, const uint8_t *cdb)
|
||||
{
|
||||
@@ -2575,6 +2642,12 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb)
|
||||
if (dev->drv->ops == NULL)
|
||||
scsi_cdrom_not_ready(dev);
|
||||
else if (toc_format < 3) {
|
||||
// Blank discs return invalid field when asked for a TOC
|
||||
if (dev->drv->blank_media) {
|
||||
scsi_cdrom_invalid_field(dev, toc_format);
|
||||
break;
|
||||
}
|
||||
|
||||
len = cdrom_read_toc(dev->drv, dev->buffer, toc_format, cdb[6], msf, max_len);
|
||||
/* If the returned length is -1, this means cdrom_read_toc() has encountered an error. */
|
||||
if (len == -1)
|
||||
@@ -2585,6 +2658,16 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb)
|
||||
scsi_cdrom_set_buf_len(dev, BufLen, &len);
|
||||
scsi_cdrom_data_command_finish(dev, len, len, len, 0);
|
||||
}
|
||||
} else if (toc_format == 3 && dev->drv->blank_media == CD_BLANK_CDR) {
|
||||
len = cdrom_read_pma(dev->drv, dev->buffer, max_len);
|
||||
|
||||
scsi_cdrom_set_buf_len(dev, BufLen, &len);
|
||||
scsi_cdrom_data_command_finish(dev, len, len, len, 0);
|
||||
} else if (toc_format == 4 && dev->drv->blank_media == CD_BLANK_CDR) {
|
||||
len = cdrom_read_atip(dev->drv, dev->buffer, max_len);
|
||||
|
||||
scsi_cdrom_set_buf_len(dev, BufLen, &len);
|
||||
scsi_cdrom_data_command_finish(dev, len, len, len, 0);
|
||||
} else
|
||||
scsi_cdrom_invalid_field(dev, toc_format);
|
||||
break;
|
||||
@@ -3578,6 +3661,14 @@ atapi_out:
|
||||
dev->buffer[6] = 8;
|
||||
len = 8;
|
||||
|
||||
// Undo the overflow if disc capacity is blank
|
||||
if (dev->drv->blank_media) {
|
||||
dev->buffer[0] = 0x00;
|
||||
dev->buffer[1] = 0x00;
|
||||
dev->buffer[2] = 0x00;
|
||||
dev->buffer[3] = 0x00;
|
||||
}
|
||||
|
||||
scsi_cdrom_log(dev->log, "CD-ROM Capacity: %08X\n",
|
||||
dev->drv->cdrom_capacity - 1);
|
||||
|
||||
@@ -3932,6 +4023,7 @@ scsi_cdrom_drive_reset(const int c)
|
||||
drv->get_volume = scsi_cdrom_get_volume;
|
||||
drv->get_channel = scsi_cdrom_get_channel;
|
||||
drv->close = scsi_cdrom_close;
|
||||
drv->insert_blank = scsi_cdrom_insert_blank;
|
||||
|
||||
drv->sector_size = 2048;
|
||||
(void) scsi_cdrom_update_sector_flags(dev);
|
||||
@@ -3973,6 +4065,10 @@ scsi_cdrom_drive_reset(const int c)
|
||||
dev->ven_cmd_is_data[0xc6] = 1;
|
||||
dev->ven_cmd_is_data[0xc7] = 1;
|
||||
dev->use_cdb_9 = 1;
|
||||
} else if (dev->drv->is_yamaha) {
|
||||
dev->ms_page_flags = scsi_cdrom_ms_page_flags_yamaha;
|
||||
dev->ms_pages_default = scsi_cdrom_ms_pages_default_yamaha;
|
||||
dev->ms_pages_changeable = scsi_cdrom_ms_pages_changeable_yamaha;
|
||||
}
|
||||
|
||||
if (dev->tf == NULL)
|
||||
@@ -4025,6 +4121,12 @@ scsi_cdrom_drive_reset(const int c)
|
||||
id->write = NULL;
|
||||
id->interrupt_drq = dev->drv->is_early;
|
||||
|
||||
if (dev->drv->is_yamaha) {
|
||||
dev->ms_page_flags = scsi_cdrom_ms_page_flags_yamaha;
|
||||
dev->ms_pages_default = scsi_cdrom_ms_pages_default_yamaha;
|
||||
dev->ms_pages_changeable = scsi_cdrom_ms_pages_changeable_yamaha;
|
||||
}
|
||||
|
||||
valid = 1;
|
||||
|
||||
ide_atapi_attach(id);
|
||||
|
||||
Reference in New Issue
Block a user