move hard-coded gdrom fads into gdi implementation

This commit is contained in:
Anthony Pesch 2017-06-05 22:41:27 -04:00
parent 3783cb4123
commit 5cd96f7088
4 changed files with 121 additions and 61 deletions

View File

@ -5,27 +5,24 @@ static const int GDI_PREGAP_SIZE = 150;
struct disc {
void (*destroy)(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);
int (*read_sector)(struct disc *, int, void *);
};
struct gdi {
struct disc;
struct session sessions[2];
int num_sessions;
struct track tracks[64];
int num_tracks;
};
static int gdi_get_num_tracks(struct disc *disc) {
struct gdi *gdi = (struct gdi *)disc;
return gdi->num_tracks;
}
static struct track *gdi_get_track(struct disc *disc, int n) {
struct gdi *gdi = (struct gdi *)disc;
return &gdi->tracks[n];
}
static int gdi_read_sector(struct disc *disc, int fad, void *dst) {
struct gdi *gdi = (struct gdi *)disc;
@ -60,6 +57,28 @@ static int gdi_read_sector(struct disc *disc, int fad, void *dst) {
return 1;
}
static struct track *gdi_get_track(struct disc *disc, int n) {
struct gdi *gdi = (struct gdi *)disc;
CHECK_LT(n, gdi->num_tracks);
return &gdi->tracks[n];
}
static int gdi_get_num_tracks(struct disc *disc) {
struct gdi *gdi = (struct gdi *)disc;
return gdi->num_tracks;
}
static struct session *gdi_get_session(struct disc *disc, int n) {
struct gdi *gdi = (struct gdi *)disc;
CHECK_LT(n, gdi->num_sessions);
return &gdi->sessions[n];
}
static int gdi_get_num_sessions(struct disc *disc) {
struct gdi *gdi = (struct gdi *)disc;
return gdi->num_sessions;
}
static void gdi_destroy(struct disc *disc) {
struct gdi *gdi = (struct gdi *)disc;
@ -77,6 +96,8 @@ static struct gdi *gdi_create(const char *filename) {
struct gdi *gdi = calloc(1, sizeof(struct gdi));
gdi->destroy = &gdi_destroy;
gdi->get_num_sessions = &gdi_get_num_sessions;
gdi->get_session = &gdi_get_session;
gdi->get_num_tracks = &gdi_get_num_tracks;
gdi->get_track = &gdi_get_track;
gdi->read_sector = &gdi_read_sector;
@ -87,8 +108,11 @@ static struct gdi *gdi_create(const char *filename) {
return NULL;
}
/* <number of tracks>
<track num> <lba> <ctrl> <sector size> <file name> <file offset> */
/* get gdi dirname to help resolve track paths */
char dirname[PATH_MAX];
fs_dirname(filename, dirname, sizeof(dirname));
/* parse tracks */
int num_tracks;
int n = fscanf(fp, "%d", &num_tracks);
if (n != 1) {
@ -97,15 +121,13 @@ static struct gdi *gdi_create(const char *filename) {
return NULL;
}
/* get gdi dirname to help resolve track paths */
char dirname[PATH_MAX];
fs_dirname(filename, dirname, sizeof(dirname));
for (int i = 0; i < num_tracks; i++) {
int num, lba, ctrl, sector_size, file_offset;
char filename[PATH_MAX];
n = fscanf(fp, "%d %d %d %d %s %d", &num, &lba, &ctrl, &sector_size,
filename, &file_offset);
if (n != 6) {
free(gdi);
fclose(fp);
@ -123,6 +145,26 @@ static struct gdi *gdi_create(const char *filename) {
dirname, filename);
}
/* gdroms contains two sessions, one for the single density area (tracks 0-1)
and one for the high density area (tracks 3+) */
gdi->num_sessions = 2;
/* single density area starts at 00:00:00 (fad 0x0) and can hold up to 4
minutes of data (18,000 sectors at 75 sectors per second) */
struct session *single = &gdi->sessions[0];
single->leadin_fad = 0x0;
single->first_track = &gdi->tracks[0];
single->last_track = &gdi->tracks[1];
single->leadout_fad = 0x4650;
/* high density area starts at 10:00:00 (fad 0xb05e) and can hold up to
504,300 sectors (112 minutes, 4 seconds at 75 sectors per second) */
struct session *high = &gdi->sessions[1];
high->leadin_fad = 0xb05e;
high->first_track = &gdi->tracks[2];
high->last_track = &gdi->tracks[num_tracks - 1];
high->leadout_fad = 0x861b4;
fclose(fp);
return gdi;
@ -140,6 +182,14 @@ int disc_get_num_tracks(struct disc *disc) {
return disc->get_num_tracks(disc);
}
struct session *disc_get_session(struct disc *disc, int n) {
return disc->get_session(disc, n);
}
int disc_get_num_sessions(struct disc *disc) {
return disc->get_num_sessions(disc);
}
void disc_destroy(struct disc *disc) {
disc->destroy(disc);
}

View File

@ -15,13 +15,24 @@ struct track {
FILE *file;
};
struct session {
int leadin_fad;
struct track *first_track;
struct track *last_track;
int leadout_fad;
};
struct disc;
struct disc *disc_create_gdi(const char *filename);
void disc_destroy(struct disc *disc);
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);
int disc_read_sector(struct disc *disc, int fad, void *dst);
#endif

View File

@ -445,10 +445,22 @@ void gdrom_get_subcode(struct gdrom *gd, int format, uint8_t *data, int size) {
memset(data, 0, SPI_SCD_SIZE);
data[1] = AST_NOSTATUS;
switch (format) {
case 0:
data[2] = 0x0;
data[3] = 0x64;
break;
case 1:
data[2] = 0x0;
data[3] = 0xe;
break;
}
LOG_GDROM("gdrom_get_subcode not fully implemented");
}
void gdrom_get_session(struct gdrom *gd, int session, uint8_t *data, int size) {
void gdrom_get_session(struct gdrom *gd, int session_num, uint8_t *data,
int size) {
CHECK_GE(size, SPI_SES_SIZE);
/* session response layout:
@ -469,29 +481,31 @@ void gdrom_get_session(struct gdrom *gd, int session, uint8_t *data, int size) {
5 | lead out fad (lsb) / starting fad (lsb) */
uint8_t status = gd->sectnum.status;
uint8_t track = 0;
uint8_t track_num = 0;
uint32_t fad = 0;
if (session == 0) {
/* when session is 0, the "fad" field contains the lead-out fad, while the
"track" field contains the total number of sessions */
if (1 /* is gd-rom */) {
track = 2;
fad = 0x861b4;
/* when session is 0 the "track_num" field contains the total number of
sessions, while the "fad" field contains the lead-out fad
when session is non-0, the "track_num" field contains the first track of
the session, while the "fad" field contains contains the starting fad of
the specified session */
if (gd->sectnum.format == DISC_GDROM) {
if (session_num == 0) {
int num_sessions = disc_get_num_sessions(gd->disc);
struct session *last_session =
disc_get_session(gd->disc, num_sessions - 1);
track_num = num_sessions;
fad = last_session->leadout_fad;
} else {
struct session *session = disc_get_session(gd->disc, session_num - 1);
struct track *first_track = session->first_track;
track_num = first_track->num;
fad = first_track->fad;
}
} else {
/* when session is non-0, the "fad" field contains contains the starting fad
of the specified session, while the "track" field contains the first
track of the session */
if (session == 1) {
struct track *trk = disc_get_track(gd->disc, 0);
track = 1;
fad = trk->fad;
} else if (session == 2) {
struct track *trk = disc_get_track(gd->disc, 2);
track = 3;
fad = trk->fad;
}
LOG_FATAL("unsupported disc type");
}
/* fad is written out big-endian */
@ -500,7 +514,7 @@ void gdrom_get_session(struct gdrom *gd, int session, uint8_t *data, int size) {
data[0] = status;
data[1] = 0;
memcpy(&data[2], &fad, 3);
data[5] = track;
data[5] = track_num;
}
void gdrom_get_toc(struct gdrom *gd, enum gd_area area_type, uint8_t *data,
@ -544,38 +558,23 @@ void gdrom_get_toc(struct gdrom *gd, enum gd_area area_type, uint8_t *data,
------------------------------------------------------
407 | lead-out track fad (lsb) */
/* for GD-ROMs, the single density area contains tracks 1 and 2, while the
dual density area contains tracks 3 - num_tracks */
int start_track_num = 0;
int end_track_num = disc_get_num_tracks(gd->disc) - 1;
/* TODO conditionally check disc to make sure it's a GD-ROM once
CD-ROMs are supported */
if (1 /* is gd-rom */) {
if (area_type == AREA_SINGLE) {
end_track_num = 1;
} else {
start_track_num = 2;
}
}
uint32_t *entry = (uint32_t *)data;
const struct track *start = disc_get_track(gd->disc, start_track_num);
const struct track *end = disc_get_track(gd->disc, end_track_num);
int leadout_fad = area_type == AREA_SINGLE ? 0x4650 : 0x861b4;
const struct session *session = disc_get_session(gd->disc, area_type);
const struct track *first = session->first_track;
const struct track *last = session->last_track;
memset(data, 0, SPI_TOC_SIZE);
/* write out entries for each track */
for (int i = start_track_num; i <= end_track_num; i++) {
const struct track *track = disc_get_track(gd->disc, i);
for (int i = first->num; i <= last->num; i++) {
const struct track *track = disc_get_track(gd->disc, i - 1);
*(entry++) = (bswap24(track->fad) << 8) | (track->ctrl << 4) | track->adr;
}
/* write out start, end and lead-out track */
*(entry++) = (start_track_num << 8) | (start->ctrl << 4) | start->adr;
*(entry++) = (end_track_num << 8) | (end->ctrl << 4) | end->adr;
*(entry++) = (bswap24(leadout_fad) << 8);
*(entry++) = (first->num << 8) | (first->ctrl << 4) | first->adr;
*(entry++) = (last->num << 8) | (last->ctrl << 4) | last->adr;
*(entry++) = (bswap24(session->leadout_fad) << 8);
}
void gdrom_get_status(struct gdrom *gd, uint8_t *data, int size) {

View File

@ -61,7 +61,7 @@ enum {
enum gd_area {
AREA_SINGLE,
AREA_DOUBLE,
AREA_HIGH,
};
enum gd_audio_status {