fix gdrom GET_TOC response

This commit is contained in:
Anthony Pesch 2017-06-18 22:22:21 -04:00
parent dc698f8d67
commit 9d0ce3700a
6 changed files with 71 additions and 19 deletions

View File

@ -67,6 +67,24 @@ static int cdi_read_sector(struct disc *disc, int fad, enum gd_secfmt fmt,
return res;
}
static void cdi_get_toc(struct disc *disc, enum gd_area area,
struct track **first_track, struct track **last_track,
int *leadin_fad, int *leadout_fad) {
struct cdi *cdi = (struct cdi *)disc;
/* cdi's have no high-density area */
CHECK_EQ(area, AREA_SINGLE);
/* the toc on cdi's represents all tracks / sessions */
struct session *first_session = &cdi->sessions[0];
struct session *last_session = &cdi->sessions[cdi->num_sessions - 1];
*first_track = &cdi->tracks[0];
*last_track = &cdi->tracks[cdi->num_tracks - 1];
*leadin_fad = first_session->leadin_fad;
*leadout_fad = last_session->leadout_fad;
}
static struct track *cdi_get_track(struct disc *disc, int n) {
struct cdi *cdi = (struct cdi *)disc;
CHECK_LT(n, cdi->num_tracks);
@ -183,19 +201,21 @@ static int cdi_parse_track(struct disc *disc, uint32_t version,
}
int sector_size = cdi_sector_sizes[sector_type];
enum gd_secfmt sector_fmt = cdi_sector_formats[mode];
int data_offset = *track_offset + pregap_length * sector_size;
track->fad = pregap_length + lba;
track->adr = 0; /* no subq channel mode info */
track->ctrl = 4; /* data track */
track->adr = 0;
track->ctrl = sector_fmt == SECTOR_CDDA ? 0 : 4;
track->sector_size = sector_size;
track->sector_fmt = cdi_sector_formats[mode];
track->file_offset = *track_offset + pregap_length * sector_size -
track->fad * track->sector_size;
track->file_offset = data_offset - track->fad * track->sector_size;
LOG_INFO("cdi_parse_track track=%d fad=%d mode=%s/%d", track->num, track->fad,
cdi_modes[mode], track->sector_size);
LOG_INFO("cdi_parse_track track=%d fad=%d off=%d mode=%s/%d", track->num,
track->fad, data_offset, cdi_modes[mode], track->sector_size);
*track_offset += total_length * sector_size;
*leadout_fad = track->fad + total_length;
*leadout_fad = track->fad + track_length;
return 1;
}
@ -341,6 +361,7 @@ struct disc *cdi_create(const char *filename) {
cdi->get_session = &cdi_get_session;
cdi->get_num_tracks = &cdi_get_num_tracks;
cdi->get_track = &cdi_get_track;
cdi->get_toc = &cdi_get_toc;
cdi->read_sector = &cdi_read_sector;
struct disc *disc = (struct disc *)cdi;

View File

@ -33,6 +33,12 @@ int disc_read_sector(struct disc *disc, int fad, enum gd_secfmt fmt,
return disc->read_sector(disc, fad, fmt, mask, dst);
}
void disc_get_toc(struct disc *disc, enum gd_area area,
struct track **first_track, struct track **last_track,
int *leadin_fad, int *leadout_fad) {
disc->get_toc(disc, area, first_track, last_track, leadin_fad, leadout_fad);
}
struct track *disc_get_track(struct disc *disc, int n) {
return disc->get_track(disc, n);
}

View File

@ -43,11 +43,17 @@ struct disc_meta {
struct disc {
void (*destroy)(struct disc *);
int (*get_format)(struct disc *);
int (*get_num_sessions)(struct disc *);
struct session *(*get_session)(struct disc *, int);
int (*get_num_tracks)(struct disc *);
struct track *(*get_track)(struct disc *, int);
void (*get_toc)(struct disc *, enum gd_area, struct track **, struct track **,
int *, int *);
int (*read_sector)(struct disc *, int, enum gd_secfmt, enum gd_secmask,
void *);
};
@ -61,6 +67,9 @@ int disc_get_num_sessions(struct disc *disc);
struct session *disc_get_session(struct disc *disc, int n);
int disc_get_num_tracks(struct disc *disc);
struct track *disc_get_track(struct disc *disc, int n);
void disc_get_toc(struct disc *disc, enum gd_area area,
struct track **first_track, struct track **last_track,
int *leadin_fad, int *leadout_fad);
int disc_read_sector(struct disc *disc, int fad, enum gd_secfmt fmt,
enum gd_secmask mask, void *dst);
struct track *disc_lookup_track(struct disc *disc, int fad);

View File

@ -43,6 +43,20 @@ static int gdi_read_sector(struct disc *disc, int fad, enum gd_secfmt fmt,
return res;
}
static void gdi_get_toc(struct disc *disc, enum gd_area area,
struct track **first_track, struct track **last_track,
int *leadin_fad, int *leadout_fad) {
struct gdi *gdi = (struct gdi *)disc;
/* gdi's have one toc per area, and there is one session per area */
struct session *session = &gdi->sessions[area];
*first_track = &gdi->tracks[session->first_track];
*last_track = &gdi->tracks[session->last_track];
*leadin_fad = session->leadin_fad;
*leadout_fad = session->leadout_fad;
}
static struct track *gdi_get_track(struct disc *disc, int n) {
struct gdi *gdi = (struct gdi *)disc;
CHECK_LT(n, gdi->num_tracks);
@ -184,6 +198,7 @@ struct disc *gdi_create(const char *filename) {
gdi->get_session = &gdi_get_session;
gdi->get_num_tracks = &gdi_get_num_tracks;
gdi->get_track = &gdi_get_track;
gdi->get_toc = &gdi_get_toc;
gdi->read_sector = &gdi_read_sector;
struct disc *disc = (struct disc *)gdi;

View File

@ -616,11 +616,12 @@ void gdrom_get_toc(struct gdrom *gd, enum gd_area area, uint8_t *data,
------------------------------------------------------
407 | lead-out track fad (lsb) */
int num_sessions = disc_get_num_sessions(gd->disc);
struct session *session = disc_get_session(gd->disc, area);
struct session *last_session = disc_get_session(gd->disc, num_sessions - 1);
struct track *first_track = disc_get_track(gd->disc, session->first_track);
struct track *last_track = disc_get_track(gd->disc, session->last_track);
struct track *first_track = NULL;
struct track *last_track = NULL;
int leadin_fad = 0;
int leadout_fad = 0;
disc_get_toc(gd->disc, area, &first_track, &last_track, &leadin_fad,
&leadout_fad);
/* 0xffffffff represents an invalid track */
memset(data, 0xff, SPI_TOC_SIZE);
@ -630,15 +631,15 @@ void gdrom_get_toc(struct gdrom *gd, enum gd_area area, uint8_t *data,
for (int i = first_track->num; i <= last_track->num; i++) {
struct track *track = disc_get_track(gd->disc, i - 1);
*(entry++) = (bswap24(track->fad) << 8) | (track->ctrl << 4) | track->adr;
entry[i - 1] = (bswap24(track->fad) << 8) | (track->ctrl << 4) | track->adr;
}
/* write out first, last and lead-out track */
*(entry++) =
entry[99] =
(first_track->num << 8) | (first_track->ctrl << 4) | first_track->adr;
*(entry++) =
entry[100] =
(last_track->num << 8) | (last_track->ctrl << 4) | last_track->adr;
*(entry++) = (bswap24(last_session->leadout_fad) << 8);
entry[101] = (bswap24(leadout_fad) << 8);
}
void gdrom_get_error(struct gdrom *gd, uint8_t *data, int size) {
@ -947,13 +948,13 @@ REG_W32(holly_cb, GD_DRVSEL) {
REG_R32(holly_cb, GD_STATUS_COMMAND) {
struct gdrom *gd = dc->gdrom;
uint16_t value = gd->status.full;
LOG_GDROM("read GD_STATUS_COMMAND 0x%x", value);
LOG_GDROM("read GD_STATUS 0x%x", value);
holly_clear_interrupt(gd->holly, HOLLY_INT_G1GDINT);
return value;
}
REG_W32(holly_cb, GD_STATUS_COMMAND) {
struct gdrom *gd = dc->gdrom;
LOG_GDROM("write GD_STATUS_COMMAND 0x%x", value);
LOG_GDROM("write GD_COMMAND 0x%x", value);
gdrom_event(gd, EVENT_ATA_CMD, value);
}

View File

@ -144,7 +144,7 @@ TEST(sh4_x64) {
0, 0, 0, \
0, \
{{0}, {0}}, \
0, 0, \
0, 0, 0, \
{0}, \
}
#define TEST_SH4(name, buffer, buffer_size, buffer_offset, \