diff --git a/src/guest/gdrom/cdi.c b/src/guest/gdrom/cdi.c index 07cf2e16..5c498525 100644 --- a/src/guest/gdrom/cdi.c +++ b/src/guest/gdrom/cdi.c @@ -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; diff --git a/src/guest/gdrom/disc.c b/src/guest/gdrom/disc.c index 9948ada5..c0282a15 100644 --- a/src/guest/gdrom/disc.c +++ b/src/guest/gdrom/disc.c @@ -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); } diff --git a/src/guest/gdrom/disc.h b/src/guest/gdrom/disc.h index 17030bba..226ee0c2 100644 --- a/src/guest/gdrom/disc.h +++ b/src/guest/gdrom/disc.h @@ -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); diff --git a/src/guest/gdrom/gdi.c b/src/guest/gdrom/gdi.c index 4b6fde8e..3e09591f 100644 --- a/src/guest/gdrom/gdi.c +++ b/src/guest/gdrom/gdi.c @@ -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; diff --git a/src/guest/gdrom/gdrom.c b/src/guest/gdrom/gdrom.c index 3d0c5331..f7152a08 100644 --- a/src/guest/gdrom/gdrom.c +++ b/src/guest/gdrom/gdrom.c @@ -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); } diff --git a/test/test_sh4.c b/test/test_sh4.c index 5e72708f..d37cc528 100644 --- a/test/test_sh4.c +++ b/test/test_sh4.c @@ -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, \