summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/cdrom.h
blob: 21665c1326f8108ef73b16209e0aa7288a833faf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    cdrom.h

    Generic MAME cd-rom implementation

***************************************************************************/

#pragma once

#ifndef __CDROM_H__
#define __CDROM_H__

#include "osdcore.h"
#include "chd.h"



/***************************************************************************
    CONSTANTS
***************************************************************************/

// tracks are padded to a multiple of this many frames
const uint32_t CD_TRACK_PADDING = 4;

#define CD_MAX_TRACKS           (99)    /* AFAIK the theoretical limit */
#define CD_MAX_SECTOR_DATA      (2352)
#define CD_MAX_SUBCODE_DATA     (96)

#define CD_FRAME_SIZE           (CD_MAX_SECTOR_DATA + CD_MAX_SUBCODE_DATA)
#define CD_FRAMES_PER_HUNK      (8)

#define CD_METADATA_WORDS       (1+(CD_MAX_TRACKS * 6))

enum
{
	CD_TRACK_MODE1 = 0,         /* mode 1 2048 bytes/sector */
	CD_TRACK_MODE1_RAW,         /* mode 1 2352 bytes/sector */
	CD_TRACK_MODE2,             /* mode 2 2336 bytes/sector */
	CD_TRACK_MODE2_FORM1,       /* mode 2 2048 bytes/sector */
	CD_TRACK_MODE2_FORM2,       /* mode 2 2324 bytes/sector */
	CD_TRACK_MODE2_FORM_MIX,    /* mode 2 2336 bytes/sector */
	CD_TRACK_MODE2_RAW,         /* mode 2 2352 bytes / sector */
	CD_TRACK_AUDIO,         /* redbook audio track 2352 bytes/sector (588 samples) */

	CD_TRACK_RAW_DONTCARE       /* special flag for cdrom_read_data: just return me whatever is there */
};

enum
{
	CD_SUB_NORMAL = 0,          /* "cooked" 96 bytes per sector */
	CD_SUB_RAW,                 /* raw uninterleaved 96 bytes per sector */
	CD_SUB_NONE                 /* no subcode data stored */
};

#define CD_FLAG_GDROM   0x00000001  // disc is a GD-ROM, all tracks should be stored with GD-ROM metadata
#define CD_FLAG_GDROMLE 0x00000002  // legacy GD-ROM, with little-endian CDDA data

/***************************************************************************
    TYPE DEFINITIONS
***************************************************************************/

struct cdrom_file;

struct cdrom_track_info
{
	/* fields used by CHDMAN and in MAME */
	uint32_t trktype;     /* track type */
	uint32_t subtype;     /* subcode data type */
	uint32_t datasize;    /* size of data in each sector of this track */
	uint32_t subsize;     /* size of subchannel data in each sector of this track */
	uint32_t frames;      /* number of frames in this track */
	uint32_t extraframes; /* number of "spillage" frames in this track */
	uint32_t pregap;      /* number of pregap frames */
	uint32_t postgap;     /* number of postgap frames */
	uint32_t pgtype;      /* type of sectors in pregap */
	uint32_t pgsub;       /* type of subchannel data in pregap */
	uint32_t pgdatasize;  /* size of data in each sector of the pregap */
	uint32_t pgsubsize;   /* size of subchannel data in each sector of the pregap */

	/* fields used in CHDMAN only */
	uint32_t padframes;   /* number of frames of padding to add to the end of the track; needed for GDI */

	/* fields used in MAME/MESS only */
	uint32_t logframeofs; /* logical frame of actual track data - offset by pregap size if pregap not physically present */
	uint32_t physframeofs; /* physical frame of actual track data in CHD data */
	uint32_t chdframeofs; /* frame number this track starts at on the CHD */
};


struct cdrom_toc
{
	uint32_t numtrks;     /* number of tracks */
	uint32_t flags;       /* see FLAG_ above */
	cdrom_track_info tracks[CD_MAX_TRACKS];
};



/***************************************************************************
    FUNCTION PROTOTYPES
***************************************************************************/

/* base functionality */
cdrom_file *cdrom_open(chd_file *chd);
void cdrom_close(cdrom_file *file);

cdrom_file *cdrom_open(const char *inputfile);

/* core read access */
uint32_t cdrom_read_data(cdrom_file *file, uint32_t lbasector, void *buffer, uint32_t datatype, bool phys=false);
uint32_t cdrom_read_subcode(cdrom_file *file, uint32_t lbasector, void *buffer, bool phys=false);

/* handy utilities */
uint32_t cdrom_get_track(cdrom_file *file, uint32_t frame);
uint32_t cdrom_get_track_start(cdrom_file *file, uint32_t track);
uint32_t cdrom_get_track_start_phys(cdrom_file *file, uint32_t track);

/* TOC utilities */
int cdrom_get_last_track(cdrom_file *file);
int cdrom_get_adr_control(cdrom_file *file, int track);
int cdrom_get_track_type(cdrom_file *file, int track);
const cdrom_toc *cdrom_get_toc(cdrom_file *file);

/* extra utilities */
void cdrom_convert_type_string_to_track_info(const char *typestring, cdrom_track_info *info);
void cdrom_convert_type_string_to_pregap_info(const char *typestring, cdrom_track_info *info);
void cdrom_convert_subtype_string_to_track_info(const char *typestring, cdrom_track_info *info);
void cdrom_convert_subtype_string_to_pregap_info(const char *typestring, cdrom_track_info *info);
const char *cdrom_get_type_string(uint32_t trktype);
const char *cdrom_get_subtype_string(uint32_t subtype);
chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc);
chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc);

// ECC utilities
bool ecc_verify(const uint8_t *sector);
void ecc_generate(uint8_t *sector);
void ecc_clear(uint8_t *sector);



/***************************************************************************
    INLINE FUNCTIONS
***************************************************************************/

static inline uint32_t msf_to_lba(uint32_t msf)
{
	return ( ((msf&0x00ff0000)>>16) * 60 * 75) + (((msf&0x0000ff00)>>8) * 75) + ((msf&0x000000ff)>>0);
}

static inline uint32_t lba_to_msf(uint32_t lba)
{
	uint8_t m, s, f;

	m = lba / (60 * 75);
	lba -= m * (60 * 75);
	s = lba / 75;
	f = lba % 75;

	return ((m / 10) << 20) | ((m % 10) << 16) |
			((s / 10) << 12) | ((s % 10) <<  8) |
			((f / 10) <<  4) | ((f % 10) <<  0);
}

// segacd needs it like this.. investigate
// Angelo also says PCE tracks often start playing at the
// wrong address.. related?
static inline uint32_t lba_to_msf_alt(int lba)
{
	uint32_t ret = 0;

	ret |= ((lba / (60 * 75))&0xff)<<16;
	ret |= (((lba / 75) % 60)&0xff)<<8;
	ret |= ((lba % 75)&0xff)<<0;

	return ret;
}




#endif  // __CDROM_H__