CD-ROM changes from Battler, including :
- New disc change handling - Additional ATAPI commands - CD drive-level volume control
This commit is contained in:
parent
5b3d307181
commit
0faa803061
13 changed files with 1600 additions and 378 deletions
|
|
@ -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,<oc,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
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue