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

@ -115,6 +115,38 @@ static int get_track_nr(uint32_t pos)
return track;
}
static int is_track_audio(uint32_t pos)
{
int c;
int control = 0;
if (!tocvalid)
return 0;
for (c = first_track; c < last_track; c++)
{
uint32_t track_address = toc[c].cdte_addr.msf.frame +
(toc[c].cdte_addr.msf.second * 75) +
(toc[c].cdte_addr.msf.minute * 75 * 60);
//pclog("get_track_nr: track=%i pos=%x track_address=%x\n", c, pos, track_address);
if (track_address <= pos)
control = toc[c].cdte_ctrl;
}
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_playaudio(uint32_t pos, uint32_t len, int ismsf)
{
// pclog("Play audio - %08X %08X %i\n", pos, len, ismsf);
@ -226,12 +258,48 @@ static int ioctl_ready(void)
tocvalid = read_toc(fd);
close(fd);
return 0;
return 1;
}
close(fd);
return 1;
}
static int ioctl_medium_changed(void)
{
long size;
int temp;
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc_entry;
int err;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
close(fd);
return 0;
}
toc_entry.cdte_track = toc_hdr.cdth_trk1;
toc_entry.cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &toc_entry);
if (err == -1)
{
close(fd);
return 0;
}
// pclog("CDROMREADTOCENTRY: addr=%02i:%02i:%02i\n", toc_entry.cdte_addr.msf.minute, toc_entry.cdte_addr.msf.second, toc_entry.cdte_addr.msf.frame);
if ((toc_entry.cdte_addr.msf.minute != toc[toc_hdr.cdth_trk1].cdte_addr.msf.minute) ||
(toc_entry.cdte_addr.msf.second != toc[toc_hdr.cdth_trk1].cdte_addr.msf.second) ||
(toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame ))
{
return 1;
}
return 0;
}
static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
{
struct cdrom_subchnl sub;
@ -321,6 +389,35 @@ static void ioctl_readsector(uint8_t *b, int sector)
close(cdrom);
}
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 void ioctl_readsector_raw(uint8_t *b, int sector)
{
int cdrom = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (cdrom <= 0)
return;
lseek(cdrom, sector*2048, SEEK_SET);
read(cdrom, b+16, 2048);
close(cdrom);
/* 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;
@ -400,7 +497,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)
{
struct cdrom_multisession session;
int len = 4;
@ -440,6 +537,61 @@ static void ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
b[len++] = temp >> 8;
b[len++] = temp;
}
return len;
}
static int ioctl_readtoc_raw(unsigned char *b, int maxlen)
{
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc2[100];
int track, err;
int len = 4;
//pclog("read_toc\n");
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
pclog("read_toc: CDROMREADTOCHDR failed\n");
return 0;
}
b[2] = toc_hdr.cdth_trk0;
b[3] = toc_hdr.cdth_trk1;
//pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track);
memset(toc, 0, sizeof(toc));
for (track = toc_hdr.cdth_trk0; track <= toc_hdr.cdth_trk1; track++)
{
if ((len + 11) > maxlen)
{
pclog("ioctl_readtocraw: This iteration would fill the buffer beyond the bounds, aborting...\n");
return len;
}
toc2[track].cdte_track = track;
toc2[track].cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &toc2[track]);
if (err == -1)
{
// pclog("read_toc: CDROMREADTOCENTRY failed on track %i\n", track);
return 0;
}
// pclog("read_toc: Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", track, toc[track].cdte_track, toc[track].cdte_ctrl, toc[track].cdte_adr, 0, toc[track].cdte_addr.msf.minute, toc[track].cdte_addr.msf.second, toc[track].cdte_addr.msf.frame);
b[len++] = toc2[track].cdte_track;
b[len++]= (toc2[track].cdte_adr << 4) | toc[track].cdte_ctrl;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++] = toc2[track].cdte_addr.msf.minute;
b[len++] = toc2[track].cdte_addr.msf.second;
b[len++] = toc2[track].cdte_addr.msf.frame;
}
return len;
}
static uint32_t ioctl_size()
@ -451,6 +603,20 @@ 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()
{
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
@ -485,10 +651,13 @@ static void ioctl_exit(void)
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,
@ -496,6 +665,8 @@ static ATAPI ioctl_atapi=
ioctl_pause,
ioctl_resume,
ioctl_size,
ioctl_status,
ioctl_is_track_audio,
ioctl_stop,
ioctl_exit
};

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
};

View file

@ -6,5 +6,6 @@
extern int ioctl_open(char d);
extern void ioctl_reset();
extern void ioctl_close();
#endif /* ! CDROM_IOCTL_H */

View file

@ -11,6 +11,7 @@ static uint32_t last_block = 0;
static uint64_t image_size = 0;
static int iso_inited = 0;
char iso_path[1024];
void iso_close(void);
static FILE *iso_image = NULL;
static int iso_changed = 0;
@ -65,15 +66,23 @@ static void iso_seek(uint32_t pos)
static int iso_ready(void)
{
if (iso_changed)
{
iso_changed = 0;
if (strlen(iso_path) == 0)
return 0;
}
if (old_cdrom_drive != cdrom_drive)
return 1;
iso_changed = 0;
return 1;
}
/* Always return 0, because there is no way to change the ISO without unmounting and remounting it. */
static int iso_medium_changed(void)
{
iso_changed = 0;
return 0;
}
static uint8_t iso_getcurrentsubchannel(uint8_t *b, int msf)
{
pclog("iso_getcurrentsubchannel stub\n");
@ -102,7 +111,26 @@ 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;
buf[2] = lba % 75;
}
static void iso_readsector_raw(uint8_t *b, int sector)
{
uint32_t temp;
if (!cdrom_drive) return;
fseek(iso_image, sector*2048, SEEK_SET);
fread(b+16, 2048, 1, iso_image);
/* 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 iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, int maxlen, int single)
@ -161,7 +189,7 @@ static int iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, i
return len;
}
static void iso_readtoc_session(unsigned char *buf, int msf, int maxlen)
static int iso_readtoc_session(unsigned char *buf, int msf, int maxlen)
{
uint8_t *q;
@ -177,6 +205,73 @@ static void iso_readtoc_session(unsigned char *buf, int msf, int maxlen)
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
return 12;
}
static int iso_readtoc_raw(unsigned char *buf, int maxlen)
{
uint8_t *q;
int len;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa0; /* lead-in */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* first track */
*q++ = 0x00; /* disk type */
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa1;
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* last track */
*q++ = 0x00;
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa2; /* lead-out */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
last_block = image_size >> 11;
/* this is raw, must be msf */
*q++ = 0; /* reserved */
lba_to_msf(q, last_block);
q += 3;
*q++ = 1; /* session number */
*q++ = 0x14; /* ADR, control */
*q++ = 0; /* track number */
*q++ = 1; /* point */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
/* same here */
*q++ = 0;
*q++ = 0;
*q++ = 0;
*q++ = 0;
len = q - buf;
buf[0] = (uint8_t)(((len-2) >> 8) & 0xff);
buf[1] = (uint8_t)((len-2) & 0xff);
return len;
}
static uint32_t iso_size()
@ -188,6 +283,14 @@ static uint32_t iso_size()
return last_block;
}
static int iso_status()
{
if (!(iso_ready()) && (cdrom_drive != 200))
return CD_STATUS_EMPTY;
return CD_STATUS_DATA_ONLY;
}
void iso_reset()
{
}
@ -199,10 +302,13 @@ int iso_open(char *fn)
if (iso_image)
fclose(iso_image);
iso_changed = 1;
if (strcmp(fn, iso_path) != 0)
iso_changed = 1;
sprintf(iso_path, "%s", fn);
pclog("Path is %s\n", iso_path);
/* Make sure iso_changed stays when changing from ISO to another ISO. */
if (cdrom_drive != CDROM_ISO)
iso_changed = 1;
strcpy(iso_path, fn);
iso_image = fopen(iso_path, "rb");
atapi = &iso_atapi;
@ -213,29 +319,36 @@ int iso_open(char *fn)
return 0;
}
static void iso_close(void)
void iso_close(void)
{
if (iso_image)
{
fclose(iso_image);
iso_image = NULL;
}
memset(iso_path, 0, 1024);
}
static void iso_exit(void)
{
iso_stop();
iso_inited = 0;
iso_close();
}
static int iso_is_track_audio(uint32_t pos, int ismsf)
{
return 0;
}
static ATAPI iso_atapi =
{
iso_ready,
iso_medium_changed,
iso_readtoc,
iso_readtoc_session,
iso_readtoc_raw,
iso_getcurrentsubchannel,
iso_readsector,
iso_readsector_raw,
iso_playaudio,
iso_seek,
iso_load,
@ -243,6 +356,8 @@ static ATAPI iso_atapi =
iso_pause,
iso_resume,
iso_size,
iso_status,
iso_is_track_audio,
iso_stop,
iso_exit
};

View file

@ -8,7 +8,6 @@ extern char iso_path[1024];
extern int iso_open(char *fn);
extern void iso_reset();
#define CDROM_ISO 200
extern void iso_close();
#endif /* ! CDROM_ISO_H */

View file

@ -40,6 +40,12 @@ static int null_ready(void)
return 0;
}
/* Always return 0, the contents of a null CD-ROM drive never change. */
static int null_medium_changed(void)
{
return 0;
}
static uint8_t null_getcurrentsubchannel(uint8_t *b, int msf)
{
return 0x13;
@ -57,13 +63,23 @@ static void null_readsector(uint8_t *b, int sector)
{
}
static void null_readsector_raw(uint8_t *b, int sector)
{
}
static int null_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
{
return 0;
}
static void null_readtoc_session(unsigned char *b, int msf, int maxlen)
static int null_readtoc_session(unsigned char *b, int msf, int maxlen)
{
return 0;
}
static int null_readtoc_raw(unsigned char *b, int maxlen)
{
return 0;
}
static uint32_t null_size()
@ -71,6 +87,11 @@ static uint32_t null_size()
return 0;
}
static int null_status()
{
return CD_STATUS_EMPTY;
}
void cdrom_null_reset()
{
}
@ -81,7 +102,7 @@ int cdrom_null_open(char d)
return 0;
}
static void null_close(void)
void null_close(void)
{
}
@ -89,13 +110,21 @@ static void null_exit(void)
{
}
static int null_is_track_audio(uint32_t pos, int ismsf)
{
return 0;
}
static ATAPI null_atapi =
{
null_ready,
null_medium_changed,
null_readtoc,
null_readtoc_session,
null_readtoc_raw,
null_getcurrentsubchannel,
null_readsector,
null_readsector_raw,
null_playaudio,
null_seek,
null_load,
@ -103,6 +132,8 @@ static ATAPI null_atapi =
null_pause,
null_resume,
null_size,
null_status,
null_is_track_audio,
null_stop,
null_exit
};

