2017-05-30 03:38:38 +02:00
/*
2022-11-13 16:37:58 -05:00
* 86 Box 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 .
2017-05-30 03:38:38 +02:00
*
2022-11-13 16:37:58 -05:00
* This file is part of the 86 Box distribution .
2017-05-30 03:38:38 +02:00
*
2022-11-13 16:37:58 -05:00
* Generic CD - ROM drive core .
2017-05-30 03:38:38 +02:00
*
2017-10-08 19:14:46 -04:00
*
2022-11-13 16:37:58 -05:00
*
* Authors : Miran Grca , < mgrca8 @ gmail . com >
*
* Copyright 2018 - 2021 Miran Grca .
2017-05-30 03:38:38 +02:00
*/
2018-03-21 14:46:54 +01:00
# include <inttypes.h>
2018-05-21 19:04:05 +02:00
# include <stdarg.h>
2017-01-16 01:49:19 +01:00
# include <stdint.h>
2018-05-21 19:04:05 +02:00
# include <stdio.h>
2017-01-17 00:01:59 +01:00
# include <string.h>
2017-09-25 04:31:20 -04:00
# include <stdlib.h>
# include <wchar.h>
2017-12-10 19:36:41 +01:00
# define HAVE_STDARG_H
2020-03-29 14:24:42 +02:00
# include <86box/86box.h>
2023-01-07 23:48:45 +01:00
# include <86box/device.h>
2020-03-29 14:24:42 +02:00
# include <86box/config.h>
# include <86box/cdrom.h>
# include <86box/cdrom_image.h>
2023-01-07 23:48:45 +01:00
# include <86box/cdrom_interface.h>
# include <86box/cdrom_mitsumi.h>
2020-03-29 14:24:42 +02:00
# include <86box/plat.h>
2022-08-02 20:11:23 -04:00
# include <86box/scsi.h>
2020-06-14 21:59:45 +02:00
# include <86box/scsi_device.h>
2020-03-29 14:24:42 +02:00
# include <86box/sound.h>
2017-09-04 01:52:29 -04:00
2018-10-30 13:32:25 +01:00
/* 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 . */
2020-06-14 21:59:45 +02:00
# undef MSFtoLBA
2022-09-18 17:11:56 -04:00
# define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f)
2018-10-30 13:32:25 +01:00
2022-09-18 17:11:56 -04:00
# define RAW_SECTOR_SIZE 2352
# define COOKED_SECTOR_SIZE 2048
2018-10-30 13:32:25 +01:00
2022-09-18 17:11:56 -04:00
# define MIN_SEEK 2000
# define MAX_SEEK 333333
2018-04-25 23:51:13 +02:00
2022-09-18 17:11:56 -04:00
# pragma pack(push, 1)
2018-10-30 13:32:25 +01:00
typedef struct {
uint8_t user_data [ 2048 ] ,
2022-09-18 17:11:56 -04:00
ecc [ 288 ] ;
2018-10-30 13:32:25 +01:00
} m1_data_t ;
typedef struct {
uint8_t sub_header [ 8 ] ,
2022-09-18 17:11:56 -04:00
user_data [ 2328 ] ;
2018-10-30 13:32:25 +01:00
} m2_data_t ;
typedef union {
m1_data_t m1_data ;
m2_data_t m2_data ;
2022-09-18 17:11:56 -04:00
uint8_t raw_data [ 2336 ] ;
2018-10-30 13:32:25 +01:00
} sector_data_t ;
typedef struct {
2022-09-18 17:11:56 -04:00
uint8_t sync [ 12 ] ;
uint8_t header [ 4 ] ;
2018-10-30 13:32:25 +01:00
sector_data_t data ;
} sector_raw_data_t ;
typedef union {
sector_raw_data_t sector_data ;
2022-09-18 17:11:56 -04:00
uint8_t raw_data [ 2352 ] ;
2018-10-30 13:32:25 +01:00
} sector_t ;
typedef struct {
sector_t sector ;
2022-09-18 17:11:56 -04:00
uint8_t c2 [ 296 ] ;
uint8_t subchannel_raw [ 96 ] ;
uint8_t subchannel_q [ 16 ] ;
uint8_t subchannel_rw [ 96 ] ;
2018-10-30 13:32:25 +01:00
} cdrom_sector_t ;
typedef union {
cdrom_sector_t cdrom_sector ;
2022-09-18 17:11:56 -04:00
uint8_t buffer [ 2856 ] ;
2018-10-30 13:32:25 +01:00
} sector_buffer_t ;
# pragma pack(pop)
2022-09-18 17:11:56 -04:00
static int cdrom_sector_size ;
static uint8_t raw_buffer [ 2856 ] ; /* Needs to be the same size as sector_buffer_t in the structs. */
static uint8_t extra_buffer [ 296 ] ;
2018-10-30 13:32:25 +01:00
2022-09-18 17:11:56 -04:00
cdrom_t cdrom [ CDROM_NUM ] ;
2017-01-16 01:49:19 +01:00
2023-01-07 23:48:45 +01:00
int cdrom_interface_current ;
2017-10-16 06:19:18 +02:00
# ifdef ENABLE_CDROM_LOG
2022-09-18 17:11:56 -04:00
int cdrom_do_log = ENABLE_CDROM_LOG ;
2017-11-24 02:23:00 -05:00
2018-10-17 05:29:48 +02:00
void
cdrom_log ( const char * fmt , . . . )
2017-01-16 01:49:19 +01:00
{
2018-04-25 23:51:13 +02:00
va_list ap ;
2017-12-05 23:35:35 +01:00
2018-04-25 23:51:13 +02:00
if ( cdrom_do_log ) {
2022-02-22 22:04:40 +01:00
va_start ( ap , fmt ) ;
pclog_ex ( fmt , ap ) ;
va_end ( ap ) ;
2018-04-25 23:51:13 +02:00
}
2017-01-16 01:49:19 +01:00
}
2018-10-17 05:29:48 +02:00
# else
2022-09-18 17:11:56 -04:00
# define cdrom_log(fmt, ...)
2018-10-17 05:29:48 +02:00
# endif
2017-01-16 01:49:19 +01:00
2023-01-07 23:48:45 +01:00
static const device_t cdrom_interface_none_device = {
. name = " None " ,
. internal_name = " none " ,
. flags = 0 ,
. local = 0 ,
. init = NULL ,
. close = NULL ,
. reset = NULL ,
{ . available = NULL } ,
. speed_changed = NULL ,
. force_redraw = NULL ,
. config = NULL
} ;
static const struct {
const device_t * device ;
} controllers [ ] = {
// clang-format off
{ & cdrom_interface_none_device } ,
{ NULL }
// clang-format on
} ;
/* Reset the CD-ROM Interface, whichever one that is. */
void
cdrom_interface_reset ( void )
{
cdrom_log ( " CD-ROM Interface: reset(current=%d) \n " ,
cdrom_interface_current ) ;
/* If we have a valid controller, add its device. */
2023-10-14 06:45:45 +02:00
if ( ( cdrom_interface_current > 0 ) & & controllers [ cdrom_interface_current ] . device )
device_add ( controllers [ cdrom_interface_current ] . device ) ;
2023-01-07 23:48:45 +01:00
}
2023-08-21 20:22:09 -04:00
const char *
2023-01-07 23:48:45 +01:00
cdrom_interface_get_internal_name ( int cdinterface )
{
return device_get_internal_name ( controllers [ cdinterface ] . device ) ;
}
int
cdrom_interface_get_from_internal_name ( char * s )
{
int c = 0 ;
while ( controllers [ c ] . device ! = NULL ) {
2023-06-09 23:46:54 -04:00
if ( ! strcmp ( controllers [ c ] . device - > internal_name , s ) )
2023-01-07 23:48:45 +01:00
return c ;
c + + ;
}
return 0 ;
}
const device_t *
cdrom_interface_get_device ( int cdinterface )
{
return ( controllers [ cdinterface ] . device ) ;
}
int
cdrom_interface_has_config ( int cdinterface )
{
const device_t * dev = cdrom_interface_get_device ( cdinterface ) ;
if ( dev = = NULL )
2023-05-16 15:43:20 -04:00
return 0 ;
2023-01-07 23:48:45 +01:00
if ( ! device_has_config ( dev ) )
2023-05-16 15:43:20 -04:00
return 0 ;
2023-01-07 23:48:45 +01:00
2023-05-16 15:43:20 -04:00
return 1 ;
2023-01-07 23:48:45 +01:00
}
int
cdrom_interface_get_flags ( int cdinterface )
{
return ( controllers [ cdinterface ] . device - > flags ) ;
}
int
cdrom_interface_available ( int cdinterface )
{
return ( device_available ( controllers [ cdinterface ] . device ) ) ;
}
char *
cdrom_getname ( int type )
{
return ( char * ) cdrom_drive_types [ type ] . name ;
}
char *
cdrom_get_internal_name ( int type )
{
return ( char * ) cdrom_drive_types [ type ] . internal_name ;
}
int
cdrom_get_from_internal_name ( char * s )
{
int c = 0 ;
while ( strlen ( cdrom_drive_types [ c ] . internal_name ) ) {
if ( ! strcmp ( ( char * ) cdrom_drive_types [ c ] . internal_name , s ) )
return c ;
c + + ;
}
return 0 ;
}
void
cdrom_set_type ( int model , int type )
{
cdrom [ model ] . type = type ;
}
int
cdrom_get_type ( int model )
{
return cdrom [ model ] . type ;
}
static __inline int
bin2bcd ( int x )
{
return ( x % 10 ) | ( ( x / 10 ) < < 4 ) ;
}
static __inline int
bcd2bin ( int x )
{
return ( x > > 4 ) * 10 + ( x & 0x0f ) ;
}
2018-04-25 23:51:13 +02:00
int
cdrom_lba_to_msf_accurate ( int lba )
2017-01-16 01:49:19 +01:00
{
2018-10-17 05:29:48 +02:00
int pos ;
2023-05-16 15:43:20 -04:00
int m ;
int s ;
int f ;
2018-04-25 23:51:13 +02:00
2018-10-17 05:29:48 +02:00
pos = lba + 150 ;
2022-09-18 17:11:56 -04:00
f = pos % 75 ;
2018-10-17 05:29:48 +02:00
pos - = f ;
pos / = 75 ;
s = pos % 60 ;
pos - = s ;
pos / = 60 ;
m = pos ;
2018-04-25 23:51:13 +02:00
return ( ( m < < 16 ) | ( s < < 8 ) | f ) ;
2017-01-16 01:49:19 +01:00
}
2018-10-17 05:29:48 +02:00
static double
cdrom_get_short_seek ( cdrom_t * dev )
2018-04-25 23:51:13 +02:00
{
2022-09-18 17:11:56 -04:00
switch ( dev - > cur_speed ) {
2022-02-22 22:04:40 +01:00
case 0 :
fatal ( " CD-ROM %i: 0x speed \n " , dev - > id ) ;
return 0.0 ;
case 1 :
return 240.0 ;
case 2 :
return 160.0 ;
case 3 :
return 150.0 ;
2022-09-18 17:11:56 -04:00
case 4 :
case 5 :
case 6 :
case 7 :
case 8 :
case 9 :
case 10 :
case 11 :
2022-02-22 22:04:40 +01:00
return 112.0 ;
2022-09-18 17:11:56 -04:00
case 12 :
case 13 :
case 14 :
case 15 :
2022-02-22 22:04:40 +01:00
return 75.0 ;
2022-09-18 17:11:56 -04:00
case 16 :
case 17 :
case 18 :
case 19 :
2022-02-22 22:04:40 +01:00
return 58.0 ;
2022-09-18 17:11:56 -04:00
case 20 :
case 21 :
case 22 :
case 23 :
case 40 :
case 41 :
case 42 :
case 43 :
case 44 :
case 45 :
case 46 :
case 47 :
2022-02-22 22:04:40 +01:00
case 48 :
return 50.0 ;
default :
/* 24-32, 52+ */
return 45.0 ;
2018-04-25 23:51:13 +02:00
}
2018-03-17 20:32:20 +01:00
}
2018-10-17 05:29:48 +02:00
static double
cdrom_get_long_seek ( cdrom_t * dev )
2018-04-25 23:51:13 +02:00
{
2022-09-18 17:11:56 -04:00
switch ( dev - > cur_speed ) {
2022-02-22 22:04:40 +01:00
case 0 :
fatal ( " CD-ROM %i: 0x speed \n " , dev - > id ) ;
return 0.0 ;
case 1 :
return 1446.0 ;
case 2 :
return 1000.0 ;
case 3 :
return 900.0 ;
2022-09-18 17:11:56 -04:00
case 4 :
case 5 :
case 6 :
case 7 :
case 8 :
case 9 :
case 10 :
case 11 :
2022-02-22 22:04:40 +01:00
return 675.0 ;
2022-09-18 17:11:56 -04:00
case 12 :
case 13 :
case 14 :
case 15 :
2022-02-22 22:04:40 +01:00
return 400.0 ;
2022-09-18 17:11:56 -04:00
case 16 :
case 17 :
case 18 :
case 19 :
2022-02-22 22:04:40 +01:00
return 350.0 ;
2022-09-18 17:11:56 -04:00
case 20 :
case 21 :
case 22 :
case 23 :
case 40 :
case 41 :
case 42 :
case 43 :
case 44 :
case 45 :
case 46 :
case 47 :
2022-02-22 22:04:40 +01:00
case 48 :
return 300.0 ;
default :
/* 24-32, 52+ */
return 270.0 ;
2018-04-25 23:51:13 +02:00
}
2018-03-17 20:32:20 +01:00
}
2018-10-10 22:33:24 +02:00
double
2018-10-17 05:29:48 +02:00
cdrom_seek_time ( cdrom_t * dev )
2018-03-17 20:32:20 +01:00
{
2018-04-25 23:51:13 +02:00
uint32_t diff = dev - > seek_diff ;
2022-09-18 17:11:56 -04:00
double sd = ( double ) ( MAX_SEEK - MIN_SEEK ) ;
2018-03-17 20:32:20 +01:00
2018-04-25 23:51:13 +02:00
if ( diff < MIN_SEEK )
2022-02-22 22:04:40 +01:00
return 0.0 ;
2018-04-25 23:51:13 +02:00
if ( diff > MAX_SEEK )
2022-02-22 22:04:40 +01:00
diff = MAX_SEEK ;
2018-03-17 20:32:20 +01:00
2018-04-25 23:51:13 +02:00
diff - = MIN_SEEK ;
2018-03-17 20:32:20 +01:00
2018-04-25 23:51:13 +02:00
return cdrom_get_short_seek ( dev ) + ( ( cdrom_get_long_seek ( dev ) * ( ( double ) diff ) ) / sd ) ;
2018-03-17 20:32:20 +01:00
}
2018-10-30 13:32:25 +01:00
void
cdrom_stop ( cdrom_t * dev )
{
if ( dev - > cd_status > CD_STATUS_DATA_ONLY )
2022-02-22 22:04:40 +01:00
dev - > cd_status = CD_STATUS_STOPPED ;
2018-10-30 13:32:25 +01:00
}
2018-10-10 22:33:24 +02:00
void
2023-01-07 23:48:45 +01:00
cdrom_seek ( cdrom_t * dev , uint32_t pos , uint8_t vendor_type )
2018-04-25 23:51:13 +02:00
{
2023-05-16 15:43:20 -04:00
int m ;
int s ;
int f ;
2023-01-07 23:48:45 +01:00
2018-10-11 10:34:12 +02:00
if ( ! dev )
2022-02-22 22:04:40 +01:00
return ;
2018-10-11 10:34:12 +02:00
2023-01-07 23:48:45 +01:00
cdrom_log ( " CD-ROM %i: Seek to LBA %08X, vendor type = %02x. \n " , dev - > id , pos , vendor_type ) ;
switch ( vendor_type ) {
case 0x40 :
m = bcd2bin ( ( pos > > 24 ) & 0xff ) ;
s = bcd2bin ( ( pos > > 16 ) & 0xff ) ;
f = bcd2bin ( ( pos > > 8 ) & 0xff ) ;
pos = MSFtoLBA ( m , s , f ) - 150 ;
break ;
case 0x80 :
pos = bcd2bin ( ( pos > > 24 ) & 0xff ) ;
break ;
2023-06-26 12:47:04 -04:00
default :
break ;
2023-01-07 23:48:45 +01:00
}
2018-10-30 13:32:25 +01:00
2022-09-18 17:11:56 -04:00
dev - > seek_pos = pos ;
2018-10-30 13:32:25 +01:00
cdrom_stop ( dev ) ;
2017-01-16 01:49:19 +01:00
}
2021-09-02 20:52:30 +02:00
int
cdrom_is_pre ( cdrom_t * dev , uint32_t lba )
{
if ( dev - > ops & & dev - > ops - > is_track_pre )
2022-02-22 22:04:40 +01:00
return dev - > ops - > is_track_pre ( dev , lba ) ;
2021-09-02 20:52:30 +02:00
return 0 ;
}
2018-10-10 22:33:24 +02:00
int
2018-10-30 13:32:25 +01:00
cdrom_audio_callback ( cdrom_t * dev , int16_t * output , int len )
2018-04-25 23:51:13 +02:00
{
2018-10-30 13:32:25 +01:00
int ret = 1 ;
2024-02-06 21:18:25 +01:00
if ( ! dev - > sound_on | | ( dev - > cd_status ! = CD_STATUS_PLAYING ) | | dev - > audio_muted_soft ) {
2024-12-31 04:37:21 +01:00
// cdrom_log("CD-ROM %i: Audio callback while not playing\n", dev->id);
2022-02-22 22:04:40 +01:00
if ( dev - > cd_status = = CD_STATUS_PLAYING )
dev - > seek_pos + = ( len > > 11 ) ;
memset ( output , 0 , len * 2 ) ;
return 0 ;
2018-10-30 13:32:25 +01:00
}
while ( dev - > cd_buflen < len ) {
2022-02-22 22:04:40 +01:00
if ( dev - > seek_pos < dev - > cd_end ) {
2024-12-31 04:37:21 +01:00
if ( dev - > ops - > read_sector ( dev , ( uint8_t * ) & ( dev - > cd_buffer [ dev - > cd_buflen ] ) , dev - > seek_pos ) ) {
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: Read LBA %08X successful \n " , dev - > id , dev - > seek_pos ) ;
2024-12-31 04:37:21 +01:00
memcpy ( dev - > subch_buffer , ( ( uint8_t * ) & ( dev - > cd_buffer [ dev - > cd_buflen ] ) ) + 2352 , 96 ) ;
2022-02-22 22:04:40 +01:00
dev - > seek_pos + + ;
dev - > cd_buflen + = ( RAW_SECTOR_SIZE / 2 ) ;
ret = 1 ;
} else {
cdrom_log ( " CD-ROM %i: Read LBA %08X failed \n " , dev - > id , dev - > seek_pos ) ;
memset ( & ( dev - > cd_buffer [ dev - > cd_buflen ] ) , 0x00 , ( BUF_SIZE - dev - > cd_buflen ) * 2 ) ;
2024-12-31 04:37:21 +01:00
dev - > cd_status = CD_STATUS_STOPPED ;
dev - > cd_buflen = len ;
ret = 0 ;
2022-02-22 22:04:40 +01:00
}
} else {
cdrom_log ( " CD-ROM %i: Playing completed \n " , dev - > id ) ;
memset ( & dev - > cd_buffer [ dev - > cd_buflen ] , 0x00 , ( BUF_SIZE - dev - > cd_buflen ) * 2 ) ;
2024-12-31 04:37:21 +01:00
dev - > cd_status = CD_STATUS_PLAYING_COMPLETED ;
dev - > cd_buflen = len ;
ret = 0 ;
2022-02-22 22:04:40 +01:00
}
2018-10-30 13:32:25 +01:00
}
memcpy ( output , dev - > cd_buffer , len * 2 ) ;
memmove ( dev - > cd_buffer , & dev - > cd_buffer [ len ] , ( BUF_SIZE - len ) * 2 ) ;
dev - > cd_buflen - = len ;
cdrom_log ( " CD-ROM %i: Audio callback returning %i \n " , dev - > id , ret ) ;
return ret ;
}
2022-10-29 06:44:30 +02:00
static void
msf_from_bcd ( int * m , int * s , int * f )
{
* m = bcd2bin ( * m ) ;
* s = bcd2bin ( * s ) ;
* f = bcd2bin ( * f ) ;
}
static void
msf_to_bcd ( int * m , int * s , int * f )
{
* m = bin2bcd ( * m ) ;
* s = bin2bcd ( * s ) ;
* f = bin2bcd ( * f ) ;
}
2018-10-30 13:32:25 +01:00
uint8_t
cdrom_audio_play ( cdrom_t * dev , uint32_t pos , uint32_t len , int ismsf )
{
track_info_t ti ;
2023-05-16 15:43:20 -04:00
int m = 0 ;
int s = 0 ;
int f = 0 ;
2018-10-30 13:32:25 +01:00
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
2022-02-22 22:04:40 +01:00
return 0 ;
2018-10-30 13:32:25 +01:00
cdrom_log ( " CD-ROM %i: Play audio - %08X %08X %i \n " , dev - > id , pos , len , ismsf ) ;
2018-10-30 16:42:43 +01:00
if ( ismsf & 0x100 ) {
2022-02-22 22:04:40 +01:00
/* Track-relative audio play. */
dev - > ops - > get_track_info ( dev , ismsf & 0xff , 0 , & ti ) ;
pos + = MSFtoLBA ( ti . m , ti . s , ti . f ) - 150 ;
2023-01-07 23:48:45 +01:00
} else if ( ( ismsf = = 2 ) | | ( ismsf = = 3 ) ) {
2022-02-22 22:04:40 +01:00
dev - > ops - > get_track_info ( dev , pos , 0 , & ti ) ;
pos = MSFtoLBA ( ti . m , ti . s , ti . f ) - 150 ;
2023-01-07 23:48:45 +01:00
if ( ismsf = = 2 ) {
/* We have to end at the *end* of the specified track,
not at the beginning . */
dev - > ops - > get_track_info ( dev , len , 1 , & ti ) ;
len = MSFtoLBA ( ti . m , ti . s , ti . f ) - 150 ;
}
2018-10-30 13:32:25 +01:00
} else if ( ismsf = = 1 ) {
2022-02-22 22:04:40 +01:00
m = ( pos > > 16 ) & 0xff ;
s = ( pos > > 8 ) & 0xff ;
f = pos & 0xff ;
2022-10-29 06:44:30 +02:00
/* NEC CDR-260 speaks BCD. */
2023-09-24 07:44:25 +02:00
if ( ( dev - > type = = CDROM_TYPE_NEC_260_100 ) | | ( dev - > type = = CDROM_TYPE_NEC_260_101 ) ) /*NEC*/
2022-10-29 06:44:30 +02:00
msf_from_bcd ( & m , & s , & f ) ;
2022-02-22 22:04:40 +01:00
if ( pos = = 0xffffff ) {
cdrom_log ( " CD-ROM %i: Playing from current position (MSF) \n " , dev - > id ) ;
pos = dev - > seek_pos ;
} else
pos = MSFtoLBA ( m , s , f ) - 150 ;
2022-11-05 20:15:00 -04:00
m = ( len > > 16 ) & 0xff ;
s = ( len > > 8 ) & 0xff ;
f = len & 0xff ;
2022-10-29 06:44:30 +02:00
/* NEC CDR-260 speaks BCD. */
2023-09-24 07:44:25 +02:00
if ( ( dev - > type = = CDROM_TYPE_NEC_260_100 ) | | ( dev - > type = = CDROM_TYPE_NEC_260_101 ) ) /*NEC*/
2022-10-29 06:44:30 +02:00
msf_from_bcd ( & m , & s , & f ) ;
2022-02-22 22:04:40 +01:00
len = MSFtoLBA ( m , s , f ) - 150 ;
cdrom_log ( " CD-ROM %i: MSF - pos = %08X len = %08X \n " , dev - > id , pos , len ) ;
2018-10-30 13:32:25 +01:00
} else if ( ismsf = = 0 ) {
2022-02-22 22:04:40 +01:00
if ( pos = = 0xffffffff ) {
cdrom_log ( " CD-ROM %i: Playing from current position \n " , dev - > id ) ;
pos = dev - > seek_pos ;
}
len + = pos ;
2018-10-30 13:32:25 +01:00
}
2024-02-06 21:18:25 +01:00
dev - > audio_muted_soft = 0 ;
2018-10-30 13:32:25 +01:00
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from . */
if ( ! ( dev - > ops - > track_type ( dev , pos ) & CD_TRACK_AUDIO ) ) {
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: LBA %08X not on an audio track \n " , dev - > id , pos ) ;
cdrom_stop ( dev ) ;
return 0 ;
2018-10-30 13:32:25 +01:00
}
2022-09-18 17:11:56 -04:00
dev - > seek_pos = pos ;
dev - > cd_end = len ;
2018-10-30 13:32:25 +01:00
dev - > cd_status = CD_STATUS_PLAYING ;
dev - > cd_buflen = 0 ;
return 1 ;
}
2020-03-24 01:00:28 +01:00
uint8_t
cdrom_audio_track_search ( cdrom_t * dev , uint32_t pos , int type , uint8_t playbit )
{
2023-05-16 15:43:20 -04:00
int m = 0 ;
int s = 0 ;
int f = 0 ;
2024-02-06 21:18:25 +01:00
uint32_t pos2 = 0 ;
2022-02-20 02:26:27 -05:00
2020-03-24 01:00:28 +01:00
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
2022-02-22 22:04:40 +01:00
return 0 ;
2022-02-20 02:26:27 -05:00
2022-12-04 20:53:03 +01:00
cdrom_log ( " Audio Track Search: MSF = %06x, type = %02x, playbit = %02x \n " , pos , type , playbit ) ;
2020-03-24 01:00:28 +01:00
switch ( type ) {
2022-12-04 20:53:03 +01:00
case 0x00 :
if ( pos = = 0xffffffff ) {
2023-01-07 23:48:45 +01:00
cdrom_log ( " CD-ROM %i: (type 0) Search from current position \n " , dev - > id ) ;
2022-12-04 20:53:03 +01:00
pos = dev - > seek_pos ;
}
2023-01-07 23:48:45 +01:00
dev - > seek_pos = pos ;
2022-12-04 20:53:03 +01:00
break ;
2022-02-22 22:04:40 +01:00
case 0x40 :
2023-01-07 23:48:45 +01:00
m = bcd2bin ( ( pos > > 24 ) & 0xff ) ;
s = bcd2bin ( ( pos > > 16 ) & 0xff ) ;
f = bcd2bin ( ( pos > > 8 ) & 0xff ) ;
2022-12-04 20:53:03 +01:00
if ( pos = = 0xffffffff ) {
2023-01-07 23:48:45 +01:00
cdrom_log ( " CD-ROM %i: (type 1) Search from current position \n " , dev - > id ) ;
2022-12-04 20:53:03 +01:00
pos = dev - > seek_pos ;
} else
pos = MSFtoLBA ( m , s , f ) - 150 ;
2023-01-07 23:48:45 +01:00
dev - > seek_pos = pos ;
break ;
case 0x80 :
if ( pos = = 0xffffffff ) {
cdrom_log ( " CD-ROM %i: (type 2) Search from current position \n " , dev - > id ) ;
pos = dev - > seek_pos ;
}
dev - > seek_pos = ( pos > > 24 ) & 0xff ;
2022-02-22 22:04:40 +01:00
break ;
2023-06-26 12:47:04 -04:00
default :
break ;
2020-03-24 01:00:28 +01:00
}
2022-02-20 02:26:27 -05:00
2024-02-06 21:18:25 +01:00
pos2 = pos - 1 ;
if ( pos2 = = 0xffffffff )
pos2 = pos + 1 ;
2023-12-16 14:03:42 +01:00
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from . */
2024-02-06 21:18:25 +01:00
if ( ! ( dev - > ops - > track_type ( dev , pos2 ) & CD_TRACK_AUDIO ) ) {
cdrom_log ( " CD-ROM %i: Track Search: LBA %08X not on an audio track \n " , dev - > id , pos ) ;
dev - > audio_muted_soft = 1 ;
if ( dev - > ops - > track_type ( dev , pos ) & CD_TRACK_AUDIO )
dev - > audio_muted_soft = 0 ;
} else
dev - > audio_muted_soft = 0 ;
2023-12-16 14:03:42 +01:00
2024-02-06 21:18:25 +01:00
cdrom_log ( " Track Search Toshiba: Muted?=%d, LBA=%08X. \n " , dev - > audio_muted_soft , pos ) ;
2022-12-04 20:53:03 +01:00
dev - > cd_buflen = 0 ;
2020-03-24 01:00:28 +01:00
dev - > cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED ;
return 1 ;
}
2023-09-20 20:29:32 +02:00
uint8_t
cdrom_audio_track_search_pioneer ( cdrom_t * dev , uint32_t pos , uint8_t playbit )
{
int m = 0 ;
int s = 0 ;
int f = 0 ;
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
return 0 ;
f = bcd2bin ( ( pos > > 24 ) & 0xff ) ;
s = bcd2bin ( ( pos > > 16 ) & 0xff ) ;
m = bcd2bin ( ( pos > > 8 ) & 0xff ) ;
if ( pos = = 0xffffffff ) {
pos = dev - > seek_pos ;
} else
pos = MSFtoLBA ( m , s , f ) - 150 ;
dev - > seek_pos = pos ;
2024-02-06 21:18:25 +01:00
dev - > audio_muted_soft = 0 ;
2023-12-16 14:03:42 +01:00
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from . */
if ( ! ( dev - > ops - > track_type ( dev , pos ) & CD_TRACK_AUDIO ) ) {
cdrom_log ( " CD-ROM %i: LBA %08X not on an audio track \n " , dev - > id , pos ) ;
cdrom_stop ( dev ) ;
return 0 ;
}
2023-09-20 20:29:32 +02:00
dev - > cd_buflen = 0 ;
dev - > cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED ;
return 1 ;
}
uint8_t
cdrom_audio_play_pioneer ( cdrom_t * dev , uint32_t pos )
{
int m = 0 ;
int s = 0 ;
int f = 0 ;
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
return 0 ;
f = bcd2bin ( ( pos > > 24 ) & 0xff ) ;
s = bcd2bin ( ( pos > > 16 ) & 0xff ) ;
m = bcd2bin ( ( pos > > 8 ) & 0xff ) ;
pos = MSFtoLBA ( m , s , f ) - 150 ;
dev - > cd_end = pos ;
2024-02-06 21:18:25 +01:00
dev - > audio_muted_soft = 0 ;
2023-09-20 20:29:32 +02:00
dev - > cd_buflen = 0 ;
dev - > cd_status = CD_STATUS_PLAYING ;
return 1 ;
}
2022-02-20 02:26:27 -05:00
uint8_t
2023-01-07 23:48:45 +01:00
cdrom_audio_play_toshiba ( cdrom_t * dev , uint32_t pos , int type )
2020-03-24 01:00:28 +01:00
{
2023-05-16 15:43:20 -04:00
int m = 0 ;
int s = 0 ;
int f = 0 ;
2020-03-24 01:00:28 +01:00
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
2022-02-22 22:04:40 +01:00
return 0 ;
2020-03-24 01:00:28 +01:00
/*Preliminary support, revert if too incomplete*/
switch ( type ) {
2023-01-07 23:48:45 +01:00
case 0x00 :
dev - > cd_end = pos ;
break ;
2022-02-22 22:04:40 +01:00
case 0x40 :
2023-01-07 23:48:45 +01:00
m = bcd2bin ( ( pos > > 24 ) & 0xff ) ;
s = bcd2bin ( ( pos > > 16 ) & 0xff ) ;
f = bcd2bin ( ( pos > > 8 ) & 0xff ) ;
2022-02-22 22:04:40 +01:00
pos = MSFtoLBA ( m , s , f ) - 150 ;
2023-01-07 23:48:45 +01:00
dev - > cd_end = pos ;
break ;
case 0x80 :
dev - > cd_end = ( pos > > 24 ) & 0xff ;
2022-02-22 22:04:40 +01:00
break ;
2022-12-04 20:53:03 +01:00
case 0xc0 :
if ( pos = = 0xffffffff ) {
cdrom_log ( " CD-ROM %i: Playing from current position \n " , dev - > id ) ;
pos = dev - > cd_end ;
}
2023-01-07 23:48:45 +01:00
dev - > cd_end = pos ;
2022-12-04 20:53:03 +01:00
break ;
2023-06-26 12:47:04 -04:00
default :
break ;
2020-03-24 01:00:28 +01:00
}
2022-02-20 02:26:27 -05:00
2024-02-06 21:18:25 +01:00
cdrom_log ( " Toshiba Play Audio: Muted?=%d, LBA=%08X. \n " , dev - > audio_muted_soft , pos ) ;
2020-03-24 01:00:28 +01:00
dev - > cd_buflen = 0 ;
2022-12-04 20:53:03 +01:00
dev - > cd_status = CD_STATUS_PLAYING ;
2020-03-24 01:00:28 +01:00
return 1 ;
}
2018-10-30 13:32:25 +01:00
2023-01-07 23:48:45 +01:00
uint8_t
cdrom_audio_scan ( cdrom_t * dev , uint32_t pos , int type )
{
2023-05-16 15:43:20 -04:00
int m = 0 ;
int s = 0 ;
int f = 0 ;
2023-01-07 23:48:45 +01:00
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
return 0 ;
cdrom_log ( " Audio Scan: MSF = %06x, type = %02x \n " , pos , type ) ;
switch ( type ) {
case 0x00 :
if ( pos = = 0xffffffff ) {
cdrom_log ( " CD-ROM %i: (type 0) Search from current position \n " , dev - > id ) ;
pos = dev - > seek_pos ;
}
dev - > seek_pos = pos ;
break ;
case 0x40 :
m = bcd2bin ( ( pos > > 24 ) & 0xff ) ;
s = bcd2bin ( ( pos > > 16 ) & 0xff ) ;
f = bcd2bin ( ( pos > > 8 ) & 0xff ) ;
if ( pos = = 0xffffffff ) {
cdrom_log ( " CD-ROM %i: (type 1) Search from current position \n " , dev - > id ) ;
pos = dev - > seek_pos ;
} else
pos = MSFtoLBA ( m , s , f ) - 150 ;
dev - > seek_pos = pos ;
break ;
case 0x80 :
dev - > seek_pos = ( pos > > 24 ) & 0xff ;
break ;
2023-06-26 12:47:04 -04:00
default :
break ;
2023-01-07 23:48:45 +01:00
}
2024-02-06 21:18:25 +01:00
dev - > audio_muted_soft = 0 ;
2023-01-07 23:48:45 +01:00
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from . */
if ( ! ( dev - > ops - > track_type ( dev , pos ) & CD_TRACK_AUDIO ) ) {
cdrom_log ( " CD-ROM %i: LBA %08X not on an audio track \n " , dev - > id , pos ) ;
cdrom_stop ( dev ) ;
return 0 ;
}
dev - > cd_buflen = 0 ;
return 1 ;
}
2018-10-30 13:32:25 +01:00
void
cdrom_audio_pause_resume ( cdrom_t * dev , uint8_t resume )
{
if ( ( dev - > cd_status = = CD_STATUS_PLAYING ) | | ( dev - > cd_status = = CD_STATUS_PAUSED ) )
2022-02-22 22:04:40 +01:00
dev - > cd_status = ( dev - > cd_status & 0xfe ) | ( resume & 0x01 ) ;
2018-10-30 13:32:25 +01:00
}
2024-12-31 04:37:21 +01:00
static void
cdrom_get_subchannel ( cdrom_t * dev , uint32_t lba , subchannel_t * subc , int cooked )
{
uint8_t * scb = dev - > subch_buffer ;
uint8_t q [ 16 ] = { 0 } ;
if ( ( lba = = dev - > seek_pos ) & & ( dev - > cd_status = = CD_STATUS_PLAYING ) ) {
for ( int i = 0 ; i < 12 ; i + + )
for ( int j = 0 ; j < 8 ; j + + )
q [ i ] | = ( ( scb [ ( i < < 3 ) + j ] > > 6 ) & 0x01 ) < < ( 7 - j ) ;
if ( cooked ) {
uint8_t temp = ( q [ 0 ] > > 4 ) | ( ( q [ 0 ] & 0xf ) < < 4 ) ;
q [ 0 ] = temp ;
for ( int i = 1 ; i < 10 ; i + + ) {
temp = bcd2bin ( q [ i ] ) ;
q [ i ] = temp ;
}
}
subc - > attr = q [ 0 ] ;
subc - > track = q [ 1 ] ;
subc - > index = q [ 2 ] ;
subc - > rel_m = q [ 3 ] ;
subc - > rel_s = q [ 4 ] ;
subc - > rel_f = q [ 5 ] ;
subc - > abs_m = q [ 7 ] ;
subc - > abs_s = q [ 8 ] ;
subc - > abs_f = q [ 9 ] ;
} else if ( ( dev - > ops ! = NULL ) & & ( dev - > ops - > get_subchannel ! = NULL ) ) {
dev - > ops - > get_subchannel ( dev , lba , subc ) ;
if ( ! cooked ) {
uint8_t temp = ( q [ 0 ] > > 4 ) | ( ( q [ 0 ] & 0xf ) < < 4 ) ;
q [ 0 ] = temp ;
subc - > attr = ( subc - > attr > > 4 ) | ( ( subc - > attr & 0xf ) < < 4 ) ;
subc - > track = bin2bcd ( subc - > track ) ;
subc - > index = bin2bcd ( subc - > index ) ;
subc - > rel_m = bin2bcd ( subc - > rel_m ) ;
subc - > rel_s = bin2bcd ( subc - > rel_s ) ;
subc - > rel_f = bin2bcd ( subc - > rel_f ) ;
subc - > abs_m = bin2bcd ( subc - > abs_m ) ;
subc - > abs_s = bin2bcd ( subc - > abs_s ) ;
subc - > abs_f = bin2bcd ( subc - > abs_f ) ;
}
}
}
2018-10-30 13:32:25 +01:00
uint8_t
2024-12-31 04:37:21 +01:00
cdrom_get_current_status ( cdrom_t * dev )
2018-10-30 13:32:25 +01:00
{
2022-09-18 17:11:56 -04:00
uint8_t ret ;
2018-10-30 13:32:25 +01:00
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
2022-02-22 22:04:40 +01:00
ret = 0x15 ;
2018-10-17 05:29:48 +02:00
else {
2022-02-22 22:04:40 +01:00
if ( dev - > cd_status = = CD_STATUS_PLAYING )
ret = 0x11 ;
else if ( dev - > cd_status = = CD_STATUS_PAUSED )
ret = 0x12 ;
else
ret = 0x13 ;
2018-10-30 13:32:25 +01:00
}
2024-12-31 04:37:21 +01:00
return ret ;
}
2022-10-29 06:44:30 +02:00
2024-12-31 04:37:21 +01:00
void
cdrom_get_current_subchannel ( cdrom_t * dev , uint8_t * b , int msf )
{
subchannel_t subc ;
uint32_t dat ;
2022-10-29 06:44:30 +02:00
2024-12-31 04:37:21 +01:00
cdrom_get_subchannel ( dev , dev - > seek_pos , & subc , 1 ) ;
cdrom_log ( " CD-ROM %i: Returned subchannel absolute at %02i:%02i.%02i, "
" relative at %02i:%02i.%02i, seek pos = %08x, cd_end = %08x. \n " ,
dev - > id , subc . abs_m , subc . abs_s , subc . abs_f , subc . rel_m , subc . rel_s , subc . rel_f ,
dev - > seek_pos , dev - > cd_end ) ;
/* Format code. */
switch ( b [ 0 ] ) {
/* Mode 0 = Q subchannel mode, first 16 bytes are indentical to mode 1 (current position),
the rest are stuff like ISRC etc . , which can be all zeroes . */
case 0x01 :
/* Current position. */
b [ 1 ] = subc . attr ;
b [ 2 ] = subc . track ;
b [ 3 ] = subc . index ;
if ( msf ) {
b [ 4 ] = b [ 8 ] = 0x00 ;
/* NEC CDR-260 speaks BCD. */
if ( ( dev - > type = = CDROM_TYPE_NEC_260_100 ) | | ( dev - > type = = CDROM_TYPE_NEC_260_101 ) ) {
/* NEC */
b [ 5 ] = bin2bcd ( subc . abs_m ) ;
b [ 6 ] = bin2bcd ( subc . abs_s ) ;
b [ 7 ] = bin2bcd ( subc . abs_f ) ;
b [ 9 ] = bin2bcd ( subc . rel_m ) ;
b [ 10 ] = bin2bcd ( subc . rel_s ) ;
b [ 11 ] = bin2bcd ( subc . rel_f ) ;
} else {
b [ 5 ] = subc . abs_m ;
b [ 6 ] = subc . abs_s ;
b [ 7 ] = subc . abs_f ;
b [ 9 ] = subc . rel_m ;
b [ 10 ] = subc . rel_s ;
b [ 11 ] = subc . rel_f ;
}
} else {
dat = MSFtoLBA ( subc . abs_m , subc . abs_s , subc . abs_f ) - 150 ;
b [ 4 ] = ( dat > > 24 ) & 0xff ;
b [ 5 ] = ( dat > > 16 ) & 0xff ;
b [ 6 ] = ( dat > > 8 ) & 0xff ;
b [ 7 ] = dat & 0xff ;
dat = MSFtoLBA ( subc . rel_m , subc . rel_s , subc . rel_f ) ;
b [ 8 ] = ( dat > > 24 ) & 0xff ;
b [ 9 ] = ( dat > > 16 ) & 0xff ;
b [ 10 ] = ( dat > > 8 ) & 0xff ;
b [ 11 ] = dat & 0xff ;
}
break ;
case 0x02 :
/* UPC - TODO: Finding and reporting the actual UPC data. */
memset ( & ( b [ 1 ] ) , 0x00 , 19 ) ;
memset ( & ( b [ 5 ] ) , 0x30 , 13 ) ;
/* NEC CDR-260 speaks BCD. */
if ( ( dev - > type = = CDROM_TYPE_NEC_260_100 ) | | ( dev - > type = = CDROM_TYPE_NEC_260_101 ) )
/* NEC */
b [ 19 ] = bin2bcd ( subc . abs_f ) ;
else
b [ 19 ] = subc . abs_f ;
break ;
case 0x03 :
/* ISRC - TODO: Finding and reporting the actual ISRC data. */
memset ( & ( b [ 1 ] ) , 0x00 , 19 ) ;
memset ( & ( b [ 5 ] ) , 0x30 , 12 ) ;
/* NEC CDR-260 speaks BCD. */
if ( ( dev - > type = = CDROM_TYPE_NEC_260_100 ) | | ( dev - > type = = CDROM_TYPE_NEC_260_101 ) )
/* NEC */
b [ 18 ] = bin2bcd ( subc . abs_f ) ;
else
b [ 18 ] = subc . abs_f ;
break ;
default :
cdrom_log ( " b[0] = %02X \n " , b [ 0 ] ) ;
break ;
2018-10-30 13:32:25 +01:00
}
}
2023-01-07 23:48:45 +01:00
void
cdrom_get_current_subchannel_sony ( cdrom_t * dev , uint8_t * b , int msf )
{
subchannel_t subc ;
uint32_t dat ;
2024-12-31 04:37:21 +01:00
cdrom_get_subchannel ( dev , dev - > seek_pos , & subc , 1 ) ;
2023-01-07 23:48:45 +01:00
2023-09-20 20:29:32 +02:00
cdrom_log ( " CD-ROM %i: Returned subchannel at %02i:%02i.%02i, seek pos = %08x, cd_end = %08x, msf = %x. \n " , dev - > id , subc . abs_m , subc . abs_s , subc . abs_f , dev - > seek_pos , dev - > cd_end , msf ) ;
2023-01-07 23:48:45 +01:00
2023-09-20 20:29:32 +02:00
b [ 0 ] = subc . attr ;
b [ 1 ] = subc . track ;
b [ 2 ] = subc . index ;
2023-01-07 23:48:45 +01:00
if ( msf ) {
2023-09-20 20:29:32 +02:00
b [ 3 ] = subc . rel_m ;
b [ 4 ] = subc . rel_s ;
b [ 5 ] = subc . rel_f ;
b [ 6 ] = subc . abs_m ;
b [ 7 ] = subc . abs_s ;
b [ 8 ] = subc . abs_f ;
2023-01-07 23:48:45 +01:00
} else {
dat = MSFtoLBA ( subc . rel_m , subc . rel_s , subc . rel_f ) ;
2023-09-20 20:29:32 +02:00
b [ 3 ] = ( dat > > 16 ) & 0xff ;
b [ 4 ] = ( dat > > 8 ) & 0xff ;
b [ 5 ] = dat & 0xff ;
2023-01-07 23:48:45 +01:00
dat = MSFtoLBA ( subc . abs_m , subc . abs_s , subc . abs_f ) - 150 ;
2023-09-20 20:29:32 +02:00
b [ 6 ] = ( dat > > 16 ) & 0xff ;
b [ 7 ] = ( dat > > 8 ) & 0xff ;
b [ 8 ] = dat & 0xff ;
2023-01-07 23:48:45 +01:00
}
}
2023-09-20 20:29:32 +02:00
uint8_t
cdrom_get_audio_status_pioneer ( cdrom_t * dev , uint8_t * b )
{
uint8_t ret ;
subchannel_t subc ;
2024-12-31 04:37:21 +01:00
cdrom_get_subchannel ( dev , dev - > seek_pos , & subc , 0 ) ;
2023-09-20 20:29:32 +02:00
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
ret = 0x05 ;
else {
if ( dev - > cd_status = = CD_STATUS_PLAYING )
ret = dev - > sound_on ? 0x00 : 0x02 ;
else if ( dev - > cd_status = = CD_STATUS_PAUSED )
ret = 0x01 ;
else
ret = 0x03 ;
}
b [ 0 ] = 0 ;
2024-12-31 04:37:21 +01:00
b [ 1 ] = subc . abs_m ;
b [ 2 ] = subc . abs_s ;
b [ 3 ] = subc . abs_f ;
2023-09-20 20:29:32 +02:00
return ret ;
}
2023-01-07 23:48:45 +01:00
uint8_t
cdrom_get_audio_status_sony ( cdrom_t * dev , uint8_t * b , int msf )
{
uint8_t ret ;
subchannel_t subc ;
uint32_t dat ;
2024-12-31 04:37:21 +01:00
cdrom_get_subchannel ( dev , dev - > seek_pos , & subc , 1 ) ;
2023-01-07 23:48:45 +01:00
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
ret = 0x05 ;
else {
if ( dev - > cd_status = = CD_STATUS_PLAYING )
ret = dev - > sound_on ? 0x00 : 0x02 ;
else if ( dev - > cd_status = = CD_STATUS_PAUSED )
ret = 0x01 ;
else
ret = 0x03 ;
}
if ( msf ) {
b [ 0 ] = 0 ;
b [ 1 ] = subc . abs_m ;
b [ 2 ] = subc . abs_s ;
b [ 3 ] = subc . abs_f ;
} else {
dat = MSFtoLBA ( subc . abs_m , subc . abs_s , subc . abs_f ) - 150 ;
b [ 0 ] = ( dat > > 24 ) & 0xff ;
b [ 1 ] = ( dat > > 16 ) & 0xff ;
b [ 2 ] = ( dat > > 8 ) & 0xff ;
b [ 3 ] = dat & 0xff ;
}
return ret ;
}
2023-09-20 20:29:32 +02:00
void
cdrom_get_current_subcodeq ( cdrom_t * dev , uint8_t * b )
{
subchannel_t subc ;
2024-12-31 04:37:21 +01:00
cdrom_get_subchannel ( dev , dev - > seek_pos , & subc , 0 ) ;
2023-09-20 20:29:32 +02:00
b [ 0 ] = subc . attr ;
2024-12-31 04:37:21 +01:00
b [ 1 ] = subc . track ;
b [ 2 ] = subc . index ;
b [ 3 ] = subc . rel_m ;
b [ 4 ] = subc . rel_s ;
b [ 5 ] = subc . rel_f ;
b [ 6 ] = subc . abs_m ;
b [ 7 ] = subc . abs_s ;
b [ 8 ] = subc . abs_f ;
2023-09-20 20:29:32 +02:00
}
2020-03-24 01:00:28 +01:00
uint8_t
cdrom_get_current_subcodeq_playstatus ( cdrom_t * dev , uint8_t * b )
{
2023-09-20 20:29:32 +02:00
uint8_t ret ;
2020-03-24 01:00:28 +01:00
2024-12-31 04:37:21 +01:00
cdrom_get_current_subcodeq ( dev , b ) ;
2022-02-20 02:26:27 -05:00
2023-09-20 20:29:32 +02:00
if ( ( dev - > cd_status = = CD_STATUS_DATA_ONLY ) | |
( dev - > cd_status = = CD_STATUS_PLAYING_COMPLETED ) | |
( dev - > cd_status = = CD_STATUS_STOPPED ) )
2022-02-22 22:04:40 +01:00
ret = 0x03 ;
2022-12-04 20:53:03 +01:00
else
ret = ( dev - > cd_status = = CD_STATUS_PLAYING ) ? 0x00 : dev - > audio_op ;
2020-03-24 01:00:28 +01:00
2024-02-06 21:18:25 +01:00
/*If a valid audio track is detected with audio on, unmute it.*/
if ( dev - > ops - > track_type ( dev , dev - > seek_pos ) & CD_TRACK_AUDIO )
dev - > audio_muted_soft = 0 ;
2024-12-31 04:37:21 +01:00
cdrom_log ( " SubCodeQ: Play Status: Seek LBA=%08x, CDEND=%08x, mute=%d. \n " ,
dev - > seek_pos , dev - > cd_end , dev - > audio_muted_soft ) ;
2020-03-24 01:00:28 +01:00
return ret ;
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
static void
read_toc_identify_sessions ( raw_track_info_t * rti , int num , unsigned char * b )
2018-10-30 13:32:25 +01:00
{
2024-12-31 04:37:21 +01:00
/* Bytes 2 and 3 = Number of first and last sessions */
b [ 2 ] = 0xff ;
b [ 3 ] = 0x00 ;
2020-07-20 03:18:56 +02:00
2024-12-31 04:37:21 +01:00
for ( int i = ( num - 1 ) ; i > = 0 ; i - - ) {
if ( rti [ i ] . session < b [ 2 ] )
b [ 2 ] = rti [ i ] . session ;
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
for ( int i = 0 ; i < num ; i + + ) {
if ( rti [ i ] . session > b [ 3 ] )
b [ 3 ] = rti [ i ] . session ;
}
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
static int
find_track ( raw_track_info_t * trti , int num , int first )
{
int ret = - 1 ;
2020-07-20 03:18:56 +02:00
2024-12-31 04:37:21 +01:00
if ( first ) {
for ( int i = 0 ; i < num ; i + + )
if ( ( trti [ i ] . point > = 1 ) & & ( trti [ i ] . point < = 99 ) ) {
ret = i ;
break ;
}
} else {
for ( int i = ( num - 1 ) ; i > = 0 ; i - - )
if ( ( trti [ i ] . point > = 1 ) & & ( trti [ i ] . point < = 99 ) ) {
ret = i ;
2022-02-22 22:04:40 +01:00
break ;
}
2018-10-30 13:32:25 +01:00
}
2024-12-31 04:37:21 +01:00
return ret ;
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
static int
find_last_lead_out ( raw_track_info_t * trti , int num )
{
int ret = - 1 ;
2022-10-29 06:44:30 +02:00
2024-12-31 04:37:21 +01:00
for ( int i = ( num - 1 ) ; i > = 0 ; i - - )
if ( trti [ i ] . point = = 0xa2 ) {
ret = i ;
break ;
2022-02-22 22:04:40 +01:00
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
return ret ;
2018-10-30 13:32:25 +01:00
}
static int
2024-12-31 04:37:21 +01:00
find_specific_track ( raw_track_info_t * trti , int num , int track )
2018-10-30 13:32:25 +01:00
{
2024-12-31 04:37:21 +01:00
int ret = - 1 ;
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
if ( ( track > = 1 ) & & ( track < = 99 ) ) {
for ( int i = ( num - 1 ) ; i > = 0 ; i - - )
if ( trti [ i ] . point = = track ) {
ret = i ;
break ;
}
}
2020-07-20 03:18:56 +02:00
2024-12-31 04:37:21 +01:00
return ret ;
}
2020-07-20 03:18:56 +02:00
2024-12-31 04:37:21 +01:00
static int
read_toc_normal ( cdrom_t * dev , unsigned char * b , unsigned char start_track , int msf , int sony )
{
uint8_t rti [ 65536 ] = { 0 } ;
uint8_t prti [ 65536 ] = { 0 } ;
raw_track_info_t * trti = ( raw_track_info_t * ) rti ;
raw_track_info_t * tprti = ( raw_track_info_t * ) prti ;
int num = 0 ;
int len = 4 ;
int s = - 1 ;
cdrom_log ( " read_toc_normal(%016 " PRIXPTR " , %016 " PRIXPTR " , %02X, %i) \n " ,
( uintptr_t ) dev , ( uintptr_t ) b , start_track , msf , sony ) ;
dev - > ops - > get_raw_track_info ( dev , & num , ( raw_track_info_t * ) rti ) ;
if ( num > 0 ) {
int j = 0 ;
for ( int i = 0 ; i < num ; i + + ) {
if ( ( trti [ i ] . point > = 0x01 ) & & ( trti [ i ] . point < = 0x63 ) ) {
tprti [ j ] = trti [ i ] ;
if ( ( s = = - 1 ) & & ( tprti [ j ] . point > = start_track ) )
s = j ;
cdrom_log ( " Sorted %03i = Unsorted %03i (s = %03i) \n " , j , i , s ) ;
j + + ;
}
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
/* Bytes 2 and 3 = Number of first and last tracks found before lead out */
b [ 2 ] = tprti [ 0 ] . point ;
b [ 3 ] = tprti [ j - 1 ] . point ;
for ( int i = ( num - 1 ) ; i > = 0 ; i - - ) {
if ( trti [ i ] . point = = 0xa2 ) {
tprti [ j ] = trti [ i ] ;
tprti [ j ] . point = 0xaa ;
if ( ( s = = - 1 ) & & ( tprti [ j ] . point > = start_track ) )
s = j ;
cdrom_log ( " Sorted %03i = Unsorted %03i (s = %03i) \n " , j , i , s ) ;
j + + ;
break ;
}
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
if ( s ! = - 1 ) for ( int i = s ; i < j ; i + + ) {
2024-12-31 04:40:14 +01:00
# ifdef ENABLE_CDROM_LOG
2024-12-31 04:37:21 +01:00
uint8_t * c = & ( b [ len ] ) ;
2024-12-31 04:40:14 +01:00
# endif
2024-12-31 04:37:21 +01:00
if ( ! sony )
b [ len + + ] = 0 ; /* Reserved */
b [ len + + ] = tprti [ i ] . adr_ctl ; /* ADR/CTL */
b [ len + + ] = tprti [ i ] . point ; /* Track number */
if ( ! sony )
b [ len + + ] = 0 ; /* Reserved */
if ( msf ) {
b [ len + + ] = 0 ;
/* NEC CDR-260 speaks BCD. */
if ( ( dev - > type = = CDROM_TYPE_NEC_260_100 ) | | ( dev - > type = = CDROM_TYPE_NEC_260_101 ) ) {
int m = tprti [ i ] . pm ;
int s = tprti [ i ] . ps ;
int f = tprti [ i ] . pf ;
msf_to_bcd ( & m , & s , & f ) ;
b [ len + + ] = m ;
b [ len + + ] = s ;
b [ len + + ] = f ;
} else {
b [ len + + ] = tprti [ i ] . pm ;
b [ len + + ] = tprti [ i ] . ps ;
b [ len + + ] = tprti [ i ] . pf ;
}
} else {
uint32_t temp = MSFtoLBA ( tprti [ i ] . pm , tprti [ i ] . ps , tprti [ i ] . pf ) - 150 ;
2020-07-20 03:18:56 +02:00
2024-12-31 04:37:21 +01:00
b [ len + + ] = temp > > 24 ;
b [ len + + ] = temp > > 16 ;
b [ len + + ] = temp > > 8 ;
b [ len + + ] = temp ;
}
2022-10-29 06:44:30 +02:00
2024-12-31 04:40:14 +01:00
# ifdef ENABLE_CDROM_LOG
2024-12-31 04:37:21 +01:00
cdrom_log ( " Track %02X: %02X %02X %02X %02X %02X %02X %02X %02X \n " ,
i , c [ 0 ] , c [ 1 ] , c [ 2 ] , c [ 3 ] , c [ 4 ] , c [ 5 ] , c [ 6 ] , c [ 7 ] ) ;
2024-12-31 04:40:14 +01:00
# endif
2022-10-29 06:44:30 +02:00
}
2024-12-31 04:37:21 +01:00
} else
b [ 2 ] = b [ 3 ] = 0 ;
2018-10-30 13:32:25 +01:00
return len ;
}
static int
2024-12-31 04:37:21 +01:00
read_toc_session ( cdrom_t * dev , unsigned char * b , int msf )
2018-10-30 13:32:25 +01:00
{
2024-12-31 04:37:21 +01:00
uint8_t rti [ 65536 ] = { 0 } ;
raw_track_info_t * t = ( raw_track_info_t * ) rti ;
raw_track_info_t * first = NULL ;
int num = 0 ;
int len = 4 ;
dev - > ops - > get_raw_track_info ( dev , & num , ( raw_track_info_t * ) rti ) ;
2018-10-30 13:32:25 +01:00
2020-07-20 03:18:56 +02:00
/* Bytes 2 and 3 = Number of first and last sessions */
2024-12-31 04:37:21 +01:00
read_toc_identify_sessions ( ( raw_track_info_t * ) rti , num , b ) ;
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
cdrom_log ( " read_toc_session(%016 " PRIXPTR " , %016 " PRIXPTR " , %i) \n " ,
( uintptr_t ) dev , ( uintptr_t ) b , msf ) ;
2024-11-25 21:23:28 +01:00
2024-12-31 04:37:21 +01:00
if ( num ! = 0 ) {
for ( int i = 0 ; i < num ; i + + ) if ( ( t [ i ] . session = = b [ 3 ] ) & & ( t [ i ] . point > = 0x01 ) & & ( t [ i ] . point < = 0x63 ) ) {
first = & ( t [ i ] ) ;
break ;
2024-11-25 21:23:28 +01:00
}
2024-12-31 04:37:21 +01:00
if ( first ! = NULL ) {
b [ len + + ] = 0x00 ;
b [ len + + ] = first - > adr_ctl ;
b [ len + + ] = first - > point ;
b [ len + + ] = 0x00 ;
if ( msf ) {
b [ len + + ] = 0x00 ;
/* NEC CDR-260 speaks BCD. */
if ( ( dev - > type = = CDROM_TYPE_NEC_260_100 ) | | ( dev - > type = = CDROM_TYPE_NEC_260_101 ) ) { /*NEC*/
int m = first - > pm ;
int s = first - > ps ;
int f = first - > pf ;
msf_to_bcd ( & m , & s , & f ) ;
b [ len + + ] = m ;
b [ len + + ] = s ;
b [ len + + ] = f ;
} else {
b [ len + + ] = first - > pm ;
b [ len + + ] = first - > ps ;
b [ len + + ] = first - > pf ;
}
} else {
uint32_t temp = MSFtoLBA ( first - > pm , first - > ps , first - > pf ) - 150 ;
2024-11-25 21:23:28 +01:00
2024-12-31 04:37:21 +01:00
b [ len + + ] = temp > > 24 ;
b [ len + + ] = temp > > 16 ;
b [ len + + ] = temp > > 8 ;
b [ len + + ] = temp ;
}
2024-11-25 21:23:28 +01:00
}
2018-10-30 13:32:25 +01:00
}
2024-12-31 04:37:21 +01:00
if ( len = = 4 )
memset ( & ( b [ len + = 8 ] ) , 0x00 , 8 ) ;
2018-10-30 13:32:25 +01:00
return len ;
}
2023-01-07 23:48:45 +01:00
static int
2024-12-31 04:37:21 +01:00
read_toc_raw ( cdrom_t * dev , unsigned char * b , unsigned char start_track )
2023-01-07 23:48:45 +01:00
{
2024-12-31 04:37:21 +01:00
uint8_t rti [ 65536 ] = { 0 } ;
raw_track_info_t * t = ( raw_track_info_t * ) rti ;
int num = 0 ;
int len = 4 ;
2023-01-07 23:48:45 +01:00
2024-12-31 04:37:21 +01:00
/* Bytes 2 and 3 = Number of first and last sessions */
read_toc_identify_sessions ( ( raw_track_info_t * ) rti , num , b ) ;
2023-01-07 23:48:45 +01:00
2024-12-31 04:37:21 +01:00
cdrom_log ( " read_toc_raw(%016 " PRIXPTR " , %016 " PRIXPTR " , %02X) \n " ,
( uintptr_t ) dev , ( uintptr_t ) b , start_track ) ;
2023-01-07 23:48:45 +01:00
2024-12-31 04:37:21 +01:00
dev - > ops - > get_raw_track_info ( dev , & num , ( raw_track_info_t * ) rti ) ;
2023-01-07 23:48:45 +01:00
2024-12-31 04:37:21 +01:00
if ( num ! = 0 ) for ( int i = 0 ; i < num ; i + + )
if ( t [ i ] . session > = start_track ) {
memcpy ( & ( b [ len ] ) , & ( t [ i ] ) , 11 ) ;
len + = 11 ;
2023-01-07 23:48:45 +01:00
}
return len ;
}
2018-10-30 13:32:25 +01:00
int
cdrom_read_toc ( cdrom_t * dev , unsigned char * b , int type , unsigned char start_track , int msf , int max_len )
{
int len ;
2022-09-18 17:11:56 -04:00
switch ( type ) {
2022-02-22 22:04:40 +01:00
case CD_TOC_NORMAL :
2024-12-31 04:37:21 +01:00
len = read_toc_normal ( dev , b , start_track , msf , 0 ) ;
2022-02-22 22:04:40 +01:00
break ;
case CD_TOC_SESSION :
len = read_toc_session ( dev , b , msf ) ;
break ;
case CD_TOC_RAW :
2024-12-31 04:37:21 +01:00
len = read_toc_raw ( dev , b , start_track ) ;
2022-02-22 22:04:40 +01:00
break ;
default :
cdrom_log ( " CD-ROM %i: Unknown TOC read type: %i \n " , dev - > id , type ) ;
return 0 ;
2018-10-30 13:32:25 +01:00
}
len = MIN ( len , max_len ) ;
b [ 0 ] = ( uint8_t ) ( ( ( len - 2 ) > > 8 ) & 0xff ) ;
b [ 1 ] = ( uint8_t ) ( ( len - 2 ) & 0xff ) ;
return len ;
}
2023-01-07 23:48:45 +01:00
int
cdrom_read_toc_sony ( cdrom_t * dev , unsigned char * b , unsigned char start_track , int msf , int max_len )
{
int len ;
2024-12-31 04:37:21 +01:00
len = read_toc_normal ( dev , b , start_track , msf , 1 ) ;
2023-01-07 23:48:45 +01:00
len = MIN ( len , max_len ) ;
b [ 0 ] = ( uint8_t ) ( ( ( len - 2 ) > > 8 ) & 0xff ) ;
b [ 1 ] = ( uint8_t ) ( ( len - 2 ) & 0xff ) ;
return len ;
}
2024-12-31 04:37:21 +01:00
# ifdef USE_CDROM_MITSUMI
2022-11-05 20:15:00 -04:00
/* New API calls for Mitsumi CD-ROM. */
2022-02-14 19:47:48 +01:00
void
cdrom_get_track_buffer ( cdrom_t * dev , uint8_t * buf )
{
2024-12-31 04:37:21 +01:00
uint8_t rti [ 65536 ] = { 0 } ;
raw_track_info_t * trti = ( raw_track_info_t * ) rti ;
int num = 0 ;
int first = - 1 ;
int last = - 1 ;
2022-02-14 19:47:48 +01:00
2024-12-31 04:37:21 +01:00
if ( dev ! = NULL )
dev - > ops - > get_raw_track_info ( dev , & num , ( raw_track_info_t * ) rti ) ;
if ( num > 0 ) {
first = find_track ( trti , num , 1 ) ;
last = find_track ( trti , num , 0 ) ;
}
if ( first ! = - 1 ) {
buf [ 0 ] = trti [ first ] . point ;
buf [ 2 ] = trti [ first ] . pm ;
buf [ 3 ] = trti [ first ] . ps ;
buf [ 4 ] = trti [ first ] . pf ;
} else {
buf [ 0 ] = 0x01 ;
buf [ 2 ] = 0x00 ;
buf [ 3 ] = 0x02 ;
buf [ 4 ] = 0x00 ;
}
if ( last ! = - 1 ) {
buf [ 1 ] = trti [ last ] . point ;
buf [ 5 ] = trti [ first ] . pm ;
buf [ 6 ] = trti [ first ] . ps ;
buf [ 7 ] = trti [ first ] . pf ;
} else {
buf [ 1 ] = 0x01 ;
buf [ 5 ] = 0x00 ;
buf [ 6 ] = 0x02 ;
buf [ 7 ] = 0x00 ;
}
buf [ 8 ] = 0x00 ;
2022-02-14 19:47:48 +01:00
}
2022-11-05 20:15:00 -04:00
void
cdrom_get_q ( cdrom_t * dev , uint8_t * buf , int * curtoctrk , uint8_t mode )
{
track_info_t ti ;
2023-05-16 15:43:20 -04:00
int first_track ;
int last_track ;
2022-11-05 20:15:00 -04:00
if ( dev ! = NULL ) {
dev - > ops - > get_tracks ( dev , & first_track , & last_track ) ;
dev - > ops - > get_track_info ( dev , * curtoctrk , 0 , & ti ) ;
buf [ 0 ] = ( ti . attr < < 4 ) & 0xf0 ;
buf [ 1 ] = ti . number ;
2023-01-07 23:48:45 +01:00
buf [ 2 ] = bin2bcd ( * curtoctrk + 1 ) ;
2022-11-05 20:15:00 -04:00
buf [ 3 ] = ti . m ;
buf [ 4 ] = ti . s ;
buf [ 5 ] = ti . f ;
buf [ 6 ] = 0x00 ;
dev - > ops - > get_track_info ( dev , 1 , 0 , & ti ) ;
buf [ 7 ] = ti . m ;
buf [ 8 ] = ti . s ;
buf [ 9 ] = ti . f ;
if ( * curtoctrk > = ( last_track + 1 ) )
* curtoctrk = 0 ;
else if ( mode )
* curtoctrk = * curtoctrk + 1 ;
} else
memset ( buf , 0x00 , 10 ) ;
}
uint8_t
cdrom_mitsumi_audio_play ( cdrom_t * dev , uint32_t pos , uint32_t len )
{
track_info_t ti ;
if ( dev - > cd_status = = CD_STATUS_DATA_ONLY )
return 0 ;
cdrom_log ( " CD-ROM 0: Play Mitsumi audio - %08X %08X \n " , pos , len ) ;
dev - > ops - > get_track_info ( dev , pos , 0 , & ti ) ;
pos = MSFtoLBA ( ti . m , ti . s , ti . f ) - 150 ;
dev - > ops - > get_track_info ( dev , len , 1 , & ti ) ;
len = MSFtoLBA ( ti . m , ti . s , ti . f ) - 150 ;
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from . */
if ( ! ( dev - > ops - > track_type ( dev , pos ) & CD_TRACK_AUDIO ) ) {
cdrom_log ( " CD-ROM %i: LBA %08X not on an audio track \n " , dev - > id , pos ) ;
cdrom_stop ( dev ) ;
return 0 ;
}
dev - > seek_pos = pos ;
dev - > cd_end = len ;
dev - > cd_status = CD_STATUS_PLAYING ;
dev - > cd_buflen = 0 ;
return 1 ;
}
2024-12-31 04:37:21 +01:00
# endif
2022-11-05 20:15:00 -04:00
2023-01-07 23:48:45 +01:00
uint8_t
2020-03-24 01:00:28 +01:00
cdrom_read_disc_info_toc ( cdrom_t * dev , unsigned char * b , unsigned char track , int type )
{
2024-12-31 04:37:21 +01:00
uint8_t rti [ 65536 ] = { 0 } ;
raw_track_info_t * trti = ( raw_track_info_t * ) rti ;
int num = 0 ;
int first = - 1 ;
int last = - 1 ;
int t = - 1 ;
uint32_t temp ;
uint8_t ret = 1 ;
2020-03-24 01:00:28 +01:00
2024-12-31 04:37:21 +01:00
if ( dev ! = NULL )
dev - > ops - > get_raw_track_info ( dev , & num , ( raw_track_info_t * ) rti ) ;
cdrom_log ( " Read DISC Info TOC Type = %d, track = %d \n " , type , track ) ;
2020-03-24 01:00:28 +01:00
switch ( type ) {
2022-02-22 22:04:40 +01:00
case 0 :
2024-12-31 04:37:21 +01:00
if ( num > 0 ) {
first = find_track ( trti , num , 1 ) ;
last = find_track ( trti , num , 0 ) ;
}
if ( ( first = = - 1 ) | | ( last = = - 1 ) )
ret = 0 ;
else {
b [ 0 ] = bin2bcd ( first ) ;
b [ 1 ] = bin2bcd ( last ) ;
b [ 2 ] = 0x00 ;
b [ 3 ] = 0x00 ;
cdrom_log ( " CD-ROM %i: Returned Toshiba/NEC disc information (type 0) at %02i:%02i \n " ,
dev - > id , b [ 0 ] , b [ 1 ] ) ;
}
2022-02-22 22:04:40 +01:00
break ;
case 1 :
2024-12-31 04:37:21 +01:00
if ( num > 0 )
t = find_last_lead_out ( trti , num ) ;
if ( t = = - 1 )
ret = 0 ;
else {
b [ 0 ] = bin2bcd ( trti [ t ] . pm ) ;
b [ 1 ] = bin2bcd ( trti [ t ] . ps ) ;
b [ 2 ] = bin2bcd ( trti [ t ] . pf ) ;
b [ 3 ] = 0x00 ;
cdrom_log ( " CD-ROM %i: Returned Toshiba/NEC disc information (type 1) at %02i:%02i.%02i \n " ,
dev - > id , b [ 0 ] , b [ 1 ] , b [ 2 ] ) ;
}
2022-02-22 22:04:40 +01:00
break ;
case 2 :
2024-12-31 04:37:21 +01:00
if ( num > 0 )
t = find_specific_track ( trti , num , bcd2bin ( track ) ) ;
if ( t = = - 1 )
ret = 0 ;
else {
b [ 0 ] = bin2bcd ( trti [ t ] . pm ) ;
b [ 1 ] = bin2bcd ( trti [ t ] . ps ) ;
b [ 2 ] = bin2bcd ( trti [ t ] . pf ) ;
b [ 3 ] = trti [ t ] . adr_ctl ;
cdrom_log ( " CD-ROM %i: Returned Toshiba/NEC disc information (type 2) at "
" %02i:%02i.%02i, track=%d, attr=%02x. \n " , dev - > id , b [ 0 ] , b [ 1 ] , b [ 2 ] , bcd2bin ( track ) , b [ 3 ] ) ;
}
2022-02-22 22:04:40 +01:00
break ;
2023-11-10 17:27:30 -03:00
case 3 : /* Undocumented on NEC CD-ROM's, from information based on sr_vendor.c from the Linux kernel */
2023-10-24 20:15:08 +02:00
switch ( dev - > type ) {
case CDROM_TYPE_NEC_25_10a :
case CDROM_TYPE_NEC_38_103 :
case CDROM_TYPE_NEC_75_103 :
case CDROM_TYPE_NEC_77_106 :
case CDROM_TYPE_NEC_211_100 :
case CDROM_TYPE_NEC_464_105 :
2024-12-31 04:37:21 +01:00
b [ 0x0e ] = 0x00 ;
if ( num > 0 )
first = find_track ( trti , num , 1 ) ;
if ( first = = - 1 )
ret = 0 ;
else {
temp = MSFtoLBA ( trti [ first ] . pm , trti [ first ] . ps , trti [ first ] . pf ) - 150 ;
b [ 0x0f ] = temp > > 24 ;
b [ 0x10 ] = temp > > 16 ;
b [ 0x11 ] = temp > > 8 ;
b [ 0x12 ] = temp ;
}
2023-10-24 20:15:08 +02:00
break ;
default :
2024-12-31 04:37:21 +01:00
b [ 0 ] = 0x00 ; /* Audio or CDROM disc. */
if ( num > 0 )
first = find_track ( trti , num , 1 ) ;
if ( first = = - 1 )
ret = 0 ;
else {
temp = MSFtoLBA ( trti [ first ] . pm , trti [ first ] . ps , trti [ first ] . pf ) - 150 ;
b [ 0x1 ] = temp > > 24 ;
b [ 0x2 ] = temp > > 16 ;
b [ 0x3 ] = temp > > 8 ;
}
2023-10-24 20:15:08 +02:00
break ;
}
2022-02-22 22:04:40 +01:00
break ;
2023-06-26 12:47:04 -04:00
default :
break ;
2020-03-24 01:00:28 +01:00
}
2023-01-07 23:48:45 +01:00
2024-12-31 04:37:21 +01:00
return ret ;
2020-03-24 01:00:28 +01:00
}
2018-10-30 13:32:25 +01:00
static int
2023-06-26 12:47:04 -04:00
track_type_is_valid ( UNUSED ( uint8_t id ) , int type , int flags , int audio , int mode2 )
2018-10-30 13:32:25 +01:00
{
2022-09-18 17:11:56 -04:00
if ( ! ( flags & 0x70 ) & & ( flags & 0xf8 ) ) { /* 0x08/0x80/0x88 are illegal modes */
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: [Any Mode] 0x08/0x80/0x88 are illegal modes \n " , id ) ;
return 0 ;
2018-10-30 13:32:25 +01:00
}
if ( ( type ! = 1 ) & & ! audio ) {
2022-02-22 22:04:40 +01:00
if ( ( flags & 0x06 ) = = 0x06 ) {
cdrom_log ( " CD-ROM %i: [Any Data Mode] Invalid error flags \n " , id ) ;
return 0 ;
}
if ( ( ( flags & 0x700 ) = = 0x300 ) | | ( ( flags & 0x700 ) > 0x400 ) ) {
cdrom_log ( " CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X) \n " , id , flags & 0x700 ) ;
return 0 ;
}
2022-09-18 17:11:56 -04:00
if ( ( flags & 0x18 ) = = 0x08 ) { /* EDC/ECC without user data is an illegal mode */
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode \n " , id ) ;
return 0 ;
}
2022-09-18 17:11:56 -04:00
if ( ( ( flags & 0xf0 ) = = 0x90 ) | | ( ( flags & 0xf0 ) = = 0xc0 ) ) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes \n " , id ) ;
return 0 ;
}
if ( ( ( type > 3 ) & & ( type ! = 8 ) ) | | ( mode2 & & ( mode2 & 0x03 ) ) ) {
2022-09-18 17:11:56 -04:00
if ( ( flags & 0xf0 ) = = 0x30 ) { /* 0x30/0x38 are illegal modes */
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes \n " , id ) ;
return 0 ;
}
2022-09-18 17:11:56 -04:00
if ( ( ( flags & 0xf0 ) = = 0xb0 ) | | ( ( flags & 0xf0 ) = = 0xd0 ) ) { /* 0xBx and 0xDx are illegal modes */
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes \n " , id ) ;
return 0 ;
}
}
2018-10-30 13:32:25 +01:00
}
return 1 ;
}
2024-10-27 13:17:55 -03:00
static int
2018-10-30 13:32:25 +01:00
read_audio ( cdrom_t * dev , uint32_t lba , uint8_t * b )
{
2024-12-31 04:37:21 +01:00
int ret = dev - > ops - > read_sector ( dev , raw_buffer , lba ) ;
2018-10-30 13:32:25 +01:00
memcpy ( b , raw_buffer , 2352 ) ;
cdrom_sector_size = 2352 ;
2024-10-27 13:17:55 -03:00
return ret ;
2018-10-30 13:32:25 +01:00
}
2024-12-31 04:37:21 +01:00
static void
process_mode1 ( cdrom_t * dev , int cdrom_sector_flags , uint8_t * b )
2018-10-30 13:32:25 +01:00
{
cdrom_sector_size = 0 ;
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x80 ) {
/* Sync */
cdrom_log ( " CD-ROM %i: [Mode 1] Sync \n " , dev - > id ) ;
memcpy ( b , raw_buffer , 12 ) ;
cdrom_sector_size + = 12 ;
b + = 12 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x20 ) {
/* Header */
cdrom_log ( " CD-ROM %i: [Mode 1] Header \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 12 , 4 ) ;
cdrom_sector_size + = 4 ;
b + = 4 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x40 ) {
/* Sub-header */
if ( ! ( cdrom_sector_flags & 0x10 ) ) {
/* No user data */
cdrom_log ( " CD-ROM %i: [Mode 1] Sub-header \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 16 , 8 ) ;
cdrom_sector_size + = 8 ;
b + = 8 ;
}
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x10 ) {
/* User data */
cdrom_log ( " CD-ROM %i: [Mode 1] User data \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 16 , 2048 ) ;
cdrom_sector_size + = 2048 ;
b + = 2048 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x08 ) {
/* EDC/ECC */
cdrom_log ( " CD-ROM %i: [Mode 1] EDC/ECC \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 2064 , 288 ) ;
cdrom_sector_size + = 288 ;
b + = 288 ;
2018-10-30 13:32:25 +01:00
}
2024-12-31 04:37:21 +01:00
}
static int
read_data ( cdrom_t * dev , uint32_t lba )
{
return dev - > ops - > read_sector ( dev , raw_buffer , lba ) ;
}
static int
read_mode1 ( cdrom_t * dev , int cdrom_sector_flags , uint32_t lba , uint8_t * b )
{
int ret = read_data ( dev , lba ) ;
process_mode1 ( dev , cdrom_sector_flags , b ) ;
2024-10-27 13:17:55 -03:00
return ret ;
2018-10-30 13:32:25 +01:00
}
2024-10-27 13:17:55 -03:00
static int
2024-12-31 04:37:21 +01:00
read_mode2_non_xa ( cdrom_t * dev , int cdrom_sector_flags , uint32_t lba , uint8_t * b )
2018-10-30 13:32:25 +01:00
{
2024-12-31 04:37:21 +01:00
int ret = dev - > ops - > read_sector ( dev , raw_buffer , lba ) ;
2018-10-30 13:32:25 +01:00
cdrom_sector_size = 0 ;
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x80 ) {
/* Sync */
cdrom_log ( " CD-ROM %i: [Mode 2 Formless] Sync \n " , dev - > id ) ;
memcpy ( b , raw_buffer , 12 ) ;
cdrom_sector_size + = 12 ;
b + = 12 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x20 ) {
/* Header */
cdrom_log ( " CD-ROM %i: [Mode 2 Formless] Header \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 12 , 4 ) ;
cdrom_sector_size + = 4 ;
b + = 4 ;
2018-10-30 13:32:25 +01:00
}
/* Mode 1 sector, expected type is 1 type. */
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x40 ) {
/* Sub-header */
cdrom_log ( " CD-ROM %i: [Mode 2 Formless] Sub-header \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 16 , 8 ) ;
cdrom_sector_size + = 8 ;
b + = 8 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x10 ) {
/* User data */
cdrom_log ( " CD-ROM %i: [Mode 2 Formless] User data \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 24 , 2336 ) ;
cdrom_sector_size + = 2336 ;
b + = 2336 ;
2018-10-30 13:32:25 +01:00
}
2024-10-27 13:17:55 -03:00
return ret ;
2018-10-30 13:32:25 +01:00
}
2024-12-31 04:37:21 +01:00
static void
process_mode2_xa_form1 ( cdrom_t * dev , int cdrom_sector_flags , uint8_t * b )
2018-10-30 13:32:25 +01:00
{
cdrom_sector_size = 0 ;
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x80 ) {
/* Sync */
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 1] Sync \n " , dev - > id ) ;
memcpy ( b , raw_buffer , 12 ) ;
cdrom_sector_size + = 12 ;
b + = 12 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x20 ) {
/* Header */
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 1] Header \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 12 , 4 ) ;
cdrom_sector_size + = 4 ;
b + = 4 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x40 ) {
/* Sub-header */
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 1] Sub-header \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 16 , 8 ) ;
cdrom_sector_size + = 8 ;
b + = 8 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x10 ) {
/* User data */
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 1] User data \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 24 , 2048 ) ;
cdrom_sector_size + = 2048 ;
b + = 2048 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x08 ) {
/* EDC/ECC */
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 2072 , 280 ) ;
cdrom_sector_size + = 280 ;
b + = 280 ;
2018-10-30 13:32:25 +01:00
}
2024-12-31 04:37:21 +01:00
}
static int
read_mode2_xa_form1 ( cdrom_t * dev , int cdrom_sector_flags , uint32_t lba , uint8_t * b )
{
int ret = read_data ( dev , lba ) ;
process_mode2_xa_form1 ( dev , cdrom_sector_flags , b ) ;
2024-10-27 13:17:55 -03:00
return ret ;
2018-10-30 13:32:25 +01:00
}
2024-10-27 13:17:55 -03:00
static int
2024-12-31 04:37:21 +01:00
read_mode2_xa_form2 ( cdrom_t * dev , int cdrom_sector_flags , uint32_t lba , uint8_t * b )
2018-10-30 13:32:25 +01:00
{
2024-12-31 04:37:21 +01:00
int ret = dev - > ops - > read_sector ( dev , raw_buffer , lba ) ;
2018-10-30 13:32:25 +01:00
cdrom_sector_size = 0 ;
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x80 ) {
/* Sync */
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 2] Sync \n " , dev - > id ) ;
memcpy ( b , raw_buffer , 12 ) ;
cdrom_sector_size + = 12 ;
b + = 12 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x20 ) {
/* Header */
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 2] Header \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 12 , 4 ) ;
cdrom_sector_size + = 4 ;
b + = 4 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x40 ) {
/* Sub-header */
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 2] Sub-header \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 16 , 8 ) ;
cdrom_sector_size + = 8 ;
b + = 8 ;
2018-10-30 13:32:25 +01:00
}
2022-02-22 22:04:40 +01:00
if ( cdrom_sector_flags & 0x10 ) {
/* User data */
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 2] User data \n " , dev - > id ) ;
memcpy ( b , raw_buffer + 24 , 2328 ) ;
cdrom_sector_size + = 2328 ;
b + = 2328 ;
2018-10-30 13:32:25 +01:00
}
2024-10-27 13:17:55 -03:00
return ret ;
2018-10-30 13:32:25 +01:00
}
int
cdrom_readsector_raw ( cdrom_t * dev , uint8_t * buffer , int sector , int ismsf , int cdrom_sector_type ,
2023-01-07 23:48:45 +01:00
int cdrom_sector_flags , int * len , uint8_t vendor_type )
2018-10-30 13:32:25 +01:00
{
2023-05-16 15:43:20 -04:00
uint8_t * b ;
uint8_t * temp_b ;
uint32_t lba ;
2024-12-31 04:37:21 +01:00
int audio = 0 ;
int mode2 = 0 ;
int unk = 0 ;
int ret = 0 ;
2018-10-30 13:32:25 +01:00
if ( dev - > cd_status = = CD_STATUS_EMPTY )
2022-02-22 22:04:40 +01:00
return 0 ;
2018-10-30 13:32:25 +01:00
b = temp_b = buffer ;
* len = 0 ;
if ( ismsf ) {
2024-12-31 04:37:21 +01:00
int m = ( sector > > 16 ) & 0xff ;
int s = ( sector > > 8 ) & 0xff ;
int f = sector & 0xff ;
2022-02-22 22:04:40 +01:00
lba = MSFtoLBA ( m , s , f ) - 150 ;
2018-10-30 13:32:25 +01:00
} else {
2023-01-07 23:48:45 +01:00
switch ( vendor_type ) {
case 0x00 :
lba = sector ;
break ;
2024-12-31 04:58:59 +01:00
case 0x40 : {
2024-12-31 04:37:21 +01:00
int m = bcd2bin ( ( sector > > 24 ) & 0xff ) ;
int s = bcd2bin ( ( sector > > 16 ) & 0xff ) ;
int f = bcd2bin ( ( sector > > 8 ) & 0xff ) ;
2023-01-07 23:48:45 +01:00
lba = MSFtoLBA ( m , s , f ) - 150 ;
break ;
2024-12-31 04:58:59 +01:00
} case 0x80 :
2023-01-07 23:48:45 +01:00
lba = bcd2bin ( ( sector > > 24 ) & 0xff ) ;
break ;
2023-01-10 04:15:29 +01:00
/* Never used values but the compiler complains. */
default :
2024-12-31 04:37:21 +01:00
lba = 0 ;
2023-01-07 23:48:45 +01:00
}
2018-10-30 13:32:25 +01:00
}
if ( dev - > ops - > track_type )
2022-02-22 22:04:40 +01:00
audio = dev - > ops - > track_type ( dev , lba ) ;
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
mode2 = audio & CD_TRACK_MODE2 ;
unk = audio & CD_TRACK_UNK_DATA ;
2018-10-30 13:32:25 +01:00
audio & = CD_TRACK_AUDIO ;
memset ( raw_buffer , 0 , 2448 ) ;
memset ( extra_buffer , 0 , 296 ) ;
2022-02-22 22:04:40 +01:00
if ( ( cdrom_sector_flags & 0xf8 ) = = 0x08 ) {
/* 0x08 is an illegal mode */
cdrom_log ( " CD-ROM %i: [Mode 1] 0x08 is an illegal mode \n " , dev - > id ) ;
return 0 ;
2018-10-30 13:32:25 +01:00
}
if ( ! track_type_is_valid ( dev - > id , cdrom_sector_type , cdrom_sector_flags , audio , mode2 ) )
2022-02-22 22:04:40 +01:00
return 0 ;
2018-10-30 13:32:25 +01:00
if ( ( cdrom_sector_type > 5 ) & & ( cdrom_sector_type ! = 8 ) ) {
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: Attempting to read an unrecognized sector type from an image \n " , dev - > id ) ;
return 0 ;
2018-10-30 13:32:25 +01:00
} else if ( cdrom_sector_type = = 1 ) {
2022-02-22 22:04:40 +01:00
if ( ! audio | | ( dev - > cd_status = = CD_STATUS_DATA_ONLY ) ) {
cdrom_log ( " CD-ROM %i: [Audio] Attempting to read an audio sector from a data image \n " , dev - > id ) ;
return 0 ;
}
2018-10-30 13:32:25 +01:00
2024-10-27 13:17:55 -03:00
ret = read_audio ( dev , lba , temp_b ) ;
2018-10-30 13:32:25 +01:00
} else if ( cdrom_sector_type = = 2 ) {
2022-02-22 22:04:40 +01:00
if ( audio | | mode2 ) {
cdrom_log ( " CD-ROM %i: [Mode 1] Attempting to read a sector of another type \n " , dev - > id ) ;
return 0 ;
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
ret = read_mode1 ( dev , cdrom_sector_flags , lba , temp_b ) ;
2018-10-30 13:32:25 +01:00
} else if ( cdrom_sector_type = = 3 ) {
2022-02-22 22:04:40 +01:00
if ( audio | | ! mode2 | | ( mode2 & 0x03 ) ) {
cdrom_log ( " CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type \n " , dev - > id ) ;
return 0 ;
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
ret = read_mode2_non_xa ( dev , cdrom_sector_flags , lba , temp_b ) ;
2018-10-30 13:32:25 +01:00
} else if ( cdrom_sector_type = = 4 ) {
2022-02-22 22:04:40 +01:00
if ( audio | | ! mode2 | | ( ( mode2 & 0x03 ) ! = 1 ) ) {
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type \n " , dev - > id ) ;
return 0 ;
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
read_mode2_xa_form1 ( dev , cdrom_sector_flags , lba , temp_b ) ;
2018-10-30 13:32:25 +01:00
} else if ( cdrom_sector_type = = 5 ) {
2022-02-22 22:04:40 +01:00
if ( audio | | ! mode2 | | ( ( mode2 & 0x03 ) ! = 2 ) ) {
cdrom_log ( " CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type \n " , dev - > id ) ;
return 0 ;
}
2018-10-30 13:32:25 +01:00
2024-12-31 04:37:21 +01:00
ret = read_mode2_xa_form2 ( dev , cdrom_sector_flags , lba , temp_b ) ;
2018-10-30 13:32:25 +01:00
} else if ( cdrom_sector_type = = 8 ) {
2022-02-22 22:04:40 +01:00
if ( audio ) {
cdrom_log ( " CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track \n " , dev - > id ) ;
return 0 ;
}
2024-12-31 04:37:21 +01:00
if ( unk ) {
/* This is needed to correctly read Mode 2 XA Form 1 sectors over IOCTL. */
ret = read_data ( dev , lba ) ;
if ( raw_buffer [ 0x000f ] = = 0x02 ) {
cdrom_log ( " CD-ROM %i: [Any Data] Unknown data type determined to be XA Mode 2 Form 1 \n " , dev - > id ) ;
process_mode2_xa_form1 ( dev , cdrom_sector_flags , temp_b ) ;
} else {
cdrom_log ( " CD-ROM %i: [Any Data] Unknown data type determined to be Mode 1 \n " , dev - > id ) ;
process_mode1 ( dev , cdrom_sector_flags , temp_b ) ;
}
} else if ( mode2 & & ( ( mode2 & 0x03 ) = = 1 ) )
ret = read_mode2_xa_form1 ( dev , cdrom_sector_flags , lba , temp_b ) ;
2022-02-22 22:04:40 +01:00
else if ( ! mode2 )
2024-12-31 04:37:21 +01:00
ret = read_mode1 ( dev , cdrom_sector_flags , lba , temp_b ) ;
2022-02-22 22:04:40 +01:00
else {
2024-12-31 04:37:21 +01:00
cdrom_log ( " CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size "
" is not 2048 bytes \n " , dev - > id ) ;
2022-02-22 22:04:40 +01:00
return 0 ;
}
2018-10-30 13:32:25 +01:00
} else {
2022-02-22 22:04:40 +01:00
if ( mode2 ) {
if ( ( mode2 & 0x03 ) = = 0x01 )
2024-12-31 04:37:21 +01:00
ret = read_mode2_xa_form1 ( dev , cdrom_sector_flags , lba , temp_b ) ;
2022-02-22 22:04:40 +01:00
else if ( ( mode2 & 0x03 ) = = 0x02 )
2024-12-31 04:37:21 +01:00
ret = read_mode2_xa_form2 ( dev , cdrom_sector_flags , lba , temp_b ) ;
2022-02-22 22:04:40 +01:00
else
2024-12-31 04:37:21 +01:00
ret = read_mode2_non_xa ( dev , cdrom_sector_flags , lba , temp_b ) ;
2022-02-22 22:04:40 +01:00
} else {
if ( audio )
2024-10-27 13:17:55 -03:00
ret = read_audio ( dev , lba , temp_b ) ;
2022-02-22 22:04:40 +01:00
else
2024-12-31 04:37:21 +01:00
ret = read_mode1 ( dev , cdrom_sector_flags , lba , temp_b ) ;
2022-02-22 22:04:40 +01:00
}
2018-10-30 13:32:25 +01:00
}
if ( ( cdrom_sector_flags & 0x06 ) = = 0x02 ) {
2022-02-22 22:04:40 +01:00
/* Add error flags. */
cdrom_log ( " CD-ROM %i: Error flags \n " , dev - > id ) ;
memcpy ( b + cdrom_sector_size , extra_buffer , 294 ) ;
cdrom_sector_size + = 294 ;
2018-10-30 13:32:25 +01:00
} else if ( ( cdrom_sector_flags & 0x06 ) = = 0x04 ) {
2022-02-22 22:04:40 +01:00
/* Add error flags. */
cdrom_log ( " CD-ROM %i: Full error flags \n " , dev - > id ) ;
memcpy ( b + cdrom_sector_size , extra_buffer , 296 ) ;
cdrom_sector_size + = 296 ;
2018-10-30 13:32:25 +01:00
}
if ( ( cdrom_sector_flags & 0x700 ) = = 0x100 ) {
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: Raw subchannel data \n " , dev - > id ) ;
memcpy ( b + cdrom_sector_size , raw_buffer + 2352 , 96 ) ;
cdrom_sector_size + = 96 ;
2018-10-30 13:32:25 +01:00
} else if ( ( cdrom_sector_flags & 0x700 ) = = 0x200 ) {
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: Q subchannel data \n " , dev - > id ) ;
memcpy ( b + cdrom_sector_size , raw_buffer + 2352 , 16 ) ;
cdrom_sector_size + = 16 ;
2018-10-30 13:32:25 +01:00
} else if ( ( cdrom_sector_flags & 0x700 ) = = 0x400 ) {
2022-02-22 22:04:40 +01:00
cdrom_log ( " CD-ROM %i: R/W subchannel data \n " , dev - > id ) ;
memcpy ( b + cdrom_sector_size , raw_buffer + 2352 , 96 ) ;
cdrom_sector_size + = 96 ;
2018-10-17 05:29:48 +02:00
}
2018-10-30 13:32:25 +01:00
* len = cdrom_sector_size ;
2018-10-17 05:29:48 +02:00
2024-10-27 13:17:55 -03:00
return ret ;
2017-01-16 01:49:19 +01:00
}
2018-10-10 22:33:24 +02:00
/* Peform a master init on the entire module. */
void
cdrom_global_init ( void )
2018-04-25 23:51:13 +02:00
{
2018-10-10 22:33:24 +02:00
/* Clear the global data. */
2018-10-17 05:29:48 +02:00
memset ( cdrom , 0x00 , sizeof ( cdrom ) ) ;
2017-01-16 01:49:19 +01:00
}
2018-04-25 23:51:13 +02:00
static void
2018-10-17 05:29:48 +02:00
cdrom_drive_reset ( cdrom_t * dev )
2018-04-25 23:51:13 +02:00
{
2022-09-18 17:11:56 -04:00
dev - > priv = NULL ;
dev - > insert = NULL ;
dev - > close = NULL ;
dev - > get_volume = NULL ;
2018-10-17 05:29:48 +02:00
dev - > get_channel = NULL ;
2017-01-16 01:49:19 +01:00
}
2024-11-25 21:23:28 +01:00
# ifdef ENABLE_CDROM_LOG
static void
cdrom_toc_dump ( cdrom_t * dev )
{
uint8_t b [ 65536 ] = { 0 } ;
int len = cdrom_read_toc ( dev , b , CD_TOC_RAW , 0 , 0 , 65536 ) ;
const char * fn2 = " d: \\ 86boxnew \\ toc_cue.dmp " ;
FILE * f = fopen ( fn2 , " wb " ) ;
fwrite ( b , 1 , len , f ) ;
fflush ( f ) ;
fclose ( f ) ;
pclog ( " Written TOC of %i bytes to %s \n " , len , fn2 ) ;
2024-12-31 04:37:21 +01:00
memset ( b , 0x00 , 65536 ) ;
len = cdrom_read_toc ( dev , b , CD_TOC_NORMAL , 0 , 0 , 65536 ) ;
fn2 = " d: \\ 86boxnew \\ toc_cue_cooked.dmp " ;
f = fopen ( fn2 , " wb " ) ;
fwrite ( b , 1 , len , f ) ;
fflush ( f ) ;
fclose ( f ) ;
pclog ( " Written cooked TOC of %i bytes to %s \n " , len , fn2 ) ;
memset ( b , 0x00 , 65536 ) ;
len = cdrom_read_toc ( dev , b , CD_TOC_SESSION , 0 , 0 , 65536 ) ;
fn2 = " d: \\ 86boxnew \\ toc_cue_session.dmp " ;
f = fopen ( fn2 , " wb " ) ;
fwrite ( b , 1 , len , f ) ;
fflush ( f ) ;
fclose ( f ) ;
pclog ( " Written session TOC of %i bytes to %s \n " , len , fn2 ) ;
2024-11-25 21:23:28 +01:00
}
# endif
2018-10-10 22:33:24 +02:00
void
cdrom_hard_reset ( void )
2018-04-25 23:51:13 +02:00
{
2018-10-17 05:29:48 +02:00
cdrom_t * dev ;
2023-05-16 15:43:20 -04:00
for ( uint8_t i = 0 ; i < CDROM_NUM ; i + + ) {
2022-02-22 22:04:40 +01:00
dev = & cdrom [ i ] ;
if ( dev - > bus_type ) {
cdrom_log ( " CD-ROM %i: Hard reset \n " , i ) ;
2018-10-17 05:29:48 +02:00
2022-02-22 22:04:40 +01:00
dev - > id = i ;
2018-03-17 20:32:20 +01:00
2022-02-22 22:04:40 +01:00
cdrom_drive_reset ( dev ) ;
2017-01-16 01:49:19 +01:00
2022-09-18 17:11:56 -04:00
switch ( dev - > bus_type ) {
2022-02-22 22:04:40 +01:00
case CDROM_BUS_ATAPI :
case CDROM_BUS_SCSI :
scsi_cdrom_drive_reset ( i ) ;
break ;
2018-04-25 23:51:13 +02:00
2022-02-22 22:04:40 +01:00
default :
break ;
}
2018-04-25 23:51:13 +02:00
2022-02-22 22:04:40 +01:00
dev - > cd_status = CD_STATUS_EMPTY ;
2018-04-25 23:51:13 +02:00
2024-05-20 02:15:17 +02:00
if ( strlen ( dev - > image_path ) > 0 ) {
2024-01-14 21:31:46 +01:00
# ifdef _WIN32
if ( ( strlen ( dev - > image_path ) > = 1 ) & & ( dev - > image_path [ strlen ( dev - > image_path ) - 1 ] = = ' / ' ) )
dev - > image_path [ strlen ( dev - > image_path ) - 1 ] = ' \\ ' ;
# else
if ( ( strlen ( dev - > image_path ) > = 1 ) & &
( dev - > image_path [ strlen ( dev - > image_path ) - 1 ] = = ' \\ ' ) )
dev - > image_path [ strlen ( dev - > image_path ) - 1 ] = ' / ' ;
# endif
2024-05-19 21:17:57 +02:00
if ( ( strlen ( dev - > image_path ) ! = 0 ) & & ( strstr ( dev - > image_path , " ioctl:// " ) = = dev - > image_path ) )
cdrom_ioctl_open ( dev , dev - > image_path ) ;
else
cdrom_image_open ( dev , dev - > image_path ) ;
2024-11-25 21:23:28 +01:00
2024-12-31 04:37:21 +01:00
cdrom_insert ( i ) ;
cdrom_insert ( i ) ;
2024-11-25 21:23:28 +01:00
# ifdef ENABLE_CDROM_LOG
2024-12-31 04:37:21 +01:00
if ( i = = 0 )
cdrom_toc_dump ( dev ) ;
2024-11-25 21:23:28 +01:00
# endif
2024-05-19 21:17:57 +02:00
}
2022-02-22 22:04:40 +01:00
}
2018-04-25 23:51:13 +02:00
}
2017-10-24 04:15:05 +02:00
2018-10-10 22:33:24 +02:00
sound_cd_thread_reset ( ) ;
2017-01-16 01:49:19 +01:00
}
2018-10-10 22:33:24 +02:00
void
2018-10-17 05:29:48 +02:00
cdrom_close ( void )
2018-01-06 22:47:41 +01:00
{
2018-10-17 05:29:48 +02:00
cdrom_t * dev ;
2018-01-06 22:47:41 +01:00
2023-05-16 15:43:20 -04:00
for ( uint8_t i = 0 ; i < CDROM_NUM ; i + + ) {
2022-02-22 22:04:40 +01:00
dev = & cdrom [ i ] ;
2018-10-17 05:29:48 +02:00
2022-02-22 22:04:40 +01:00
if ( dev - > bus_type = = CDROM_BUS_SCSI )
memset ( & scsi_devices [ dev - > scsi_device_id ] , 0x00 , sizeof ( scsi_device_t ) ) ;
2020-06-14 21:59:45 +02:00
2022-02-22 22:04:40 +01:00
if ( dev - > close )
dev - > close ( dev - > priv ) ;
2018-10-30 13:32:25 +01:00
2022-02-22 22:04:40 +01:00
if ( dev - > ops & & dev - > ops - > exit )
dev - > ops - > exit ( dev ) ;
2018-10-17 05:29:48 +02:00
2022-09-18 17:11:56 -04:00
dev - > ops = NULL ;
2022-02-22 22:04:40 +01:00
dev - > priv = NULL ;
2018-10-26 04:47:21 +02:00
2022-02-22 22:04:40 +01:00
cdrom_drive_reset ( dev ) ;
2018-10-17 05:29:48 +02:00
}
}
/* Signal disc change to the emulated machine. */
void
cdrom_insert ( uint8_t id )
{
cdrom_t * dev = & cdrom [ id ] ;
2023-08-16 05:23:03 +02:00
if ( dev - > bus_type & & dev - > insert )
dev - > insert ( dev - > priv ) ;
2018-10-17 05:29:48 +02:00
}
2024-09-18 08:01:38 +02:00
void
cdrom_exit ( uint8_t id )
{
cdrom_t * dev = & cdrom [ id ] ;
strcpy ( dev - > prev_image_path , dev - > image_path ) ;
if ( dev - > ops ) {
if ( dev - > ops - > exit )
dev - > ops - > exit ( dev ) ;
dev - > ops = NULL ;
}
memset ( dev - > image_path , 0 , sizeof ( dev - > image_path ) ) ;
2024-12-31 04:37:21 +01:00
pclog ( " cdrom_exit(%i): cdrom_insert(%i) \n " , id , id ) ;
2024-09-18 08:01:38 +02:00
cdrom_insert ( id ) ;
}
2024-12-31 04:37:21 +01:00
int
cdrom_is_empty ( uint8_t id )
{
cdrom_t * dev = & cdrom [ id ] ;
int ret = 0 ;
/* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */
if ( strlen ( dev - > image_path ) = = 0 )
/* Switch from empty to empty. Do nothing. */
ret = 1 ;
return ret ;
}
2018-10-17 05:29:48 +02:00
/* The mechanics of ejecting a CD-ROM from a drive. */
void
cdrom_eject ( uint8_t id )
{
cdrom_t * dev = & cdrom [ id ] ;
/* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */
2024-12-31 04:37:21 +01:00
if ( strlen ( dev - > image_path ) = = 0 )
2022-02-22 22:04:40 +01:00
/* Switch from empty to empty. Do nothing. */
return ;
2018-10-11 10:34:12 +02:00
2024-09-18 08:01:38 +02:00
cdrom_exit ( id ) ;
2018-10-17 05:29:48 +02:00
plat_cdrom_ui_update ( id , 0 ) ;
config_save ( ) ;
2018-01-06 22:47:41 +01:00
}
2018-10-17 05:29:48 +02:00
/* The mechanics of re-loading a CD-ROM drive. */
2018-10-10 22:33:24 +02:00
void
2018-10-17 05:29:48 +02:00
cdrom_reload ( uint8_t id )
2017-01-16 01:49:19 +01:00
{
2024-12-31 04:37:21 +01:00
cdrom_t * dev = & cdrom [ id ] ;
int was_empty = cdrom_is_empty ( id ) ;
2017-01-16 01:49:19 +01:00
2024-05-20 02:15:17 +02:00
if ( ( strcmp ( dev - > image_path , dev - > prev_image_path ) = = 0 ) | | ( strlen ( dev - > prev_image_path ) = = 0 ) | | ( strlen ( dev - > image_path ) > 0 ) ) {
2022-02-22 22:04:40 +01:00
/* Switch from empty to empty. Do nothing. */
return ;
2018-10-17 05:29:48 +02:00
}
if ( dev - > ops & & dev - > ops - > exit )
2022-02-22 22:04:40 +01:00
dev - > ops - > exit ( dev ) ;
2018-10-17 05:29:48 +02:00
dev - > ops = NULL ;
memset ( dev - > image_path , 0 , sizeof ( dev - > image_path ) ) ;
2017-01-18 21:51:03 +01:00
2024-05-20 02:15:17 +02:00
if ( strlen ( dev - > image_path ) > 0 ) {
2022-02-22 22:04:40 +01:00
/* Reload a previous image. */
2024-05-20 02:15:17 +02:00
if ( strlen ( dev - > prev_image_path ) > 0 )
2024-05-18 22:37:49 +02:00
strcpy ( dev - > image_path , dev - > prev_image_path ) ;
2024-01-14 21:31:46 +01:00
# ifdef _WIN32
2024-11-25 21:23:28 +01:00
if ( ( strlen ( dev - > prev_image_path ) > 0 ) & & ( strlen ( dev - > image_path ) > = 1 ) & &
( dev - > image_path [ strlen ( dev - > image_path ) - 1 ] = = ' / ' ) )
dev - > image_path [ strlen ( dev - > image_path ) - 1 ] = ' \\ ' ;
2024-01-14 21:31:46 +01:00
# else
2024-11-25 21:23:28 +01:00
if ( ( strlen ( dev - > prev_image_path ) > 0 ) & & ( strlen ( dev - > image_path ) > = 1 ) & &
( dev - > image_path [ strlen ( dev - > image_path ) - 1 ] = = ' \\ ' ) )
dev - > image_path [ strlen ( dev - > image_path ) - 1 ] = ' / ' ;
2024-01-14 21:31:46 +01:00
# endif
2024-05-19 21:17:57 +02:00
if ( ( strlen ( dev - > image_path ) ! = 0 ) & & ( strstr ( dev - > image_path , " ioctl:// " ) = = dev - > image_path ) )
cdrom_ioctl_open ( dev , dev - > image_path ) ;
2024-05-18 19:42:00 +02:00
else
cdrom_image_open ( dev , dev - > image_path ) ;
2017-01-16 01:49:19 +01:00
2024-11-25 21:23:28 +01:00
# ifdef ENABLE_CDROM_LOG
cdrom_toc_dump ( dev ) ;
# endif
2024-12-31 04:37:21 +01:00
/* Signal media change to the emulated machine. */
pclog ( " cdrom_reload(%i): cdrom_insert(%i) \n " , id , id ) ;
2022-02-22 22:04:40 +01:00
cdrom_insert ( id ) ;
2024-12-31 04:37:21 +01:00
/* The drive was previously empty, transition directly to UNIT ATTENTION. */
if ( was_empty )
cdrom_insert ( id ) ;
2018-04-25 23:51:13 +02:00
}
2018-10-17 05:29:48 +02:00
plat_cdrom_ui_update ( id , 1 ) ;
config_save ( ) ;
2018-04-25 23:51:13 +02:00
}