mirror of https://github.com/inolen/redream.git
move hard-coded gdrom fads into gdi implementation
This commit is contained in:
parent
3783cb4123
commit
5cd96f7088
|
@ -5,27 +5,24 @@ static const int GDI_PREGAP_SIZE = 150;
|
||||||
|
|
||||||
struct disc {
|
struct disc {
|
||||||
void (*destroy)(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 *);
|
int (*get_num_tracks)(struct disc *);
|
||||||
struct track *(*get_track)(struct disc *, int);
|
struct track *(*get_track)(struct disc *, int);
|
||||||
|
|
||||||
int (*read_sector)(struct disc *, int, void *);
|
int (*read_sector)(struct disc *, int, void *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gdi {
|
struct gdi {
|
||||||
struct disc;
|
struct disc;
|
||||||
|
struct session sessions[2];
|
||||||
|
int num_sessions;
|
||||||
struct track tracks[64];
|
struct track tracks[64];
|
||||||
int num_tracks;
|
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) {
|
static int gdi_read_sector(struct disc *disc, int fad, void *dst) {
|
||||||
struct gdi *gdi = (struct gdi *)disc;
|
struct gdi *gdi = (struct gdi *)disc;
|
||||||
|
|
||||||
|
@ -60,6 +57,28 @@ static int gdi_read_sector(struct disc *disc, int fad, void *dst) {
|
||||||
return 1;
|
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) {
|
static void gdi_destroy(struct disc *disc) {
|
||||||
struct gdi *gdi = (struct gdi *)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));
|
struct gdi *gdi = calloc(1, sizeof(struct gdi));
|
||||||
|
|
||||||
gdi->destroy = &gdi_destroy;
|
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_num_tracks = &gdi_get_num_tracks;
|
||||||
gdi->get_track = &gdi_get_track;
|
gdi->get_track = &gdi_get_track;
|
||||||
gdi->read_sector = &gdi_read_sector;
|
gdi->read_sector = &gdi_read_sector;
|
||||||
|
@ -87,8 +108,11 @@ static struct gdi *gdi_create(const char *filename) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* <number of tracks>
|
/* get gdi dirname to help resolve track paths */
|
||||||
<track num> <lba> <ctrl> <sector size> <file name> <file offset> */
|
char dirname[PATH_MAX];
|
||||||
|
fs_dirname(filename, dirname, sizeof(dirname));
|
||||||
|
|
||||||
|
/* parse tracks */
|
||||||
int num_tracks;
|
int num_tracks;
|
||||||
int n = fscanf(fp, "%d", &num_tracks);
|
int n = fscanf(fp, "%d", &num_tracks);
|
||||||
if (n != 1) {
|
if (n != 1) {
|
||||||
|
@ -97,15 +121,13 @@ static struct gdi *gdi_create(const char *filename) {
|
||||||
return NULL;
|
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++) {
|
for (int i = 0; i < num_tracks; i++) {
|
||||||
int num, lba, ctrl, sector_size, file_offset;
|
int num, lba, ctrl, sector_size, file_offset;
|
||||||
char filename[PATH_MAX];
|
char filename[PATH_MAX];
|
||||||
|
|
||||||
n = fscanf(fp, "%d %d %d %d %s %d", &num, &lba, &ctrl, §or_size,
|
n = fscanf(fp, "%d %d %d %d %s %d", &num, &lba, &ctrl, §or_size,
|
||||||
filename, &file_offset);
|
filename, &file_offset);
|
||||||
|
|
||||||
if (n != 6) {
|
if (n != 6) {
|
||||||
free(gdi);
|
free(gdi);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
@ -123,6 +145,26 @@ static struct gdi *gdi_create(const char *filename) {
|
||||||
dirname, 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);
|
fclose(fp);
|
||||||
|
|
||||||
return gdi;
|
return gdi;
|
||||||
|
@ -140,6 +182,14 @@ int disc_get_num_tracks(struct disc *disc) {
|
||||||
return disc->get_num_tracks(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) {
|
void disc_destroy(struct disc *disc) {
|
||||||
disc->destroy(disc);
|
disc->destroy(disc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,24 @@ struct track {
|
||||||
FILE *file;
|
FILE *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct session {
|
||||||
|
int leadin_fad;
|
||||||
|
struct track *first_track;
|
||||||
|
struct track *last_track;
|
||||||
|
int leadout_fad;
|
||||||
|
};
|
||||||
|
|
||||||
struct disc;
|
struct disc;
|
||||||
|
|
||||||
struct disc *disc_create_gdi(const char *filename);
|
struct disc *disc_create_gdi(const char *filename);
|
||||||
void disc_destroy(struct disc *disc);
|
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);
|
int disc_get_num_tracks(struct disc *disc);
|
||||||
struct track *disc_get_track(struct disc *disc, int n);
|
struct track *disc_get_track(struct disc *disc, int n);
|
||||||
|
|
||||||
int disc_read_sector(struct disc *disc, int fad, void *dst);
|
int disc_read_sector(struct disc *disc, int fad, void *dst);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -445,10 +445,22 @@ void gdrom_get_subcode(struct gdrom *gd, int format, uint8_t *data, int size) {
|
||||||
memset(data, 0, SPI_SCD_SIZE);
|
memset(data, 0, SPI_SCD_SIZE);
|
||||||
data[1] = AST_NOSTATUS;
|
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");
|
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);
|
CHECK_GE(size, SPI_SES_SIZE);
|
||||||
|
|
||||||
/* session response layout:
|
/* 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) */
|
5 | lead out fad (lsb) / starting fad (lsb) */
|
||||||
|
|
||||||
uint8_t status = gd->sectnum.status;
|
uint8_t status = gd->sectnum.status;
|
||||||
uint8_t track = 0;
|
uint8_t track_num = 0;
|
||||||
uint32_t fad = 0;
|
uint32_t fad = 0;
|
||||||
|
|
||||||
if (session == 0) {
|
/* when session is 0 the "track_num" field contains the total number of
|
||||||
/* when session is 0, the "fad" field contains the lead-out fad, while the
|
sessions, while the "fad" field contains the lead-out fad
|
||||||
"track" field contains the total number of sessions */
|
|
||||||
if (1 /* is gd-rom */) {
|
when session is non-0, the "track_num" field contains the first track of
|
||||||
track = 2;
|
the session, while the "fad" field contains contains the starting fad of
|
||||||
fad = 0x861b4;
|
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 {
|
} else {
|
||||||
/* when session is non-0, the "fad" field contains contains the starting fad
|
LOG_FATAL("unsupported disc type");
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fad is written out big-endian */
|
/* 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[0] = status;
|
||||||
data[1] = 0;
|
data[1] = 0;
|
||||||
memcpy(&data[2], &fad, 3);
|
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,
|
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) */
|
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;
|
uint32_t *entry = (uint32_t *)data;
|
||||||
const struct track *start = disc_get_track(gd->disc, start_track_num);
|
const struct session *session = disc_get_session(gd->disc, area_type);
|
||||||
const struct track *end = disc_get_track(gd->disc, end_track_num);
|
const struct track *first = session->first_track;
|
||||||
int leadout_fad = area_type == AREA_SINGLE ? 0x4650 : 0x861b4;
|
const struct track *last = session->last_track;
|
||||||
|
|
||||||
memset(data, 0, SPI_TOC_SIZE);
|
memset(data, 0, SPI_TOC_SIZE);
|
||||||
|
|
||||||
/* write out entries for each track */
|
/* write out entries for each track */
|
||||||
for (int i = start_track_num; i <= end_track_num; i++) {
|
for (int i = first->num; i <= last->num; i++) {
|
||||||
const struct track *track = disc_get_track(gd->disc, i);
|
const struct track *track = disc_get_track(gd->disc, i - 1);
|
||||||
*(entry++) = (bswap24(track->fad) << 8) | (track->ctrl << 4) | track->adr;
|
*(entry++) = (bswap24(track->fad) << 8) | (track->ctrl << 4) | track->adr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write out start, end and lead-out track */
|
/* write out start, end and lead-out track */
|
||||||
*(entry++) = (start_track_num << 8) | (start->ctrl << 4) | start->adr;
|
*(entry++) = (first->num << 8) | (first->ctrl << 4) | first->adr;
|
||||||
*(entry++) = (end_track_num << 8) | (end->ctrl << 4) | end->adr;
|
*(entry++) = (last->num << 8) | (last->ctrl << 4) | last->adr;
|
||||||
*(entry++) = (bswap24(leadout_fad) << 8);
|
*(entry++) = (bswap24(session->leadout_fad) << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdrom_get_status(struct gdrom *gd, uint8_t *data, int size) {
|
void gdrom_get_status(struct gdrom *gd, uint8_t *data, int size) {
|
||||||
|
|
|
@ -61,7 +61,7 @@ enum {
|
||||||
|
|
||||||
enum gd_area {
|
enum gd_area {
|
||||||
AREA_SINGLE,
|
AREA_SINGLE,
|
||||||
AREA_DOUBLE,
|
AREA_HIGH,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum gd_audio_status {
|
enum gd_audio_status {
|
||||||
|
|
Loading…
Reference in New Issue