View file

@ -6,5 +6,6 @@
extern int cdrom_null_open(char d);
extern void cdrom_null_reset();
extern void null_close();
#endif /* ! CDROM_IOCTL_H */

View file

@ -452,9 +452,18 @@ int keybsenddelay;
/*CD-ROM*/
extern int cdrom_drive;
extern int old_cdrom_drive;
extern int idecallback[2];
extern int cdrom_enabled;
#define CD_STATUS_EMPTY 0
#define CD_STATUS_DATA_ONLY 1
#define CD_STATUS_PLAYING 2
#define CD_STATUS_PAUSED 3
#define CD_STATUS_STOPPED 4
extern uint32_t atapi_get_cd_volume(int channel);
void pclog(const char *format, ...);
extern int nmi;

1268
src/ide.c

File diff suppressed because it is too large Load diff

View file

@ -20,10 +20,13 @@ extern void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), i
typedef struct ATAPI
{
int (*ready)(void);
int (*medium_changed)(void);
int (*readtoc)(uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single);
void (*readtoc_session)(uint8_t *b, int msf, int maxlen);
int (*readtoc_session)(uint8_t *b, int msf, int maxlen);
int (*readtoc_raw)(uint8_t *b, int maxlen);
uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf);
void (*readsector)(uint8_t *b, int sector);
void (*readsector_raw)(uint8_t *b, int sector);
void (*playaudio)(uint32_t pos, uint32_t len, int ismsf);
void (*seek)(uint32_t pos);
void (*load)(void);
@ -31,6 +34,8 @@ typedef struct ATAPI
void (*pause)(void);
void (*resume)(void);
uint32_t (*size)(void);
int (*status)(void);
int (*is_track_audio)(uint32_t pos, int ismsf);
void (*stop)(void);
void (*exit)(void);
} ATAPI;
@ -38,6 +43,7 @@ typedef struct ATAPI
extern ATAPI *atapi;
void atapi_discchanged();
void atapi_insert_cdrom();
extern int ideboard;
@ -47,4 +53,6 @@ extern char ide_fn[4][512];
extern int cdrom_channel;
#define CDROM_ISO 200
#endif //__IDE__

