CD-ROM changes from Battler, including :

- New disc change handling
- Additional ATAPI commands
- CD drive-level volume control
This commit is contained in:
TomW 2016-03-08 20:47:05 +00:00
commit 0faa803061
13 changed files with 1600 additions and 378 deletions

View file

@ -12,6 +12,7 @@
#include "cdrom-ioctl.h"
int cdrom_drive;
int old_cdrom_drive;
#ifndef __MINGW64__
typedef struct _CDROM_TOC_SESSION_DATA {
@ -27,7 +28,7 @@ static ATAPI ioctl_atapi;
static uint32_t last_block = 0;
static int ioctl_inited = 0;
static char ioctl_path[8];
static void ioctl_close(void);
void ioctl_close(void);
static HANDLE hIOCTL;
static CDROM_TOC toc;
static int tocvalid = 0;
@ -233,11 +234,14 @@ static int ioctl_ready(void)
ioctl_close();
if (!temp)
return 0;
//pclog("ioctl_ready(): Drive opened successfully\n");
//if ((cdrom_drive != old_cdrom_drive)) pclog("Drive has changed\n");
if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != toc.TrackData[toc.LastTrack].Address[1]) ||
(ltoc.TrackData[ltoc.LastTrack].Address[2] != toc.TrackData[toc.LastTrack].Address[2]) ||
(ltoc.TrackData[ltoc.LastTrack].Address[3] != toc.TrackData[toc.LastTrack].Address[3]) ||
!tocvalid)
!tocvalid || (cdrom_drive != old_cdrom_drive))
{
//pclog("ioctl_ready(): Disc or drive changed\n");
ioctl_cd_state = CD_STOPPED;
/* pclog("Not ready %02X %02X %02X %02X %02X %02X %i\n",ltoc.TrackData[ltoc.LastTrack].Address[1],ltoc.TrackData[ltoc.LastTrack].Address[2],ltoc.TrackData[ltoc.LastTrack].Address[3],
toc.TrackData[ltoc.LastTrack].Address[1], toc.TrackData[ltoc.LastTrack].Address[2], toc.TrackData[ltoc.LastTrack].Address[3],tocvalid);*/
@ -245,13 +249,44 @@ static int ioctl_ready(void)
/* ioctl_open(0);
temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&toc,sizeof(toc),&size,NULL);
ioctl_close();*/
toc=ltoc;
tocvalid=1;
return 0;
if (cdrom_drive != old_cdrom_drive)
old_cdrom_drive = cdrom_drive;
return 1;
}
// pclog("IOCTL says ready\n");
// pclog("ioctl_ready(): All is good\n");
return 1;
// return (temp)?1:0;
}
static int ioctl_medium_changed(void)
{
long size;
int temp;
CDROM_TOC ltoc;
if (!cdrom_drive) return 0; /* This will be handled by the not ready handler instead. */
ioctl_open(0);
temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&ltoc,sizeof(ltoc),&size,NULL);
ioctl_close();
if (!temp)
return 0; /* Drive empty, a not ready handler matter, not disc change. */
if (!tocvalid || (cdrom_drive != old_cdrom_drive))
{
ioctl_cd_state = CD_STOPPED;
toc = ltoc;
tocvalid = 1;
if (cdrom_drive != old_cdrom_drive)
old_cdrom_drive = cdrom_drive;
return 0;
}
if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != toc.TrackData[toc.LastTrack].Address[1]) ||
(ltoc.TrackData[ltoc.LastTrack].Address[2] != toc.TrackData[toc.LastTrack].Address[2]) ||
(ltoc.TrackData[ltoc.LastTrack].Address[3] != toc.TrackData[toc.LastTrack].Address[3]))
{
ioctl_cd_state = CD_STOPPED;
toc = ltoc;
return 1; /* TOC mismatches. */
}
return 0; /* None of the above, return 0. */
}
static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
@ -365,6 +400,10 @@ static void ioctl_readsector(uint8_t *b, int sector)
LARGE_INTEGER pos;
long size;
if (!cdrom_drive) return;
if (ioctl_cd_state == CD_PLAYING)
return;
ioctl_cd_state = CD_STOPPED;
pos.QuadPart=sector*2048;
ioctl_open(0);
@ -373,6 +412,74 @@ static void ioctl_readsector(uint8_t *b, int sector)
ioctl_close();
}
static void lba_to_msf(uint8_t *buf, int lba)
{
lba += 150;
buf[0] = (lba / 75) / 60;
buf[1] = (lba / 75) % 60;
buf[2] = lba % 75;
}
static int is_track_audio(uint32_t pos)
{
int c;
int control = 0;
if (!tocvalid)
return 0;
for (c = toc.FirstTrack; c < toc.LastTrack; c++)
{
uint32_t track_address = toc.TrackData[c].Address[3] +
(toc.TrackData[c].Address[2] * 75) +
(toc.TrackData[c].Address[1] * 75 * 60);
if (track_address <= pos)
control = toc.TrackData[c].Control;
}
return (control & 4) ? 0 : 1;
}
static int ioctl_is_track_audio(uint32_t pos, int ismsf)
{
if (ismsf)
{
int m = (pos >> 16) & 0xff;
int s = (pos >> 8) & 0xff;
int f = pos & 0xff;
pos = MSFtoLBA(m, s, f);
}
return is_track_audio(pos);
}
static void ioctl_readsector_raw(uint8_t *b, int sector)
{
LARGE_INTEGER pos;
long size;
uint32_t temp;
if (!cdrom_drive) return;
if (ioctl_cd_state == CD_PLAYING)
return;
ioctl_cd_state = CD_STOPPED;
pos.QuadPart=sector*2048;
ioctl_open(0);
SetFilePointer(hIOCTL,pos.LowPart,&pos.HighPart,FILE_BEGIN);
ReadFile(hIOCTL,b+16,2048,&size,NULL);
ioctl_close();
/* sync bytes */
b[0] = 0;
memset(b + 1, 0xff, 10);
b[11] = 0;
b += 12;
lba_to_msf(b, sector);
b[3] = 1; /* mode 1 data */
b += 4;
b += 2048;
memset(b, 0, 288);
}
static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
{
int len=4;
@ -441,7 +548,7 @@ static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, in
return len;
}
static void ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
static int ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
{
int len=4;
int size;
@ -461,25 +568,71 @@ static void ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
// pclog("Read TOC session - %i %02X %02X %i %i %02X %02X %02X\n",size,toc.Length[0],toc.Length[1],toc.FirstCompleteSession,toc.LastCompleteSession,toc.TrackData[0].Adr,toc.TrackData[0].Control,toc.TrackData[0].TrackNumber);
b[2]=toc.FirstCompleteSession;
b[3]=toc.LastCompleteSession;
b[len++]=0; /*Reserved*/
b[len++]=(toc.TrackData[0].Adr<<4)|toc.TrackData[0].Control;
b[len++]=toc.TrackData[0].TrackNumber;
b[len++]=0; /*Reserved*/
if (msf)
{
b[len++]=toc.TrackData[0].Address[0];
b[len++]=toc.TrackData[0].Address[1];
b[len++]=toc.TrackData[0].Address[2];
b[len++]=toc.TrackData[0].Address[3];
}
else
{
temp=MSFtoLBA(toc.TrackData[0].Address[1],toc.TrackData[0].Address[2],toc.TrackData[0].Address[3]);
b[len++]=temp>>24;
b[len++]=temp>>16;
b[len++]=temp>>8;
b[len++]=temp;
}
b[len++]=0; /*Reserved*/
b[len++]=(toc.TrackData[0].Adr<<4)|toc.TrackData[0].Control;
b[len++]=toc.TrackData[0].TrackNumber;
b[len++]=0; /*Reserved*/
if (msf)
{
b[len++]=toc.TrackData[0].Address[0];
b[len++]=toc.TrackData[0].Address[1];
b[len++]=toc.TrackData[0].Address[2];
b[len++]=toc.TrackData[0].Address[3];
}
else
{
temp=MSFtoLBA(toc.TrackData[0].Address[1],toc.TrackData[0].Address[2],toc.TrackData[0].Address[3]);
b[len++]=temp>>24;
b[len++]=temp>>16;
b[len++]=temp>>8;
b[len++]=temp;
}
return len;
}
static int ioctl_readtoc_raw(unsigned char *b, int maxlen)
{
int len=4;
int size;
uint32_t temp;
int i;
int BytesRead = 0;
CDROM_READ_TOC_EX toc_ex;
CDROM_TOC_FULL_TOC_DATA toc;
if (!cdrom_drive) return 0;
ioctl_cd_state = CD_STOPPED;
memset(&toc_ex,0,sizeof(toc_ex));
memset(&toc,0,sizeof(toc));
toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_FULL_TOC;
toc_ex.Msf=1;
toc_ex.SessionTrack=0;
ioctl_open(0);
DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL);
ioctl_close();
// pclog("Read TOC session - %i %02X %02X %i %i %02X %02X %02X\n",size,toc.Length[0],toc.Length[1],toc.FirstCompleteSession,toc.LastCompleteSession,toc.TrackData[0].Adr,toc.TrackData[0].Control,toc.TrackData[0].TrackNumber);
b[2]=toc.FirstCompleteSession;
b[3]=toc.LastCompleteSession;
size -= sizeof(CDROM_TOC_FULL_TOC_DATA);
size /= sizeof(toc.Descriptors[0]);
for (i = 0; i <= size; i++)
{
b[len++]=toc.Descriptors[i].SessionNumber;
b[len++]=(toc.Descriptors[i].Adr<<4)|toc.Descriptors[i].Control;
b[len++]=0;
b[len++]=toc.Descriptors[i].Reserved1; /*Reserved*/
b[len++]=toc.Descriptors[i].MsfExtra[0];
b[len++]=toc.Descriptors[i].MsfExtra[1];
b[len++]=toc.Descriptors[i].MsfExtra[2];
b[len++]=toc.Descriptors[i].Zero;
b[len++]=toc.Descriptors[i].Msf[0];
b[len++]=toc.Descriptors[i].Msf[1];
b[len++]=toc.Descriptors[i].Msf[2];
}
return len;
}
static uint32_t ioctl_size()
@ -491,6 +644,22 @@ static uint32_t ioctl_size()
return last_block;
}
static int ioctl_status()
{
if (!(ioctl_ready) && (cdrom_drive <= 0))
return CD_STATUS_EMPTY;
switch(ioctl_cd_state)
{
case CD_PLAYING:
return CD_STATUS_PLAYING;
case CD_PAUSED:
return CD_STATUS_PAUSED;
case CD_STOPPED:
return CD_STATUS_STOPPED;
}
}
void ioctl_reset()
{
CDROM_TOC ltoc;
@ -536,7 +705,7 @@ int ioctl_open(char d)
return 0;
}
static void ioctl_close(void)
void ioctl_close(void)
{
if (hIOCTL)
{
@ -550,16 +719,18 @@ static void ioctl_exit(void)
ioctl_stop();
ioctl_inited=0;
tocvalid=0;
ioctl_close();
}
static ATAPI ioctl_atapi=
{
ioctl_ready,
ioctl_medium_changed,
ioctl_readtoc,
ioctl_readtoc_session,
ioctl_readtoc_raw,
ioctl_getcurrentsubchannel,
ioctl_readsector,
ioctl_readsector_raw,
ioctl_playaudio,
ioctl_seek,
ioctl_load,
@ -567,6 +738,8 @@ static ATAPI ioctl_atapi=
ioctl_pause,
ioctl_resume,
ioctl_size,
ioctl_status,
ioctl_is_track_audio,
ioctl_stop,
ioctl_exit
};