1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     cdrom.h
6 
7     Generic MAME cd-rom implementation
8 
9 ***************************************************************************/
10 
11 #ifndef MAME_UTIL_CDROM_H
12 #define MAME_UTIL_CDROM_H
13 
14 #pragma once
15 
16 #include "osdcore.h"
17 #include "chd.h"
18 
19 
20 
21 /***************************************************************************
22     CONSTANTS
23 ***************************************************************************/
24 
25 // tracks are padded to a multiple of this many frames
26 const uint32_t CD_TRACK_PADDING = 4;
27 
28 #define CD_MAX_TRACKS           (99)    /* AFAIK the theoretical limit */
29 #define CD_MAX_SECTOR_DATA      (2352)
30 #define CD_MAX_SUBCODE_DATA     (96)
31 
32 #define CD_FRAME_SIZE           (CD_MAX_SECTOR_DATA + CD_MAX_SUBCODE_DATA)
33 #define CD_FRAMES_PER_HUNK      (8)
34 
35 #define CD_METADATA_WORDS       (1+(CD_MAX_TRACKS * 6))
36 
37 enum
38 {
39 	CD_TRACK_MODE1 = 0,         /* mode 1 2048 bytes/sector */
40 	CD_TRACK_MODE1_RAW,         /* mode 1 2352 bytes/sector */
41 	CD_TRACK_MODE2,             /* mode 2 2336 bytes/sector */
42 	CD_TRACK_MODE2_FORM1,       /* mode 2 2048 bytes/sector */
43 	CD_TRACK_MODE2_FORM2,       /* mode 2 2324 bytes/sector */
44 	CD_TRACK_MODE2_FORM_MIX,    /* mode 2 2336 bytes/sector */
45 	CD_TRACK_MODE2_RAW,         /* mode 2 2352 bytes / sector */
46 	CD_TRACK_AUDIO,         /* redbook audio track 2352 bytes/sector (588 samples) */
47 
48 	CD_TRACK_RAW_DONTCARE       /* special flag for cdrom_read_data: just return me whatever is there */
49 };
50 
51 enum
52 {
53 	CD_SUB_NORMAL = 0,          /* "cooked" 96 bytes per sector */
54 	CD_SUB_RAW,                 /* raw uninterleaved 96 bytes per sector */
55 	CD_SUB_NONE                 /* no subcode data stored */
56 };
57 
58 #define CD_FLAG_GDROM   0x00000001  // disc is a GD-ROM, all tracks should be stored with GD-ROM metadata
59 #define CD_FLAG_GDROMLE 0x00000002  // legacy GD-ROM, with little-endian CDDA data
60 
61 /***************************************************************************
62     TYPE DEFINITIONS
63 ***************************************************************************/
64 
65 struct cdrom_file;
66 
67 struct cdrom_track_info
68 {
69 	/* fields used by CHDMAN and in MAME */
70 	uint32_t trktype;     /* track type */
71 	uint32_t subtype;     /* subcode data type */
72 	uint32_t datasize;    /* size of data in each sector of this track */
73 	uint32_t subsize;     /* size of subchannel data in each sector of this track */
74 	uint32_t frames;      /* number of frames in this track */
75 	uint32_t extraframes; /* number of "spillage" frames in this track */
76 	uint32_t pregap;      /* number of pregap frames */
77 	uint32_t postgap;     /* number of postgap frames */
78 	uint32_t pgtype;      /* type of sectors in pregap */
79 	uint32_t pgsub;       /* type of subchannel data in pregap */
80 	uint32_t pgdatasize;  /* size of data in each sector of the pregap */
81 	uint32_t pgsubsize;   /* size of subchannel data in each sector of the pregap */
82 
83 	/* fields used in CHDMAN only */
84 	uint32_t padframes;   /* number of frames of padding to add to the end of the track; needed for GDI */
85 
86 	/* fields used in MAME/MESS only */
87 	uint32_t logframeofs; /* logical frame of actual track data - offset by pregap size if pregap not physically present */
88 	uint32_t physframeofs; /* physical frame of actual track data in CHD data */
89 	uint32_t chdframeofs; /* frame number this track starts at on the CHD */
90 };
91 
92 
93 struct cdrom_toc
94 {
95 	uint32_t numtrks;     /* number of tracks */
96 	uint32_t flags;       /* see FLAG_ above */
97 	cdrom_track_info tracks[CD_MAX_TRACKS];
98 };
99 
100 
101 
102 /***************************************************************************
103     FUNCTION PROTOTYPES
104 ***************************************************************************/
105 
106 /* base functionality */
107 cdrom_file *cdrom_open(chd_file *chd);
108 void cdrom_close(cdrom_file *file);
109 
110 cdrom_file *cdrom_open(const char *inputfile);
111 
112 /* core read access */
113 uint32_t cdrom_read_data(cdrom_file *file, uint32_t lbasector, void *buffer, uint32_t datatype, bool phys=false);
114 uint32_t cdrom_read_subcode(cdrom_file *file, uint32_t lbasector, void *buffer, bool phys=false);
115 
116 /* handy utilities */
117 uint32_t cdrom_get_track(cdrom_file *file, uint32_t frame);
118 uint32_t cdrom_get_track_start(cdrom_file *file, uint32_t track);
119 uint32_t cdrom_get_track_start_phys(cdrom_file *file, uint32_t track);
120 chd_file *cdrom_get_chd(cdrom_file *file);
121 
122 /* TOC utilities */
123 int cdrom_get_last_track(cdrom_file *file);
124 int cdrom_get_adr_control(cdrom_file *file, int track);
125 int cdrom_get_track_type(cdrom_file *file, int track);
126 const cdrom_toc *cdrom_get_toc(cdrom_file *file);
127 
128 /* extra utilities */
129 void cdrom_convert_type_string_to_track_info(const char *typestring, cdrom_track_info *info);
130 void cdrom_convert_type_string_to_pregap_info(const char *typestring, cdrom_track_info *info);
131 void cdrom_convert_subtype_string_to_track_info(const char *typestring, cdrom_track_info *info);
132 void cdrom_convert_subtype_string_to_pregap_info(const char *typestring, cdrom_track_info *info);
133 const char *cdrom_get_type_string(uint32_t trktype);
134 const char *cdrom_get_subtype_string(uint32_t subtype);
135 chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc);
136 chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc);
137 
138 // ECC utilities
139 bool ecc_verify(const uint8_t *sector);
140 void ecc_generate(uint8_t *sector);
141 void ecc_clear(uint8_t *sector);
142 
143 
144 
145 /***************************************************************************
146     INLINE FUNCTIONS
147 ***************************************************************************/
148 
msf_to_lba(uint32_t msf)149 static inline uint32_t msf_to_lba(uint32_t msf)
150 {
151 	return ( ((msf&0x00ff0000)>>16) * 60 * 75) + (((msf&0x0000ff00)>>8) * 75) + ((msf&0x000000ff)>>0);
152 }
153 
lba_to_msf(uint32_t lba)154 static inline uint32_t lba_to_msf(uint32_t lba)
155 {
156 	uint8_t m, s, f;
157 
158 	m = lba / (60 * 75);
159 	lba -= m * (60 * 75);
160 	s = lba / 75;
161 	f = lba % 75;
162 
163 	return ((m / 10) << 20) | ((m % 10) << 16) |
164 			((s / 10) << 12) | ((s % 10) <<  8) |
165 			((f / 10) <<  4) | ((f % 10) <<  0);
166 }
167 
168 // segacd needs it like this.. investigate
169 // Angelo also says PCE tracks often start playing at the
170 // wrong address.. related?
lba_to_msf_alt(int lba)171 static inline uint32_t lba_to_msf_alt(int lba)
172 {
173 	uint32_t ret = 0;
174 
175 	ret |= ((lba / (60 * 75))&0xff)<<16;
176 	ret |= (((lba / 75) % 60)&0xff)<<8;
177 	ret |= ((lba % 75)&0xff)<<0;
178 
179 	return ret;
180 }
181 
182 #endif // MAME_UTIL_CDROM_H
183