View file

@ -276,7 +276,22 @@ void initpc(int argc, char *argv[])
{
if (cdrom_drive == CDROM_ISO)
{
iso_open(iso_path);
FILE *ff = fopen(iso_path, "rb");
if (ff)
{
fclose(ff);
iso_open(iso_path);
}
else
{
#if __unix
cdrom_drive = -1;
cdrom_null_open(cdrom_drive);
#else
cdrom_drive = 0;
ioctl_open(cdrom_drive);
#endif
}
}
else
{

View file

@ -110,10 +110,15 @@ static void sound_cd_thread(void *param)
ioctl_audio_callback(cd_buffer, CD_BUFLEN*2);
if (soundon)
{
int32_t atapi_vol_l = atapi_get_cd_volume(0);
int32_t atapi_vol_r = atapi_get_cd_volume(1);
for (c = 0; c < CD_BUFLEN*2; c += 2)
{
cd_buffer[c] = ((int32_t)cd_buffer[c] * cd_vol_l) / 65535;
cd_buffer[c] = ((int32_t)cd_buffer[c] * atapi_vol_l) / 255;
cd_buffer[c+1] = ((int32_t)cd_buffer[c+1] * cd_vol_r) / 65535;
cd_buffer[c+1] = ((int32_t)cd_buffer[c+1] * atapi_vol_r) / 255;
}
givealbuffer_cd(cd_buffer);
}

View file

@ -830,11 +830,25 @@ LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam );
}
void atapi_close(void)
{
switch (cdrom_drive)
{
case CDROM_ISO:
iso_close();
break;
default:
ioctl_close();
break;
}
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HMENU hmenu;
RECT rect;
char temp_iso_path[1024];
int new_cdrom_drive;
// pclog("Message %i %08X\n",message,message);
switch (message)
{
@ -980,12 +994,21 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
{
if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
break;
}
atapi->exit();
}
if (!cdrom_enabled)
{
/* Switching from disabled to disabled. Do nothing. */
break;
}
atapi->exit();
atapi_close();
ioctl_open(0);
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_CHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
old_cdrom_drive = cdrom_drive;
cdrom_drive=0;
CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
if (cdrom_enabled)
{
pause = 1;
@ -1002,12 +1025,24 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
{
if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
break;
}
atapi->exit();
}
if ((cdrom_drive == 0) && cdrom_enabled)
{
/* Switch from empty to empty. Do nothing. */
break;
}
atapi->exit();
atapi_close();
ioctl_open(0);
if (cdrom_enabled)
{
/* Signal disc change to the emulated machine. */
atapi_insert_cdrom();
}
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
old_cdrom_drive = cdrom_drive;
cdrom_drive=0;
CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_CHECKED);
saveconfig();
@ -1030,14 +1065,26 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
break;
}
atapi->exit();
old_cdrom_drive = cdrom_drive;
strcpy(temp_iso_path, openfilestring);
if ((strcmp(iso_path, temp_iso_path) == 0) && (cdrom_drive == CDROM_ISO) && cdrom_enabled)
{
/* Switching from ISO to the same ISO. Do nothing. */
break;
}
atapi->exit();
atapi_close();
iso_open(temp_iso_path);
if (cdrom_enabled)
{
/* Signal disc change to the emulated machine. */
atapi_insert_cdrom();
}
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
cdrom_drive = CDROM_ISO;
iso_open(temp_iso_path);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_CHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_CHECKED);
saveconfig();
if (!cdrom_enabled)
{
@ -1058,13 +1105,26 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
{
if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
break;
}
atapi->exit();
ioctl_open(LOWORD(wParam)-IDM_CDROM_REAL);
}
new_cdrom_drive = LOWORD(wParam)-IDM_CDROM_REAL;
if ((cdrom_drive == new_cdrom_drive) && cdrom_enabled)
{
/* Switching to the same drive. Do nothing. */
break;
}
old_cdrom_drive = cdrom_drive;
atapi->exit();
atapi_close();
ioctl_open(new_cdrom_drive);
if (cdrom_enabled)
{
/* Signal disc change to the emulated machine. */
atapi_insert_cdrom();
}
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
cdrom_drive = LOWORD(wParam) - IDM_CDROM_REAL;
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
cdrom_drive = new_cdrom_drive;
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED);
saveconfig();
if (!cdrom_enabled)